Ejemplo n.º 1
0
class BeaglesMainWindow(QMainWindow, ActionCallbacks):
    def __init__(self):
        super(BeaglesMainWindow, self).__init__()
        self.io = SharedFlagIO(subprogram=True)

        def createActions(actions: list):
            nonlocal self
            action = partial(newAction, self)
            cmd = 'global {0}; {0} = action("{1}", {2}, {3}, "{4}", "{5}", {6}, {7})'
            for act in actions:
                _str = act
                action_str = getStr(_str)
                shortcut, checkable, enabled = [
                    str(i) for i in self.actionFile[_str]
                ]
                shortcut = '"{}"'.format(
                    shortcut) if shortcut is not None else None
                detail = getStr(_str + "Detail")
                icon = _str
                callback = 'self.' + act
                cmd_string = cmd.format(_str, action_str, callback, shortcut,
                                        icon, detail, checkable, enabled)
                self.io.logger.debug(cmd_string)
                exec(cmd_string)

        with open('beagles/resources/actions/actions.json', 'r') as json_file:
            self.actionFile = json.load(json_file)
        actionList = list(self.actionFile.keys())
        createActions(actionList)
        self.setup()

    def menu(self, title, actions=None):
        menu = self.menuBar().addMenu(title)
        if actions:
            addActions(menu, actions)
        return menu

    def toolbar(self, title, actions=None):
        toolbar = ToolBar(title)
        toolbar.setObjectName(u'%sToolBar' % title)
        toolbar.setMovable(False)
        toolbar.setFixedHeight(32)
        toolbar.setIconSize(QSize(30, 30))
        toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        if actions:
            addActions(toolbar, actions)
        self.addToolBar(Qt.TopToolBarArea, toolbar)
        return toolbar

    def setup(self):
        self._beginner = True
        self.settings = Settings()
        self.settings.load()
        self.setupZoomWidget()
        self.setupActions()
        self.setupMenus()
        self.setupToolbar()
        self.setupFileDock()
        self.setupLabelDock()
        self.populateMenus()
        self.setupCanvasWidget()
        self.populateModeActions()

    def setupActions(self):
        # Auto saving : Enable auto saving if pressing next
        self.autoSaving = QAction(getStr('autoSaveMode'), self)
        self.autoSaving.setCheckable(True)
        self.autoSaving.setChecked(self.settings.get(SETTING_AUTO_SAVE, False))
        # Sync single class mode from PR#106
        self.singleClassMode = QAction(getStr('singleClsMode'), self)
        self.singleClassMode.setCheckable(True)
        self.singleClassMode.setChecked(
            self.settings.get(SETTING_SINGLE_CLASS, False))
        # Add option to enable/disable labels being displayed at the top of bounding boxes

        self.displayLabelOption = QAction(getStr('displayLabel'), self)
        self.displayLabelOption.setShortcut("Ctrl+Shift+P")
        self.displayLabelOption.setCheckable(True)
        self.displayLabelOption.setChecked(
            self.settings.get(SETTING_PAINT_LABEL, False))
        self.displayLabelOption.triggered.connect(self.togglePaintLabelsOption)

        self.drawSquaresOption = QAction('Draw Squares', self)
        self.drawSquaresOption.setShortcut('Ctrl+Shift+R')
        self.drawSquaresOption.setCheckable(True)
        self.drawSquaresOption.setChecked(
            self.settings.get(SETTING_DRAW_SQUARE, False))
        self.drawSquaresOption.triggered.connect(self.toggleDrawSquare)
        # noinspection PyUnresolvedReferences
        zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, setFitWin,
                       setFitWidth)
        # noinspection PyUnresolvedReferences
        self.actions = Struct(
            saveFile=saveFile,
            changeFormat=changeFormat,
            saveAs=saveAs,
            openFile=openFile,
            closeFile=closeFile,
            resetAll=resetAll,
            verifyImg=verifyImg,
            lineColor=boxLineColor,
            create=createShape,
            delBox=delBox,
            editLabel=editLabel,
            copySelectedShape=copySelectedShape,
            trainModel=trainModel,
            visualize=visualize,
            setCreateMode=setCreateMode,
            setEditMode=setEditMode,
            advancedMode=advancedMode,
            shapeLineColor=shapeLineColor,
            shapeFillColor=shapeFillColor,
            zoom=self.zoom,
            zoomIn=zoomIn,
            zoomOut=zoomOut,
            zoomOrg=zoomOrg,
            setFitWin=setFitWin,
            setFitWidth=setFitWidth,
            zoomActions=zoomActions,
            fileMenuActions=(openFile, openDir, impVideo, saveFile, saveAs,
                             commitAnnotatedFrames, trainModel, visualize,
                             closeFile, resetAll, close),
            beginner=(),
            advanced=(),
            editMenu=(editLabel, copySelectedShape, delBox, None, boxLineColor,
                      self.drawSquaresOption),
            beginnerContext=(createShape, editLabel, copySelectedShape,
                             delBox),
            advancedContext=(setCreateMode, setEditMode, editLabel,
                             copySelectedShape, delBox, shapeLineColor,
                             shapeFillColor),
            onLoadActive=(closeFile, createShape, setCreateMode, setEditMode),
            onShapesPresent=(saveAs, hideAll, showAll))

    # noinspection PyUnresolvedReferences
    def populateModeActions(self):
        if self.beginner():
            tool, menu = self.actions.beginner, self.actions.beginnerContext
        else:
            tool, menu = self.actions.advanced, self.actions.advancedContext
        self.tools.clear()
        addActions(self.tools, tool)
        self.canvas.menus[0].clear()
        addActions(self.canvas.menus[0], menu)
        self.menus.edit.clear()
        actions = (self.actions.create,) if self.beginner() \
            else (self.actions.setCreateMode, self.actions.setEditMode,
                  self.actions.verifyImg)
        addActions(self.menus.edit, actions + self.actions.editMenu)

    def setupMenus(self):
        labelMenu = QMenu()
        # noinspection PyUnresolvedReferences
        addActions(labelMenu, (editLabel, delBox))
        self.menus = Struct(file=self.menu('&File'),
                            edit=self.menu('&Edit'),
                            view=self.menu('&View'),
                            machine_learning=self.menu('&Machine Learning'),
                            help=self.menu('&Help'),
                            recentFiles=QMenu('Open &Recent'),
                            labelList=labelMenu)
        # noinspection PyUnresolvedAttribute
        self.menus.file.aboutToShow.connect(self.updateFileMenu)

    def populateMenus(self):
        labels = self.dock.toggleViewAction()
        labels.setText(getStr('showHide'))
        labels.setShortcut('Ctrl+Shift+L')
        # noinspection PyUnresolvedReferences
        addActions(self.menus.file,
                   (openFile, self.menus.recentFiles, openDir, changeSaveDir,
                    impVideo, openAnnotation, saveFile, changeFormat, saveAs,
                    closeFile, resetAll, close))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.help, (showTutorialDialog, showInfo))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.view,
                   (self.autoSaving, self.singleClassMode,
                    self.displayLabelOption, labels, advancedMode, None,
                    prevImg, nextImg, None, hideAll, showAll, None, zoomIn,
                    zoomOut, zoomOrg, None, setFitWin, setFitWidth))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.machine_learning,
                   (commitAnnotatedFrames, trainModel, visualize, None))

    def setupToolbar(self):
        self.tools = self.toolbar('Tools')
        # noinspection PyUnresolvedReferences
        self.actions.beginner = (openFile, openDir, changeSaveDir, saveFile,
                                 None, createShape, copySelectedShape, delBox,
                                 None, prevImg, nextImg, None, zoomIn,
                                 self.zoom, zoomOut, setFitWin, setFitWidth)

        # noinspection PyUnresolvedReferences
        self.actions.advanced = (openFile, saveFile, None, setCreateMode,
                                 setEditMode, verifyImg, None, hideAll,
                                 showAll, None, commitAnnotatedFrames,
                                 trainModel, visualize, impVideo)

    def setupFileDock(self):
        self.fileListWidget = QListWidget()
        self.fileListWidget.itemDoubleClicked.connect(
            self.fileitemDoubleClicked)
        filelistLayout = QVBoxLayout()
        filelistLayout.setContentsMargins(0, 0, 0, 0)
        filelistLayout.addWidget(self.fileListWidget)
        fileListContainer = QWidget()
        fileListContainer.setLayout(filelistLayout)
        self.filedock = QDockWidget(getStr('fileList'), self)
        self.filedock.setObjectName(getStr('files'))
        self.filedock.setWidget(fileListContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock)
        self.filedock.setFeatures(QDockWidget.DockWidgetFloatable)

    def setupLabelDock(self):
        listLayout = QVBoxLayout()
        listLayout.setContentsMargins(0, 0, 0, 0)
        self.editButton = QToolButton()
        self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        # noinspection PyUnresolvedReferences
        self.editButton.setDefaultAction(editLabel)
        # Create a widget for edit and diffc button
        self.difficultButton = QCheckBox(getStr('useDifficult'))
        self.difficultButton.setChecked(False)
        self.difficultButton.stateChanged.connect(self.buttonState)
        self.labelList = QListWidget()
        labelListContainer = QWidget()
        labelListContainer.setLayout(listLayout)
        self.labelList.itemActivated.connect(self.labelSelectionChanged)
        self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged)
        self.labelList.itemDoubleClicked.connect(self.editLabel)
        # Connect to itemChanged to detect checkbox changes.
        self.labelList.itemChanged.connect(self.labelItemChanged)
        listLayout.addWidget(self.labelList)
        self.dock = QDockWidget(getStr('boxLabelText'), self)
        self.dock.setObjectName(getStr('labels'))
        self.dock.setWidget(labelListContainer)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.dockFeatures = \
            QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
        # noinspection PyTypeChecker
        self.dock.setFeatures(self.dock.features() ^ self.dockFeatures)
        self.useDefaultLabelCheckbox = QCheckBox(getStr('useDefaultLabel'))
        self.useDefaultLabelCheckbox.setChecked(False)
        self.defaultLabelTextLine = QLineEdit()
        useDefaultLabelQHBoxLayout = QHBoxLayout()
        useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLabelCheckbox)
        useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine)
        useDefaultLabelContainer = QWidget()
        useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout)
        # Add some of widgets to listLayout
        listLayout.addWidget(self.editButton)
        listLayout.addWidget(self.difficultButton)
        listLayout.addWidget(useDefaultLabelContainer)
        self.lastLabel = None

    def setupZoomWidget(self):
        self.zoom = QWidgetAction(self)
        self.zoomWidget = ZoomWidget()
        self.zoom.setDefaultWidget(self.zoomWidget)
        self.zoomWidget.setEnabled(False)

    def setupCanvasWidget(self):
        action = partial(newAction, self)
        # Create and add a widget for showing current label items
        self.canvas = Canvas(parent=self)
        self.canvas.zoomRequest.connect(self.zoomRequest)
        self.canvas.setDrawingShapeToSquare(
            self.settings.get(SETTING_DRAW_SQUARE, False))
        self.canvas.scrollRequest.connect(self.scrollRequest)

        self.canvas.newShape.connect(self.newShape)
        self.canvas.shapeMoved.connect(self.setDirty)
        self.canvas.selectionChanged.connect(self.shapeSelectionChanged)
        self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive)
        # Custom context menu for the canvas widget:
        # noinspection PyUnresolvedReferences
        addActions(self.canvas.menus[0], self.actions.beginnerContext)
        addActions(self.canvas.menus[1],
                   (action('&Copy here', self.copyShape),
                    action('&Move here', self.moveShape)))

    def resetState(self):
        self.itemsToShapes.clear()
        self.shapesToItems.clear()
        self.labelList.clear()
        self.filePath = None
        self.imageData = None
        self.labelFile = None
        self.canvas.resetState()
        self.labelCoordinates.clear()

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Control:
            self.canvas.setDrawingShapeToSquare(False)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Control:
            # Draw rectangle if Ctrl is pressed
            self.canvas.setDrawingShapeToSquare(True)

    def resizeEvent(self, event):
        if self.canvas and not self.image.isNull() \
                and self.zoomMode != self.MANUAL_ZOOM:
            self.adjustScale()
        super(BeaglesMainWindow, self).resizeEvent(event)

    def closeEvent(self, event):
        for handler in self.io.logger.handlers:
            handler.doRollover()
        if not self.mayContinue():
            event.ignore()
        if self.tb_process.pid() > 0:
            self.tb_process.kill()
        settings = self.settings
        # If it loads images from dir, don't load it at the beginning
        if self.dirname is None:
            settings[SETTING_FILENAME] = self.filePath if self.filePath else ''
        else:
            settings[SETTING_FILENAME] = ''
        settings[SETTING_WIN_SIZE] = self.size()
        settings[SETTING_WIN_POSE] = self.pos()
        settings[SETTING_WIN_STATE] = self.saveState()
        settings[SETTING_LINE_COLOR] = self.lineColor
        settings[SETTING_FILL_COLOR] = self.fillColor
        settings[SETTING_RECENT_FILES] = self.recentFiles
        settings[SETTING_ADVANCE_MODE] = not self._beginner

        if self.defaultSaveDir and os.path.exists(self.defaultSaveDir):
            settings[SETTING_SAVE_DIR] = str(self.defaultSaveDir)
        else:
            settings[SETTING_SAVE_DIR] = ''

        if self.lastOpenDir and os.path.exists(self.lastOpenDir):
            settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir
        else:
            settings[SETTING_LAST_OPEN_DIR] = ''

        settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
        settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
        settings[SETTING_PAINT_LABEL] = self.displayLabelOption.isChecked()
        settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked()
        settings.save()
Ejemplo n.º 2
0
class MainWindowDirectLoad(QMainWindow):
    def __init__(self):
        #self.add_hello_context_menu()
        super(MainWindowDirectLoad, self).__init__()
        self.initUI()

    def initUI(self):
        self.desktopPath = path = os.path.expanduser("~/Desktop")

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('About')
        aboutAct = QAction('Things about us', self)
        fileMenu.addAction(aboutAct)
        aboutAct.triggered.connect(self.showAbout)
        self.statusBar()

        # Create a widget for tool dock
        # Add some of widgets to listLayout
        listLayout = QVBoxLayout()
        listLayout.setContentsMargins(0, 0, 0, 0)

        # Create and add a widget for showing current label items
        self.labelList = QListWidget()
        labelListContainer = QWidget()
        labelListContainer.setLayout(listLayout)
        listLayout.addWidget(self.labelList)

        self.dock = QDockWidget(u'工具', self)
        self.dock.setObjectName(u'Labels')
        self.dock.setWidget(labelListContainer)

        # create the labelList widget here
        self.labelList = myFileList(self)
        self.populate(self.labelList)

        self.fileListWidget = myFileList(self)
        self.populate(self.fileListWidget)
        filelistLayout = QVBoxLayout()
        filelistLayout.setContentsMargins(0, 0, 0, 0)
        filelistLayout.addWidget(self.fileListWidget)
        fileListContainer = QWidget()
        fileListContainer.setLayout(filelistLayout)
        self.filedock = QDockWidget(u'图片列表', self)
        self.filedock.setObjectName(u'Files')
        self.filedock.setWidget(fileListContainer)

        self.setCentralWidget(self.labelList)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.filedock)
        self.dockFeatures = QDockWidget.DockWidgetClosable \
                            | QDockWidget.DockWidgetFloatable
        self.dock.setFeatures(self.dock.features() ^ self.dockFeatures)
        self.filedock.setFeatures(self.filedock.features() ^ self.dockFeatures)

        self.setGeometry(400, 200, 950, 600)
        self.setWindowTitle('Desktop Backup')
        self.statusBar().showMessage("Program started.")

        self.show()

    def populate(self, fileList):
        for file in os.listdir(self.desktopPath):
            print(file)
            myQListWidgetItem = QListWidgetItem(fileList)
            myQListWidgetItem.setText(file)
            fileList.addItem(myQListWidgetItem)

    def showAbout(self):
        self.statusBar().showMessage("About us!!!")
        QMessageBox.question(self, 'About', "emmmmmmmmmmm", QMessageBox.Ok,
                             QMessageBox.Ok)