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)
示例#2
0
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()
示例#5
0
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)