class EmbeddedAuthWindowUI(object): def __init__(self, MainWin, config, credential_file, cookie_persistence, success_callback, failure_callback, log_level): # Main Window MainWin.setObjectName("EmbeddedAuthWindow") MainWin.setWindowIcon(QIcon(":/images/keys.png")) MainWin.setWindowTitle( MainWin.tr("DERIVA Authentication Agent %s" % VERSION)) MainWin.resize(1024, 745) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") self.authWidget = AuthWidget(MainWin, config, credential_file, cookie_persistence, log_level) self.authWidget.setSuccessCallback(success_callback) self.authWidget.setFailureCallback(failure_callback) self.authWidget.setObjectName("authWidget") self.verticalLayout.addWidget(self.authWidget) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class MainWindowUI(object): title = "Synspy Launcher" def __init__(self, MainWin): super(MainWindow).__init__() # Main Window MainWin.setObjectName("MainWindow") MainWin.setWindowTitle( MainWin.tr("%s %s" % (self.title, synspy_version))) MainWin.resize(800, 600) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") # Splitter for Worklist/Log self.splitter = QSplitter(Qt.Vertical) # Table View (Work list) self.workList = TableWidget(self.centralWidget) self.workList.setObjectName("tableWidget") self.workList.setStyleSheet(""" QTableWidget { border: 2px solid grey; border-radius: 5px; } """) self.workList.setEditTriggers( QAbstractItemView.NoEditTriggers ) # use NoEditTriggers to disable editing self.workList.setAlternatingRowColors(True) self.workList.setSelectionBehavior(QAbstractItemView.SelectRows) self.workList.setSelectionMode(QAbstractItemView.SingleSelection) self.workList.verticalHeader().setDefaultSectionSize( 18) # tighten up the row size self.workList.horizontalHeader().setStretchLastSection(True) # self.workList.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.workList.setSortingEnabled(True) # allow sorting self.workList.setContextMenuPolicy(Qt.ActionsContextMenu) self.workList.doubleClicked.connect(MainWin.on_actionLaunch_triggered) self.splitter.addWidget(self.workList) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([600, 100]) self.verticalLayout.addWidget(self.splitter) # Actions # Launch self.actionLaunch = QAction(MainWin) self.actionLaunch.setObjectName("actionLaunch") self.actionLaunch.setText(MainWin.tr("Launch Analysis")) self.actionLaunch.setToolTip( MainWin.tr("Launch the synspy-viewer process")) self.actionLaunch.setShortcut(MainWin.tr("Ctrl+L")) # Refresh self.actionRefresh = QAction(MainWin) self.actionRefresh.setObjectName("actionRefresh") self.actionRefresh.setText(MainWin.tr("Refresh Work List")) self.actionRefresh.setToolTip(MainWin.tr("Refresh the work list")) self.actionRefresh.setShortcut(MainWin.tr("Ctrl+R")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration Options")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+P")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip(MainWin.tr("Login to the server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+G")) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip(MainWin.tr("Logout of the server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) # Exit self.actionExit = QAction(MainWin) self.actionExit.setObjectName("actionExit") self.actionExit.setText(MainWin.tr("Exit")) self.actionExit.setToolTip(MainWin.tr("Exit the application")) self.actionExit.setShortcut(MainWin.tr("Ctrl+Z")) # Help self.actionHelp = QAction(MainWin) self.actionHelp.setObjectName("actionHelp") self.actionHelp.setText(MainWin.tr("Help")) self.actionHelp.setToolTip(MainWin.tr("Help")) self.actionHelp.setShortcut(MainWin.tr("Ctrl+H")) # Mark Incomplete self.markIncompleteAction = QAction('Mark Incomplete', self.workList) self.markIncompleteAction.triggered.connect(MainWin.markIncomplete) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Launch self.mainToolBar.addAction(self.actionLaunch) self.actionLaunch.setIcon(qApp.style().standardIcon( QStyle.SP_MediaPlay)) # Reload self.mainToolBar.addAction(self.actionRefresh) self.actionRefresh.setIcon(qApp.style().standardIcon( QStyle.SP_BrowserReload)) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogDetailedView)) # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon( QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon( QStyle.SP_DialogOkButton)) # Help #self.mainToolBar.addAction(self.actionHelp) self.actionHelp.setIcon(qApp.style().standardIcon( QStyle.SP_MessageBoxQuestion)) # Exit self.mainToolBar.addAction(self.actionExit) self.actionExit.setIcon(qApp.style().standardIcon( QStyle.SP_DialogCancelButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class AuthWindowUI(object): def __init__(self, MainWin): # Main Window MainWin.setObjectName("AuthWindow") MainWin.setWindowIcon(MainWin.window_icon) MainWin.setWindowTitle(MainWin.tr(MainWin.window_title)) MainWin.resize(1024, 860) self.config = MainWin.config self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = QTabWidget(MainWin) self.tabWidget.currentChanged.connect(MainWin.onTabChanged) self.tabWidget.tabCloseRequested.connect(MainWin.onTabClosed) self.tabWidget.setTabsClosable(True) # workaround for https://bugreports.qt.io/browse/QTBUG-58267 if "darwin" in sys.platform: self.tabWidget.setDocumentMode(True) # Splitter for log self.splitter = QSplitter(Qt.Vertical) self.splitter.addWidget(self.tabWidget) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([800, 100]) self.verticalLayout.addWidget(self.splitter) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.mainToolBar.setContextMenuPolicy(Qt.PreventContextMenu) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Servers self.serverWidget = QWidget(MainWin) self.serverLayout = QHBoxLayout() self.serverLabel = QLabel("Server:") self.serverLayout.addWidget(self.serverLabel) self.serverComboBox = QComboBox() self.serverComboBox.setEditable(True) self.serverComboBox.setDuplicatesEnabled(False) self.serverComboBox.setMinimumContentsLength(50) self.serverComboBox.currentIndexChanged.connect( MainWin.onServerListChanged) lineEdit = self.serverComboBox.lineEdit() lineEdit.returnPressed.connect(MainWin.on_actionAdd_triggered) self.serverLayout.addWidget(self.serverComboBox) self.serverWidget.setLayout(self.serverLayout) self.mainToolBar.addWidget(self.serverWidget) # Add self.actionAdd = QAction(MainWin) self.actionAdd.setObjectName("actionAdd") self.actionAdd.setText(MainWin.tr("Add")) self.actionAdd.setToolTip(MainWin.tr("Add to server list")) self.actionAdd.setShortcut(MainWin.tr("Ctrl+A")) # Remove self.actionRemove = QAction(MainWin) self.actionRemove.setObjectName("actionRemove") self.actionRemove.setText(MainWin.tr("Remove")) self.actionRemove.setToolTip(MainWin.tr("Remove from server list")) self.actionRemove.setShortcut(MainWin.tr("Ctrl+X")) # Show Token self.actionShowToken = QAction(MainWin) self.actionShowToken.setEnabled(False) self.actionShowToken.setObjectName("actionShowToken") self.actionShowToken.setText(MainWin.tr("Show Token")) self.actionShowToken.setToolTip( MainWin.tr("Display the current authentication token")) self.actionShowToken.setShortcut(MainWin.tr("Ctrl+S")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip( MainWin.tr("Login to the currently selected server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+L")) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip( MainWin.tr("Logout of the currently selected server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) # Add self.mainToolBar.addAction(self.actionAdd) self.actionAdd.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogNewFolder)) # Remove self.mainToolBar.addAction(self.actionRemove) self.actionRemove.setIcon(qApp.style().standardIcon( QStyle.SP_DialogDiscardButton)) # Show Token self.mainToolBar.addAction(self.actionShowToken) self.actionShowToken.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogInfoView)) self.mainToolBar.addSeparator() # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addSeparator() self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon( QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addSeparator() self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon( QStyle.SP_DialogOkButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # configure logging self.logTextBrowser.widget.log_update_signal.connect(MainWin.updateLog) self.logTextBrowser.setFormatter( logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.getLogger().addHandler(self.logTextBrowser) logging.getLogger().setLevel(logging.INFO) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class MainWindow(QMainWindow): def __init__(self): super().__init__() #adjusting main window self.resize(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT) self.move(0, 0) #setting scaling factor = 1 self.zoom = 1 #initializing and registering centeral widget self.centeral_widget = QWidget(self) self.setCentralWidget(self.centeral_widget) #initializing frame view self.frame_panel = DLabel(self.centeral_widget, self) # position frame panel self.frame_panel.move(FRAME_MARGIN_LEFT, FRAME_MARGIN_TOP) # set initial image self.frame_panel.setPixmap(QPixmap("initial.png")) #fur testing self.frame_panel.content = cv2.imread("initial.png") # enabling custom context menu self.setContextMenuPolicy(Qt.CustomContextMenu) #initializing menubar self.menubar = QMenuBar(self) #adding menu options self.file_menu = QMenu(self.menubar) self.zoom_menu = QMenu(self.menubar) self.marker_menu = QMenu(self.menubar) self.bounding_boxes = QMenu(self.menubar) #registering menubar self.menubar.move(0, 0) self.menubar.setDefaultUp(False) self.setMenuBar(self.menubar) #initializing and registering statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) #add permanent frame lable to statusbar self.statusbar.frame_lable = QLabel(self) self.statusbar.frame_lable.setText("") self.statusbar.frame_lable.resize(100, 50) self.statusbar.frame_lable.move(DEFAULT_WINDOW_WIDTH - 100, DEFAULT_WINDOW_HEIGHT - 37) # set initail status tip self.statusbar.setStatusTip("Please choose a video file to begin") self.initialize_submenus() #assign visual texts to window, menus and submenus self.setTexts() #initailize video path self.vid_path = "" self.vid = False #adding slider for quick seek self.slider = QSlider(self.centeral_widget) #setting slider geometery self.slider.resize(DEFAULT_WINDOW_WIDTH - SLIDER_MARGINS * 2, SLIDER_HEIGHT) self.slider.move( SLIDER_MARGINS, DEFAULT_WINDOW_HEIGHT - STATUSBAR_HEIGHT - SLIDER_HEIGHT - SLIDER_MARGINS) #setting orientation self.slider.setOrientation(Qt.Horizontal) #connecting mouse event self.slider.valueChanged.connect(self.moveSliderToClickedPosition) self.slider.setDisabled(True) # initialize context menu self.initContextMenu() # initializing mongo client and db self.database_client = MongoClient() self.db = self.database_client.fish # initializing collection self.collection = False def initContextMenu(self): # initialize custom context menu and submenu self.context_menu = QMenu(self) self.context_sub_menu = QMenu('Class', self) # create a delete action self.delete_action = QAction('Delete', self) self.delete_action.triggered.connect(self.frame_panel.deleteMarker) # create get lable action self.ask_lable = QAction('Ask Lable', self) self.ask_lable.triggered.connect(self.frame_panel.getLable) # adding dictionary for reverse search self.classes = {} # initializing class group self.class_group = QActionGroup(self) # adding submenu actions for item in CONFIGURED_CLASSES: self.classes[item] = QAction(item, self) self.classes[item].setCheckable(True) self.class_group.addAction(self.classes[item]) # connecting group to handlers and setting default class self.class_group.triggered.connect(self.frame_panel.toggleMarkerClass) self.classes[CONFIGURED_CLASSES[0]].setChecked(True) # add delete action to menu self.context_menu.addAction(self.delete_action) # add ask lable action to menu self.context_menu.addAction(self.ask_lable) # add class actions to submenu self.context_sub_menu.addActions(self.class_group.actions()) # regester submenu to menu self.context_menu.addMenu(self.context_sub_menu) def initialize_submenus(self): #intializing open submenu self.open_submenu = QAction(self) self.open_submenu.setShortcut('Ctrl+F') self.open_submenu.setStatusTip("Open") self.open_submenu.triggered.connect(self.selectFile) # intializing export submenu self.export_submenu = QAction(self) self.export_submenu.setShortcut('Ctrl+E') self.export_submenu.setStatusTip("Export") self.export_submenu.triggered.connect(self.exportImages) self.export_submenu.setDisabled(True) # intializing export submenu self.init_submenu = QAction(self) self.init_submenu.setShortcut('Ctrl+I') self.init_submenu.setStatusTip("Initialize") self.init_submenu.triggered.connect(self.initializeWithAlgorithm) self.init_submenu.setDisabled(True) #initializing options for zoom menu self.p50_submenu = QAction(self) self.p50_submenu.setStatusTip("50%") self.p50_submenu.setCheckable(True) self.p50_submenu.val = 0.5 self.p100_submenu = QAction(self) self.p100_submenu.setStatusTip("100%") self.p100_submenu.setCheckable(True) self.p100_submenu.val = 1.0 self.p150_submenu = QAction(self) self.p150_submenu.setStatusTip("150%") self.p150_submenu.setCheckable(True) self.p150_submenu.val = 1.5 self.p200_submenu = QAction(self) self.p200_submenu.setStatusTip("200%") self.p200_submenu.setCheckable(True) self.p200_submenu.val = 2.0 self.zoom_group = QActionGroup(self) self.zoom_group.addAction(self.p50_submenu) self.zoom_group.addAction(self.p100_submenu) self.zoom_group.addAction(self.p150_submenu) self.zoom_group.addAction(self.p200_submenu) self.p100_submenu.setChecked(True) self.zoom_group.setDisabled(True) self.zoom_group.triggered.connect(self.changeZoom) #registering file submenus self.file_menu.addAction(self.open_submenu) # registering bounding box submenus self.bounding_boxes.addAction(self.export_submenu) self.bounding_boxes.addAction(self.init_submenu) #registering zoom submenus self.zoom_menu.addActions(self.zoom_group.actions()) #registering menus to menubar self.menubar.addAction(self.file_menu.menuAction()) self.menubar.addAction(self.zoom_menu.menuAction()) self.menubar.addAction(self.bounding_boxes.menuAction()) def setTexts(self): self.setWindowTitle("FIBVID Analyser") #file menu self.file_menu.setTitle("File") self.open_submenu.setText("Open") self.bounding_boxes.setTitle("Boxes") # bouding boxes menu self.export_submenu.setText("Export as Images") self.init_submenu.setText("Initialize with Model") #zoom menu self.zoom_menu.setTitle("Zoom") self.p50_submenu.setText("50%") self.p100_submenu.setText("100%") self.p100_submenu.setText("100%") self.p150_submenu.setText("150%") self.p200_submenu.setText("200%") def selectFile(self): # get the file browser pop-up path, _ = QFileDialog.getOpenFileName(self.statusbar, 'Select Video File', '/home') self.vid_path = path self.initVideo() def exportImages(self): cursor_pos = self.vid.get(cv2.CAP_PROP_POS_FRAMES) markers = self.collection.find({}) markers.batch_size(1000000000) markers = [marker for marker in markers] height, width = self.current_frame.shape[0:2] empty = np.zeros((height, width, 3), np.uint8) center = (int(width / 2), int(height / 2)) i = 0 last = 0 for marker in markers: progress = int(i * 100 / len(markers)) img = empty.copy() cv2.circle(img, center, 100, (255, 255, 255)) cv2.circle(img, center, progress, (255, 255, 255), -1) print(progress) self.setFrame(img) cv2.waitKey(1) last = progress box = [marker["start_pos"], marker["end_pos"]] rbox = RBox.fromPointBoundingBox(box) self.vid.set(cv2.CAP_PROP_POS_FRAMES, marker["frame_no"] - 1) rtt, frame = self.vid.read() patch = rbox.extractPatchFromImage(frame, square=True) name = str(marker["_id"]) name = "./exports/" + name + ".png" cv2.imwrite(name, patch) i += 1 self.initVideo() def showProgress(self, progress, fps): height, width = self.current_frame.shape[0:2] empty = np.zeros((height, width, 3), np.uint8) center = (int(width / 2), int(height / 2)) cv2.circle(empty, center, progress, (255, 255, 255), -1) empty[center[1] - 100:center[1] + 100, center[0] - 100:center[0] + 100] = cv2.bitwise_and(empty[center[1] - 100:center[1] + 100, center[0] - 100:center[0] + 100], empty[center[1] - 100:center[1] + 100, center[0] - 100:center[0] + 100], mask=self.coin) cv2.circle(empty, center, 98, (255, 255, 255)) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(empty, "FPS: {}".format(fps), (10, 20), font, 0.5, (255, 255, 255), 1, cv2.LINE_AA) self.setFrame(empty) def initializeWithAlgorithm(self): self.initVideo() self.analyser = RuntimeABGSC(vid_path=self.vid_path) # read progress image coin = cv2.imread("fish_coin_inv.png") self.coin = np.uint8( cv2.cvtColor(coin, cv2.COLOR_RGB2GRAY) > 150) * 255 # empty collection self.collection.delete_many({}) # frame cout frame_count = self.vid.get(cv2.CAP_PROP_FRAME_COUNT) counter = 0 # disable scroll bar self.slider.setDisabled(True) # disable video self.vid = False markers = [] while (self.analyser.status): # while video is not complete start = time() self.analyser.process(show_output=False) end = time() # increment counter counter += 1 # calculate fps fps = int(1 / (end - start)) # show progress in display window progress = int(counter * 100 / frame_count) self.showProgress(progress, fps) for box in self.analyser.final_boxes: start_pos = (int(box[0][0]), int(box[0][1])) end_pos = (int(box[1][0]), int(box[1][1])) # add resultant marker to markers of current frame marker = Marker(start_pos, end_pos, counter, CONFIGURED_CLASSES[3]) markers.append(marker.toDictionary()) #self.frame_panel.markers.append(marker) # add markers to database self.collection.insert_many(markers) self.initVideo() def changeZoom(self): # get selected option's value zoom = self.zoom_group.checkedAction().val # reset frame according to new scaling self.resetFrame(zoom) def resetFrame(self, zoom): self.zoom = zoom self.frame_panel.zoom = zoom #resize frame panel self.frame_panel.resize(self.vid_height * zoom, self.vid_width * zoom) #resize window if dynamic scaling is enabled if DYNAMIC_WINDOW_SCALING: self.resize( self.vid_height * zoom + FRAME_MARGIN_LEFT + FRAME_MARGIN_RIGHT, self.vid_width * zoom + FRAME_MARGIN_TOP + FRAME_MARGIN_BOTTOM) # reposition slider self.slider.move( SLIDER_MARGINS, self.vid_width * zoom - (SLIDER_HEIGHT + SLIDER_MARGINS)) # resize slider self.slider.resize(self.width() - SLIDER_MARGINS * 2, SLIDER_HEIGHT) # reposition frame lable self.statusbar.frame_lable.move(self.width() - 100, self.height() - 37) self.currentFrame() def initVideo(self): # reset zoom self.zoom = 1.0 self.vid = cv2.VideoCapture() # load selected video rtt = self.vid.open(self.vid_path) # clear slider self.slider.disconnect() # seek slider to start self.slider.setValue(0) self.slider.valueChanged.connect(self.moveSliderToClickedPosition) if rtt == False: if self.vid_path == "": self.statusbar.setStatusTip("No file selected") else: self.statusbar.setStatusTip("Error: Format not supported") # disalbe zoom options self.zoom_group.setDisabled(True) # clean video from memory self.vid = False # disable slider self.slider.setDisabled(True) return else: self.statusbar.setStatusTip("Ready") # set collection self.collection = self.db[self.vid_path] # seek to start self.vid.set(cv2.CAP_PROP_POS_FRAMES, 0) # read first frame rtt, frame = self.vid.read() # extract height and width of video self.vid_width, self.vid_height, self.vid_depth = np.shape(frame) self.vid_width *= self.zoom self.vid_height *= self.zoom self.current_frame = frame.copy() # resize frame view according to the video's geometery self.frame_panel.resize(self.vid_height, self.vid_width) # getting current frame number self.frame_no = self.vid.get(cv2.CAP_PROP_POS_FRAMES) # adding frame no to status tip self.statusbar.frame_lable.setText("Frame: {0}".format( "%05.0i" % int(self.frame_no))) # reset frame to start self.resetFrame(self.zoom) #enable zoom options self.zoom_group.setDisabled(False) #enable slider self.slider.setDisabled(False) # enable algorithmBasedInitialization self.init_submenu.setDisabled(False) self.export_submenu.setDisabled(False) # plot the current frame on canvas self.frame_panel.content = frame.copy() self.setImageFrame(frame) # seek slider to start self.moveSliderToPosition(0) def setImageFrame(self, frame): # load image with markers self.frame_panel.loadMarkers() self.frame_panel.reDraw() self.frame_panel.dragStatus = "Ended" def setFrame(self, frame): # convert raw frame to QPixmap and set it on frame_panel frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) self.frame_panel.setPixmap( QPixmap.fromImage( QImage(frame, self.vid_height * self.zoom, self.vid_width * self.zoom, self.vid_height * self.zoom * self.vid_depth, QImage.Format_RGB888))) def nextFrame(self): # read next frame of video as Image rtt, frame = self.vid.read() if rtt: self.frame_panel.content = frame.copy() self.current_frame = frame.copy() # check if there is a next frame and convert cv Image to Pixmap frame = cv2.resize(frame, None, fx=self.zoom, fy=self.zoom, interpolation=cv2.INTER_CUBIC) # initializing markers on frame_panel self.frame_panel.markers = [] # getting current frame number self.frame_no = self.vid.get(cv2.CAP_PROP_POS_FRAMES) # clear slider self.slider.disconnect() # seek slider to start self.slider.setValue(self.frame_no * 100 / self.vid.get(cv2.CAP_PROP_FRAME_COUNT)) self.slider.valueChanged.connect(self.moveSliderToClickedPosition) self.setImageFrame(frame) #adding frame no to status tip self.statusbar.frame_lable.setText("Frame: {0}".format( "%05.0i" % int(self.frame_no))) def previousFrame(self): # set current frame number to 2 frames backward self.vid.set(cv2.CAP_PROP_POS_FRAMES, self.vid.get(cv2.CAP_PROP_POS_FRAMES) - 2) # get next frame self.nextFrame() def currentFrame(self): self.frame_panel.content = self.current_frame.copy() # check if there is a next frame and convert cv Image to Pixmap frame = cv2.resize(self.current_frame.copy(), None, fx=self.zoom, fy=self.zoom, interpolation=cv2.INTER_CUBIC) self.setImageFrame(frame) def keyPressEvent(self, event): # don't do anything if no video is selected if self.vid == False: return # Key press event on window if type(event) == QKeyEvent and event.key() == Qt.Key_D: # navigate forward if D pressed self.nextFrame() if type(event) == QKeyEvent and event.key() == Qt.Key_A: # navigate backward if A pressed self.previousFrame() if type(event) == QKeyEvent and event.key() == Qt.Key_Plus: # zoom in self.resetFrame(self.zoom + 1) if type(event) == QKeyEvent and event.key() == Qt.Key_Minus: # zoom out if zoom factor is greater than 1 if (self.zoom > 1.0): self.resetFrame(self.zoom - 1) def moveSliderToClickedPosition(self): # enable slider to move with mouse click # get click position relative to slider click_position = self.slider.mapFromGlobal(QCursor.pos()).x() self.moveSliderToPosition(click_position) def moveSliderToPosition(self, position): # set position of slider to position by setting its value slider_completion_ratio = position / self.slider.width() self.slider.setValue(slider_completion_ratio * 100) # seek video accordingly if self.vid: self.vid.set( cv2.CAP_PROP_POS_FRAMES, self.vid.get(cv2.CAP_PROP_FRAME_COUNT) * slider_completion_ratio) # refresh frame self.nextFrame()
class MainWindowUI(object): def setup_ui(self, MainWin): # Main Window MainWin.setObjectName("MainWindow") MainWin.setWindowTitle(MainWin.tr("BDBag")) MainWin.resize(680, 600) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") # Actions # Create/Update self.actionCreateOrUpdate = QAction(MainWin) self.actionCreateOrUpdate.setObjectName("actionCreateOrUpdate") # Revert self.actionRevert = QAction(MainWin) self.actionRevert.setObjectName("actionRevert") self.actionRevert.setText(MainWin.tr("Revert")) self.actionRevert.setToolTip( MainWin.tr("Revert a bag directory back to a normal directory.")) self.actionRevert.setShortcut(MainWin.tr("Ctrl+R")) # Validate Fast self.actionValidateFast = QAction(MainWin) self.actionValidateFast.setObjectName("actionValidateFast") self.actionValidateFast.setText(MainWin.tr("Validate: Fast")) self.actionValidateFast.setToolTip( MainWin. tr("Perform fast validation by checking the payload file counts and sizes against the Payload-0xum " "value from the bag manifest")) self.actionValidateFast.setShortcut(MainWin.tr("Ctrl+F")) # Validate Full self.actionValidateFull = QAction(MainWin) self.actionValidateFull.setObjectName("actionValidateFull") self.actionValidateFull.setText(MainWin.tr("Validate: Full")) self.actionValidateFull.setToolTip( MainWin. tr("Perform full validation by calculating checksums for all files and comparing them against " "entries in the bag manifest(s)")) self.actionValidateFull.setShortcut(MainWin.tr("Ctrl+V")) # Fetch Missing self.actionFetchMissing = QAction(MainWin) self.actionFetchMissing.setObjectName("actionFetchMissing") self.actionFetchMissing.setText(MainWin.tr("Fetch: Missing")) self.actionFetchMissing.setToolTip( MainWin. tr("Fetch only those remote files that are not already present in the bag" )) self.actionFetchMissing.setShortcut(MainWin.tr("Ctrl+M")) # Fetch All self.actionFetchAll = QAction(MainWin) self.actionFetchAll.setObjectName("actionFetchAll") self.actionFetchAll.setText(MainWin.tr("Fetch: All")) self.actionFetchAll.setToolTip( MainWin. tr("Fetch all remote files, even if they are already present in the bag" )) self.actionFetchAll.setShortcut(MainWin.tr("Ctrl+A")) # Archive ZIP self.actionArchiveZIP = QAction(MainWin) self.actionArchiveZIP.setObjectName("actionArchiveZIP") self.actionArchiveZIP.setText(MainWin.tr("Archive: ZIP")) self.actionArchiveZIP.setToolTip( MainWin.tr("Create a ZIP format archive of the bag.")) self.actionArchiveZIP.setShortcut(MainWin.tr("Ctrl+Z")) # Archive TGZ self.actionArchiveTGZ = QAction(MainWin) self.actionArchiveTGZ.setObjectName("actionArchiveTGZ") self.actionArchiveTGZ.setText(MainWin.tr("Archive: TGZ")) self.actionArchiveTGZ.setToolTip( MainWin.tr("Create a TAR/GZIP format archive of the bag.")) self.actionArchiveTGZ.setShortcut(MainWin.tr("Ctrl+T")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration options.")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+O")) # Cancel self.actionCancel = QAction(MainWin) self.actionCancel.setObjectName("actionCancel") self.actionCancel.setText(MainWin.tr("Cancel")) self.actionCancel.setToolTip( MainWin.tr("Cancel the current background task.")) self.actionCancel.setShortcut(MainWin.tr("Ctrl+C")) # About self.actionAbout = QAction(MainWin) self.actionAbout.setObjectName("actionAbout") self.actionAbout.setText(MainWin.tr("About")) self.actionAbout.setToolTip(MainWin.tr("Show version information.")) self.actionAbout.setShortcut(MainWin.tr("Ctrl+B")) # Tree View self.treeView = QTreeView(self.centralWidget) self.treeView.setObjectName("treeView") self.treeView.setStyleSheet(""" QTreeView { border: 2px solid grey; border-radius: 5px; } """) self.verticalLayout.addWidget(self.treeView) # Log Widget self.logTextBrowser = log_widget.QPlainTextEditLogger( self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.verticalLayout.addWidget(self.logTextBrowser.widget) # Menu Bar self.menuBar = QMenuBar(MainWin) self.menuBar.setObjectName("menuBar") MainWin.setMenuBar(self.menuBar) # Bag Menu self.menuBag = QMenu(self.menuBar) self.menuBag.setObjectName("menuBag") self.menuBag.setTitle(MainWin.tr("Bag")) self.menuBar.addAction(self.menuBag.menuAction()) self.menuBag.addAction(self.actionCreateOrUpdate) self.menuBag.addAction(self.actionRevert) self.menuBag.addAction(self.actionCancel) self.menuBag.addAction(self.actionOptions) # Fetch Menu self.menuFetch = QMenu(self.menuBag) self.menuFetch.setObjectName("menuFetch") self.menuFetch.setTitle(MainWin.tr("Fetch")) self.menuFetch.addAction(self.actionFetchMissing) self.menuFetch.addAction(self.actionFetchAll) self.menuBag.addAction(self.menuFetch.menuAction()) # Validate Menu self.menuValidate = QMenu(self.menuBag) self.menuValidate.setObjectName("menuValidate") self.menuValidate.setTitle(MainWin.tr("Validate")) self.menuValidate.addAction(self.actionValidateFast) self.menuValidate.addAction(self.actionValidateFull) self.menuBag.addAction(self.menuValidate.menuAction()) # Archive Menu self.menuArchive = QMenu(self.menuBag) self.menuArchive.setObjectName("menuArchive") self.menuArchive.setTitle(MainWin.tr("Archive")) self.menuArchive.addAction(self.actionArchiveZIP) self.menuArchive.addAction(self.actionArchiveTGZ) self.menuBag.addAction(self.menuArchive.menuAction()) # Help Menu self.menuHelp = QMenu(self.menuBar) self.menuHelp.setObjectName("menuHelp") self.menuHelp.setTitle(MainWin.tr("Help")) self.menuHelp.addAction(self.actionAbout) self.menuBar.addAction(self.menuHelp.menuAction()) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Create/Update self.mainToolBar.addAction(self.actionCreateOrUpdate) self.actionCreateOrUpdate.setIcon( self.actionCreateOrUpdate.parentWidget().style().standardIcon( getattr(QStyle, "SP_FileDialogNewFolder"))) # Revert self.mainToolBar.addAction(self.actionRevert) self.actionRevert.setIcon( self.actionRevert.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogOkButton"))) # Fetch self.mainToolBar.addAction(self.actionFetchMissing) self.actionFetchMissing.setIcon( self.actionFetchMissing.parentWidget().style().standardIcon( getattr(QStyle, "SP_ArrowDown"))) self.mainToolBar.addAction(self.actionFetchAll) self.actionFetchAll.setIcon( self.actionFetchAll.parentWidget().style().standardIcon( getattr(QStyle, "SP_ArrowDown"))) # Validate self.mainToolBar.addAction(self.actionValidateFast) self.actionValidateFast.setIcon( self.actionValidateFast.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogApplyButton"))) self.mainToolBar.addAction(self.actionValidateFull) self.actionValidateFull.setIcon( self.actionValidateFull.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogApplyButton"))) # Archive self.mainToolBar.addAction(self.actionArchiveZIP) self.actionArchiveZIP.setIcon( self.actionArchiveZIP.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogSaveButton"))) self.mainToolBar.addAction(self.actionArchiveTGZ) self.actionArchiveTGZ.setIcon( self.actionArchiveTGZ.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogSaveButton"))) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon( self.actionOptions.parentWidget().style().standardIcon( getattr(QStyle, "SP_FileDialogDetailedView"))) # Cancel self.mainToolBar.addAction(self.actionCancel) self.actionCancel.setIcon( self.actionCancel.parentWidget().style().standardIcon( getattr(QStyle, "SP_BrowserStop"))) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # Progress Bar self.progressBar = QProgressBar(self.centralWidget) self.progressBar.setValue(0) self.progressBar.setTextVisible(False) self.progressBar.setObjectName("progressBar") self.progressBar.setStyleSheet(""" QProgressBar { border: 2px solid grey; border-radius: 5px; text-align: center; } QProgressBar::chunk { background-color: darkblue; width: 10px; margin: 0.5px; } """) self.verticalLayout.addWidget(self.progressBar) # finalize UI setup self.toggleCreateOrUpdate(MainWin) QMetaObject.connectSlotsByName(MainWin) def toggleCreateOrUpdate(self, MainWin): if MainWin.isBag: self.actionCreateOrUpdate.setText(MainWin.tr("Update")) self.actionCreateOrUpdate.setToolTip( MainWin.tr("Update a bag in an existing directory")) self.actionCreateOrUpdate.setShortcut(MainWin.tr("Ctrl+U")) else: self.actionCreateOrUpdate.setText(MainWin.tr("Create")) self.actionCreateOrUpdate.setToolTip( MainWin.tr("Create a new bag from an existing directory")) self.actionCreateOrUpdate.setShortcut(MainWin.tr("Ctrl+N"))
class UploadWindowUI(object): title = "DERIVA File Uploader" def __init__(self, MainWin): # Main Window MainWin.setObjectName("UploadWindow") MainWin.setWindowTitle(MainWin.tr(self.title)) MainWin.resize(1024, 768) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QHBoxLayout() self.pathLabel = QLabel("Directory:") self.horizontalLayout.addWidget(self.pathLabel) self.pathTextBox = QLineEdit() self.pathTextBox.setReadOnly(True) self.horizontalLayout.addWidget(self.pathTextBox) self.browseButton = QPushButton("Browse", self.centralWidget) self.browseButton.clicked.connect(MainWin.on_actionBrowse_triggered) self.horizontalLayout.addWidget(self.browseButton) self.verticalLayout.addLayout(self.horizontalLayout) # Splitter for Upload list/Log self.splitter = QSplitter(Qt.Vertical) # Table View (Upload list) self.uploadList = TableWidget(self.centralWidget) self.uploadList.setObjectName("uploadList") self.uploadList.setStyleSheet( """ QTableWidget { border: 2px solid grey; border-radius: 5px; } """) self.uploadList.setEditTriggers(QAbstractItemView.NoEditTriggers) # use NoEditTriggers to disable editing self.uploadList.setAlternatingRowColors(True) self.uploadList.setSelectionBehavior(QAbstractItemView.SelectRows) self.uploadList.setSelectionMode(QAbstractItemView.NoSelection) self.uploadList.verticalHeader().setDefaultSectionSize(18) # tighten up the row size self.uploadList.horizontalHeader().setStretchLastSection(True) self.uploadList.setSortingEnabled(True) # allow sorting self.splitter.addWidget(self.uploadList) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet( """ QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([400, 200]) self.verticalLayout.addWidget(self.splitter) # Actions # Browse self.actionBrowse = QAction(MainWin) self.actionBrowse.setObjectName("actionBrowse") self.actionBrowse.setText(MainWin.tr("Browse")) self.actionBrowse.setToolTip(MainWin.tr("Set the upload directory")) self.actionBrowse.setShortcut(MainWin.tr("Ctrl+B")) # Upload self.actionUpload = QAction(MainWin) self.actionUpload.setObjectName("actionUpload") self.actionUpload.setText(MainWin.tr("Upload")) self.actionUpload.setToolTip(MainWin.tr("Upload files")) self.actionUpload.setShortcut(MainWin.tr("Ctrl+L")) self.actionUpload.setEnabled(False) # Rescan self.actionRescan = QAction(MainWin) self.actionRescan.setObjectName("actionRescan") self.actionRescan.setText(MainWin.tr("Rescan")) self.actionRescan.setToolTip(MainWin.tr("Rescan the upload directory")) self.actionRescan.setShortcut(MainWin.tr("Ctrl+R")) self.actionRescan.setEnabled(False) # Cancel self.actionCancel = QAction(MainWin) self.actionCancel.setObjectName("actionCancel") self.actionCancel.setText(MainWin.tr("Cancel")) self.actionCancel.setToolTip(MainWin.tr("Cancel any upload(s) in-progress")) self.actionCancel.setShortcut(MainWin.tr("Ctrl+C")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration Options")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+P")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip(MainWin.tr("Login to the server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+G")) self.actionLogin.setEnabled(False) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip(MainWin.tr("Logout of the server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) self.actionLogout.setEnabled(False) # Exit self.actionExit = QAction(MainWin) self.actionExit.setObjectName("actionExit") self.actionExit.setText(MainWin.tr("Exit")) self.actionExit.setToolTip(MainWin.tr("Exit the application")) self.actionExit.setShortcut(MainWin.tr("Ctrl+Z")) # Help self.actionHelp = QAction(MainWin) self.actionHelp.setObjectName("actionHelp") self.actionHelp.setText(MainWin.tr("Help")) self.actionHelp.setToolTip(MainWin.tr("Help")) self.actionHelp.setShortcut(MainWin.tr("Ctrl+H")) # Menu Bar """ self.menuBar = QMenuBar(MainWin) self.menuBar.setObjectName("menuBar") MainWin.setMenuBar(self.menuBar) self.menuBar.setStyleSheet( "QMenuBar{font-family: Arial;font-style: normal;font-size: 10pt;font-weight: bold;};") """ # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.mainToolBar.setContextMenuPolicy(Qt.PreventContextMenu) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Upload self.mainToolBar.addAction(self.actionUpload) self.actionUpload.setIcon(qApp.style().standardIcon(QStyle.SP_FileDialogToParent)) # Rescan self.mainToolBar.addAction(self.actionRescan) self.actionRescan.setIcon(qApp.style().standardIcon(QStyle.SP_BrowserReload)) # Cancel self.mainToolBar.addAction(self.actionCancel) self.actionCancel.setIcon(qApp.style().standardIcon(QStyle.SP_BrowserStop)) self.actionCancel.setEnabled(False) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon(qApp.style().standardIcon(QStyle.SP_FileDialogDetailedView)) # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon(QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon(QStyle.SP_DialogOkButton)) # Help #self.mainToolBar.addAction(self.actionHelp) self.actionHelp.setIcon(qApp.style().standardIcon(QStyle.SP_MessageBoxQuestion)) # Exit self.mainToolBar.addAction(self.actionExit) self.actionExit.setIcon(qApp.style().standardIcon(QStyle.SP_DialogCancelButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # configure logging self.logTextBrowser.widget.log_update_signal.connect(MainWin.updateLog) self.logTextBrowser.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.getLogger().addHandler(self.logTextBrowser) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)