示例#1
0
    def init_splitter(self):
        self.frame = QFrame()
        self.frame.setFrameShape(QFrame.StyledPanel)
        hbox = QHBoxLayout()  # here should be no 'self' argument
        self.browser_widget = bv.BrowserWidget(self)
        self.top_splitter = QSplitter(Qt.Horizontal)
        frame = QFrame()
        layout = QVBoxLayout()
        for addon in self.addon_list:
            layout.addWidget(addon)
            addon.hide()
        frame.setLayout(layout)        
        self.top_splitter.addWidget(frame)
        self.current_addon = self.addon_list[0]
        self.current_addon.show_itself()
        self.top_splitter.addWidget(self.browser_widget)
        self.top_splitter.setSizes([100, 200])

        handle_width = 6

        # https://stackoverflow.com/questions/2545577/qsplitter-becoming-undistinguishable-between-qwidget-and-qtabwidget
        self.top_splitter.setOpaqueResize(False)
        self.top_splitter.setChildrenCollapsible(False)
        self.top_splitter.setHandleWidth(handle_width)

        splitter2 = QSplitter(Qt.Vertical)
        splitter2.addWidget(self.top_splitter)
        splitter2.addWidget(self.jupyter_widget)
        splitter2.setOpaqueResize(False)
        splitter2.setChildrenCollapsible(False)
        splitter2.setHandleWidth(handle_width)

        hbox.addWidget(splitter2)

        self.frame.setLayout(hbox)
示例#2
0
    def decorate(splitter: QSplitter, index: int = 1):

        gripLength = 35
        gripWidth = 1  # may need to be 1 or 2 depending on theme
        gripSpacing = 0
        grips = 3

        splitter.setOpaqueResize(False)
        splitter.setChildrenCollapsible(False)
        splitter.setHandleWidth(7)
        handle = splitter.handle(index)
        orientation = splitter.orientation()
        layout = QHBoxLayout(handle)
        layout.setSpacing(gripSpacing)
        layout.setContentsMargins(0, 0, 0, 0)

        if orientation == Qt.Horizontal:
            for i in range(grips):
                line = QFrame(handle)
                line.setMinimumSize(gripWidth, gripLength)
                line.setMaximumSize(gripWidth, gripLength)
                line.setLineWidth(gripWidth)
                line.setFrameShape(line.StyledPanel)
                line.setStyleSheet("border: 1px solid lightgray;")
                layout.addWidget(line)
        else:
            # center the vertical grip by adding spacers before and after
            layout.addStretch()
            vBox = QVBoxLayout()

            for i in range(grips):
                line = QFrame(handle)
                line.setMinimumSize(gripLength, gripWidth)
                line.setMaximumSize(gripLength, gripWidth)
                line.setFrameShape(line.StyledPanel)
                line.setStyleSheet("border: 1px solid lightgray;")
                vBox.addWidget(line)
            layout.addLayout(vBox)
            layout.addStretch()
示例#3
0
class HelpDialog(QObject, LogMixin):
    """Class implementing qthelp viewer dialog"""

    def __init__(self, qthelp_file, parent = None):
        """
        Constructor of HelpDialog

        :param qthelp_file: full path to qthelp helpfile

        """
        super(HelpDialog,self).__init__(parent)

        # instantiate help engine

        helpEngine = QHelpEngine(qthelp_file)
        helpEngine.setupData()
        self._helpEngine = helpEngine

        # base dialog widget
        self.ui = QDialog(None, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinMaxButtonsHint | QtCore.Qt.WindowCloseButtonHint )

        self.ui.setWindowTitle("HelpViewer")
        self.ui.setWindowIcon(QIcon(":/images/prog_icons/help/help.ico"))

        # Create webview for help information
        # and assign a custom URL scheme handler for scheme "qthelp)
        self._wv = QWebEngineView(self.ui)
        self._urlschemehandler = HelpSchemeHandler(self._helpEngine, self._wv.page().profile())
        self._wv.page().profile().installUrlSchemeHandler(b'qthelp', self._urlschemehandler)

        # get help content overview widget
        self._helpContent = self._helpEngine.contentWidget()
        self._helpIndex = self._helpEngine.indexWidget()
        self._helpSearchQuery = self._helpEngine.searchEngine().queryWidget()
        self._helpSearchResult = self._helpEngine.searchEngine().resultWidget()
        self._se = self._helpEngine.searchEngine()
        self._se.reindexDocumentation()

        self._helpSearchQuery.search.connect(self.search)

        # create QSplitter
        self._splitterMain = QSplitter(QtCore.Qt.Vertical)
        self._splitterMain.setOpaqueResize(False)
        self._splitterSearch = QSplitter(QtCore.Qt.Horizontal)
        self._splitterSearch.setOpaqueResize(False)
        self._splitterUpper = QSplitter(QtCore.Qt.Horizontal)
        self._splitterUpper.setOpaqueResize(False)
        self._splitterLower = QSplitter(QtCore.Qt.Horizontal)
        self._splitterLower.setOpaqueResize(False)

        # create horzLayout
        self._horzLayoutSearch = QHBoxLayout()
        self._horzLayoutUpper = QHBoxLayout()
        self._horzLayoutLower = QHBoxLayout()
        # create vertLayout
        self._vertLayout = QVBoxLayout()

        # main widgets
        self._upperWidget = QWidget()
        self._lowerWidget = QWidget()
        self._btnReset = QPushButton()
        self._btnReset.setMaximumHeight(23)
        self._btnReset.setMaximumWidth(100)

        # build search structure
        self._splitterSearch.insertWidget(0, self._helpSearchQuery)
        self._splitterSearch.insertWidget(1, self._btnReset)

        # build upper inner structure
        self._splitterUpper.insertWidget(0, self._helpContent)
        self._splitterUpper.insertWidget(1, self._wv)
        self._horzLayoutUpper.addWidget(self._splitterUpper)
        self._upperWidget.setLayout(self._horzLayoutUpper)

        # build lower inner structure
        self._splitterLower.insertWidget(0, self._helpIndex)
        self._splitterLower.insertWidget(1, self._helpSearchResult)
        self._horzLayoutLower.addWidget(self._splitterLower)
        self._lowerWidget.setLayout(self._horzLayoutLower)

        # build outer structure
        self._splitterMain.insertWidget(0, self._splitterSearch)
        self._splitterMain.insertWidget(1, self._upperWidget)
        self._splitterMain.insertWidget(2, self._lowerWidget)

        self._helpSearchResult.hide()
        self._btnReset.hide()

        self._vertLayout.addWidget(self._splitterMain)
        self.ui.setLayout(self._vertLayout)

        # set splitter width
        w = self._splitterUpper.geometry().width()
        self._splitterUpper.setSizes([w*(1/4), w*(3/4)])
        w = self._splitterLower.geometry().width()
        self._splitterLower.setSizes([w*(1/5), w*(4/5)])
        h = self._splitterMain.geometry().height()
        self._splitterMain.setSizes([h*(1/9), h*(7/9), h*(1/9)])

        self._helpContent.linkActivated.connect(self._wv.setUrl)
        self._helpIndex.linkActivated.connect(self._wv.setUrl)
        self._helpSearchResult.requestShowLink.connect(self._wv.setUrl)
        self._se.searchingFinished.connect(self.showResults)
        self._btnReset.clicked.connect(self.resetResult)

        self.retranslateMsg()

    def retranslateMsg(self):
        self.logger.debug("Retranslating further messages...")
        self._btnReset.setText(translate("HelpViewer", "Reset"))
        self._btnReset.setText(translate("HelpViewer", "Search"))

    def search(self):
        """Initiate qthelp search"""
        self._se.search(self._helpSearchQuery.query())

    def showResults(self):
        """Show search results, if any"""
        if self._se.hitCount() > 0:
            self._helpIndex.hide()
            h = self._splitterMain.geometry().height()
            self._splitterMain.setSizes([h*(1/3), h*(1/3), h*(1/3)])
            self._helpSearchResult.show()
            self._btnReset.show()

    def resetResult(self):
        """Reset search result widget"""

        self._helpSearchResult.hide()
        self._btnReset.hide()
        self._helpIndex.show()
        h = self._splitterMain.geometry().height()
        self._splitterMain.setSizes([h*(1/9), h*(7/9), h*(1/9)])
示例#4
0
class GuiMain(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)

        logger.info("Starting %s" % nw.__package__)
        logger.debug("Initialising GUI ...")
        self.mainConf   = nw.CONFIG
        self.theTheme   = GuiTheme(self)
        self.theProject = NWProject(self)
        self.theIndex   = NWIndex(self.theProject, self)
        self.hasProject = False
        self.isZenMode  = False

        logger.info("OS: %s" % (
            self.mainConf.osType)
        )
        logger.info("Qt5 Version: %s (%d)" % (
            self.mainConf.verQtString, self.mainConf.verQtValue)
        )
        logger.info("PyQt5 Version: %s (%d)" % (
            self.mainConf.verPyQtString, self.mainConf.verPyQtValue)
        )
        logger.info("Python Version: %s (0x%x)" % (
            self.mainConf.verPyString, self.mainConf.verPyHexVal)
        )

        self.resize(*self.mainConf.winGeometry)
        self._setWindowTitle()
        self.setWindowIcon(QIcon(path.join(self.mainConf.appIcon)))

        # Main GUI Elements
        self.statusBar = GuiMainStatus(self)
        self.noticeBar = GuiNoticeBar(self)
        self.docEditor = GuiDocEditor(self, self.theProject)
        self.docViewer = GuiDocViewer(self, self.theProject)
        self.viewMeta  = GuiDocViewDetails(self, self.theProject)
        self.searchBar = GuiSearchBar(self)
        self.treeMeta  = GuiDocDetails(self, self.theProject)
        self.treeView  = GuiDocTree(self, self.theProject)
        self.mainMenu  = GuiMainMenu(self, self.theProject)

        # Minor Gui Elements
        self.statusIcons = []
        self.importIcons = []

        # Assemble Main Window
        self.treePane = QFrame()
        self.treeBox = QVBoxLayout()
        self.treeBox.setContentsMargins(0,0,0,0)
        self.treeBox.addWidget(self.treeView)
        self.treeBox.addWidget(self.treeMeta)
        self.treePane.setLayout(self.treeBox)

        self.editPane = QFrame()
        self.docEdit = QVBoxLayout()
        self.docEdit.setContentsMargins(0,0,0,0)
        self.docEdit.addWidget(self.searchBar)
        self.docEdit.addWidget(self.noticeBar)
        self.docEdit.addWidget(self.docEditor)
        self.editPane.setLayout(self.docEdit)

        self.viewPane = QFrame()
        self.docView = QVBoxLayout()
        self.docView.setContentsMargins(0,0,0,0)
        self.docView.addWidget(self.docViewer)
        self.docView.addWidget(self.viewMeta)
        self.docView.setStretch(0, 1)
        self.viewPane.setLayout(self.docView)

        self.splitView = QSplitter(Qt.Horizontal)
        self.splitView.setOpaqueResize(False)
        self.splitView.addWidget(self.editPane)
        self.splitView.addWidget(self.viewPane)

        self.splitMain = QSplitter(Qt.Horizontal)
        self.splitMain.setContentsMargins(4,4,4,4)
        self.splitMain.setOpaqueResize(False)
        self.splitMain.addWidget(self.treePane)
        self.splitMain.addWidget(self.splitView)
        self.splitMain.setSizes(self.mainConf.mainPanePos)

        self.setCentralWidget(self.splitMain)

        self.idxTree   = self.splitMain.indexOf(self.treePane)
        self.idxMain   = self.splitMain.indexOf(self.splitView)
        self.idxEditor = self.splitView.indexOf(self.editPane)
        self.idxViewer = self.splitView.indexOf(self.viewPane)

        self.splitMain.setCollapsible(self.idxTree, False)
        self.splitMain.setCollapsible(self.idxMain, False)
        self.splitView.setCollapsible(self.idxEditor, False)
        self.splitView.setCollapsible(self.idxViewer, True)

        self.viewPane.setVisible(False)
        self.searchBar.setVisible(False)

        # Build The Tree View
        self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
        self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
        self.rebuildTree()

        # Set Main Window Elements
        self.setMenuBar(self.mainMenu)
        self.setStatusBar(self.statusBar)
        self.statusBar.setStatus("Ready")

        # Set Up Autosaving Project Timer
        self.asProjTimer = QTimer()
        self.asProjTimer.timeout.connect(self._autoSaveProject)

        # Set Up Autosaving Document Timer
        self.asDocTimer = QTimer()
        self.asDocTimer.timeout.connect(self._autoSaveDocument)

        # Shortcuts and Actions
        self._connectMenuActions()
        keyReturn = QShortcut(self.treeView)
        keyReturn.setKey(QKeySequence(Qt.Key_Return))
        keyReturn.activated.connect(self._treeKeyPressReturn)
        keyEscape = QShortcut(self)
        keyEscape.setKey(QKeySequence(Qt.Key_Escape))
        keyEscape.activated.connect(self._keyPressEscape)

        # Forward Functions
        self.setStatus = self.statusBar.setStatus
        self.setProjectStatus = self.statusBar.setProjectStatus

        if self.mainConf.showGUI:
            self.show()

        self.initMain()
        self.asProjTimer.start()
        self.asDocTimer.start()
        self.statusBar.clearStatus()

        self.showNormal()
        if self.mainConf.isFullScreen:
            self.toggleFullScreenMode()

        logger.debug("GUI initialisation complete")

        if self.mainConf.cmdOpen is not None:
            logger.debug("Opening project from additional command line option")
            self.openProject(self.mainConf.cmdOpen)

        return

    def clearGUI(self):
        """Wrapper function to clear all sub-elements of the main GUI.
        """
        self.treeView.clearTree()
        self.docEditor.clearEditor()
        self.closeDocViewer()
        self.statusBar.clearStatus()
        return True

    def initMain(self):
        self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000))
        self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000))
        return True

    ##
    #  Project Actions
    ##

    def newProject(self, projPath=None, forceNew=False):

        if self.hasProject:
            msgBox = QMessageBox()
            msgRes = msgBox.warning(
                self, "New Project",
                "Please close the current project<br>before making a new one."
            )
            return False

        if projPath is None:
            projPath = self.newProjectDialog()
        if projPath is None:
            return False

        if path.isfile(path.join(projPath,self.theProject.projFile)) and not forceNew:
            msgBox = QMessageBox()
            msgRes = msgBox.critical(
                self, "New Project",
                "A project already exists in that location.<br>Please choose another folder."
            )
            return False

        logger.info("Creating new project")
        self.theProject.newProject()
        self.theProject.setProjectPath(projPath)
        self.rebuildTree()
        self.saveProject()
        self.hasProject = True
        self.statusBar.setRefTime(self.theProject.projOpened)

        return True

    def closeProject(self, isYes=False):
        """Closes the project if one is open.
        isYes is passed on from the close application event so the user
        doesn't get prompted twice.
        """
        if not self.hasProject:
            # There is no project loaded, everything OK
            return True

        if self.mainConf.showGUI and not isYes:
            msgBox = QMessageBox()
            msgRes = msgBox.question(
                self, "Close Project", "Save changes and close current project?"
            )
            if msgRes != QMessageBox.Yes:
                return False

        if self.docEditor.docChanged:
            self.saveDocument()

        if self.theProject.projAltered:
            saveOK   = self.saveProject()
            doBackup = False
            if self.theProject.doBackup and self.mainConf.backupOnClose:
                doBackup = True
                if self.mainConf.showGUI and self.mainConf.askBeforeBackup:
                    msgBox = QMessageBox()
                    msgRes = msgBox.question(
                        self, "Backup Project", "Backup current project?"
                    )
                    if msgRes != QMessageBox.Yes:
                        doBackup = False
            if doBackup:
                self.backupProject()
        else:
            saveOK = True

        if saveOK:
            self.closeDocument()
            self.theProject.closeProject()
            self.theIndex.clearIndex()
            self.clearGUI()
            self.hasProject = False

        return saveOK

    def openProject(self, projFile=None):
        """Open a project. The parameter projFile is passed from the
        open recent projects menu, so it can be set. If not, we pop the
        dialog.
        """
        if projFile is None:
            projFile = self.openProjectDialog()
        if projFile is None:
            return False

        # Make sure any open project is cleared out first before we load
        # another one
        if not self.closeProject():
            return False

        # Try to open the project
        if not self.theProject.openProject(projFile):
            return False

        # project is loaded
        self.hasProject = True

        # Load the tag index
        self.theIndex.loadIndex()

        # Update GUI
        self._setWindowTitle(self.theProject.projName)
        self.rebuildTree()
        self.docEditor.setDictionaries()
        self.docEditor.setSpellCheck(self.theProject.spellCheck)
        self.statusBar.setRefTime(self.theProject.projOpened)
        self.mainMenu.updateMenu()

        # Restore previously open documents, if any
        if self.theProject.lastEdited is not None:
            self.openDocument(self.theProject.lastEdited)
        if self.theProject.lastViewed is not None:
            self.viewDocument(self.theProject.lastViewed)

        # Check if we need to rebuild the index
        if self.theIndex.indexBroken:
            self.rebuildIndex()

        return True

    def saveProject(self):
        """Save the current project.
        """
        if not self.hasProject:
            return False

        # If the project is new, it may not have a path, so we need one
        if self.theProject.projPath is None:
            projPath = self.saveProjectDialog()
            self.theProject.setProjectPath(projPath)
        if self.theProject.projPath is None:
            return False

        self.treeView.saveTreeOrder()
        self.theProject.saveProject()
        self.theIndex.saveIndex()
        self.mainMenu.updateRecentProjects()

        return True

    def backupProject(self):
        theBackup = NWBackup(self, self.theProject)
        theBackup.zipIt()
        return True

    ##
    #  Document Actions
    ##

    def closeDocument(self):
        if self.hasProject:
            if self.docEditor.docChanged:
                self.saveDocument()
            self.docEditor.clearEditor()
        return True

    def openDocument(self, tHandle):
        if self.hasProject:
            self.closeDocument()
            if self.docEditor.loadText(tHandle):
                self.docEditor.setFocus()
                self.theProject.setLastEdited(tHandle)
            else:
                return False
        return True

    def saveDocument(self):
        if self.hasProject:
            self.docEditor.saveText()
        return True

    def viewDocument(self, tHandle=None):

        if tHandle is None:
            tHandle = self.treeView.getSelectedHandle()
        if tHandle is None:
            logger.debug("No document selected, trying editor document")
            tHandle = self.docEditor.theHandle
        if tHandle is None:
            logger.debug("No document selected, trying last viewed")
            tHandle = self.theProject.lastViewed
        if tHandle is None:
            logger.debug("No document selected, giving up")
            return False

        if self.docViewer.loadText(tHandle) and not self.viewPane.isVisible():
            bPos = self.splitMain.sizes()
            self.viewPane.setVisible(True)
            vPos = [0,0]
            vPos[0] = int(bPos[1]/2)
            vPos[1] = bPos[1]-vPos[0]
            self.splitView.setSizes(vPos)

        return True

    def importDocument(self):

        lastPath = self.mainConf.lastPath

        extFilter = [
            "Text files (*.txt)",
            "Markdown files (*.md)",
            "All files (*.*)",
        ]
        dlgOpt  = QFileDialog.Options()
        dlgOpt |= QFileDialog.DontUseNativeDialog
        inPath  = QFileDialog.getOpenFileName(
            self,"Import File",lastPath,options=dlgOpt,filter=";;".join(extFilter)
        )
        if inPath:
            loadFile = inPath[0]
        else:
            return False

        if loadFile.strip() == "":
            return False

        theText = None
        try:
            with open(loadFile,mode="rt",encoding="utf8") as inFile:
                theText = inFile.read()
            self.mainConf.setLastPath(loadFile)
        except Exception as e:
            self.makeAlert(
                ["Could not read file. The file must be an existing text file.",str(e)],
                nwAlert.ERROR
            )
            return False

        if self.docEditor.theHandle is None:
            self.makeAlert(
                ["Please open a document to import the text file into."],
                nwAlert.ERROR
            )
            return False

        if not self.docEditor.isEmpty():
            if self.mainConf.showGUI:
                msgBox = QMessageBox()
                msgRes = msgBox.question(self, "Import Document",(
                    "Importing the file will overwrite the current content of the document. "
                    "Do you want to proceed?"
                ))
                if msgRes != QMessageBox.Yes:
                    return False
            else:
                return False

        self.docEditor.replaceText(theText)

        return True

    def mergeDocuments(self):
        """Merge multiple documents to one single new document.
        """
        if self.mainConf.showGUI:
            dlgMerge = GuiDocMerge(self, self.theProject)
            dlgMerge.exec_()
        return True

    def splitDocument(self):
        """Split a single document into multiple documents.
        """
        if self.mainConf.showGUI:
            dlgSplit = GuiDocSplit(self, self.theProject)
            dlgSplit.exec_()
        return True

    def passDocumentAction(self, theAction):
        """Pass on document action theAction to whatever document has
        the focus. If no document has focus, the action is discarded.
        """
        if self.docEditor.hasFocus():
            self.docEditor.docAction(theAction)
        elif self.docViewer.hasFocus():
            self.docViewer.docAction(theAction)
        else:
            logger.debug("Document action requested, but no document has focus")
        return True

    ##
    #  Tree Item Actions
    ##

    def openSelectedItem(self):
        tHandle = self.treeView.getSelectedHandle()
        if tHandle is None:
            logger.warning("No item selected")
            return False

        logger.verbose("Opening item %s" % tHandle)
        nwItem = self.theProject.getItem(tHandle)
        if nwItem.itemType == nwItemType.FILE:
            logger.verbose("Requested item %s is a file" % tHandle)
            self.openDocument(tHandle)
        else:
            logger.verbose("Requested item %s is not a file" % tHandle)

        return True

    def editItem(self):
        tHandle = self.treeView.getSelectedHandle()
        if tHandle is None:
            logger.warning("No item selected")
            return

        logger.verbose("Requesting change to item %s" % tHandle)
        if self.mainConf.showGUI:
            dlgProj = GuiItemEditor(self, self.theProject, tHandle)
            if dlgProj.exec_():
                self.treeView.setTreeItemValues(tHandle)

        return

    def rebuildTree(self):
        self._makeStatusIcons()
        self._makeImportIcons()
        self.treeView.clearTree()
        self.treeView.buildTree()
        return

    def rebuildIndex(self):

        if not self.hasProject:
            return False

        logger.debug("Rebuilding indices ...")

        self.treeView.saveTreeOrder()
        self.theIndex.clearIndex()
        nItems = len(self.theProject.treeOrder)

        dlgProg = QProgressDialog("Scanning files ...", "Cancel", 0, nItems, self)
        dlgProg.setWindowModality(Qt.WindowModal)
        dlgProg.setMinimumDuration(0)
        dlgProg.setFixedWidth(480)
        dlgProg.setLabelText("Starting file scan ...")
        dlgProg.setValue(0)
        dlgProg.show()
        time.sleep(0.5)

        nDone = 0
        for tHandle in self.theProject.treeOrder:

            tItem = self.theProject.getItem(tHandle)

            dlgProg.setValue(nDone)
            dlgProg.setLabelText("Scanning: %s" % tItem.itemName)
            logger.verbose("Scanning: %s" % tItem.itemName)

            if tItem is not None and tItem.itemType == nwItemType.FILE:
                theDoc  = NWDoc(self.theProject, self)
                theText = theDoc.openDocument(tHandle, False)

                # Run Word Count
                cC, wC, pC = countWords(theText)
                tItem.setCharCount(cC)
                tItem.setWordCount(wC)
                tItem.setParaCount(pC)
                self.treeView.propagateCount(tHandle, wC)
                self.treeView.projectWordCount()

                # Build tag index
                self.theIndex.scanText(tHandle, theText)

            nDone += 1
            if dlgProg.wasCanceled():
                break

        dlgProg.setValue(nItems)

        return True

    ##
    #  Main Dialogs
    ##

    def openProjectDialog(self):
        dlgOpt  = QFileDialog.Options()
        dlgOpt |= QFileDialog.DontUseNativeDialog
        projFile, _ = QFileDialog.getOpenFileName(
            self, "Open novelWriter Project", "",
            "novelWriter Project File (%s);;All Files (*)" % nwFiles.PROJ_FILE,
            options=dlgOpt
        )
        if projFile:
            return projFile
        return None

    def saveProjectDialog(self):
        dlgOpt  = QFileDialog.Options()
        dlgOpt |= QFileDialog.ShowDirsOnly
        dlgOpt |= QFileDialog.DontUseNativeDialog
        projPath = QFileDialog.getExistingDirectory(
            self, "Save novelWriter Project", "", options=dlgOpt
        )
        if projPath:
            return projPath
        return None

    def newProjectDialog(self):
        dlgOpt  = QFileDialog.Options()
        dlgOpt |= QFileDialog.ShowDirsOnly
        dlgOpt |= QFileDialog.DontUseNativeDialog
        projPath = QFileDialog.getExistingDirectory(
            self, "Select Location for New novelWriter Project", "", options=dlgOpt
        )
        if projPath:
            return projPath
        return None

    def editConfigDialog(self):
        dlgConf = GuiConfigEditor(self, self.theProject)
        if dlgConf.exec_() == QDialog.Accepted:
            logger.debug("Applying new preferences")
            self.initMain()
            self.theTheme.updateTheme()
            self.saveDocument()
            self.docEditor.initEditor()
            self.docViewer.initViewer()
        return True

    def editProjectDialog(self):
        if self.hasProject:
            dlgProj = GuiProjectEditor(self, self.theProject)
            dlgProj.exec_()
            self._setWindowTitle(self.theProject.projName)
        return True

    def exportProjectDialog(self):
        if self.hasProject:
            dlgExport = GuiExport(self, self.theProject)
            dlgExport.exec_()
        return True

    def showTimeLineDialog(self):
        if self.hasProject:
            dlgTLine = GuiTimeLineView(self, self.theProject, self.theIndex)
            dlgTLine.exec_()
        return True

    def showSessionLogDialog(self):
        if self.hasProject:
            dlgTLine = GuiSessionLogView(self, self.theProject)
            dlgTLine.exec_()
        return True

    def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
        """Alert both the user and the logger at the same time. Message
        can be either a string or an array of strings. Severity level is
        0 = info, 1 = warning, and 2 = error.
        """

        if isinstance(theMessage, list):
            popMsg = " ".join(theMessage)
            logMsg = theMessage
        else:
            popMsg = theMessage
            logMsg = [theMessage]

        msgBox = QMessageBox()
        if theLevel == nwAlert.INFO:
            for msgLine in logMsg:
                logger.info(msgLine)
            msgBox.information(self, "Information", popMsg)
        elif theLevel == nwAlert.WARN:
            for msgLine in logMsg:
                logger.warning(msgLine)
            msgBox.warning(self, "Warning", popMsg)
        elif theLevel == nwAlert.ERROR:
            for msgLine in logMsg:
                logger.error(msgLine)
            msgBox.critical(self, "Error", popMsg)
        elif theLevel == nwAlert.BUG:
            for msgLine in logMsg:
                logger.error(msgLine)
            popMsg += "<br>This is a bug!"
            msgBox.critical(self, "Internal Error", popMsg)

        return

    ##
    #  Main Window Actions
    ##

    def closeMain(self):

        if self.mainConf.showGUI and self.hasProject:
            msgBox = QMessageBox()
            msgRes = msgBox.question(
                self, "Exit", "Do you want to save changes and exit?"
            )
            if msgRes != QMessageBox.Yes:
                return False

        logger.info("Exiting %s" % nw.__package__)
        self.closeProject(True)

        self.mainConf.setTreeColWidths(self.treeView.getColumnSizes())
        if not self.mainConf.isFullScreen:
            self.mainConf.setWinSize(self.width(), self.height())
        if not self.isZenMode:
            self.mainConf.setMainPanePos(self.splitMain.sizes())
            self.mainConf.setDocPanePos(self.splitView.sizes())
        self.mainConf.saveConfig()

        qApp.quit()

        return True

    def setFocus(self, paneNo):
        if paneNo == 1:
            self.treeView.setFocus()
        elif paneNo == 2:
            self.docEditor.setFocus()
        elif paneNo == 3:
            self.docViewer.setFocus()
        return

    def closeDocEditor(self):
        self.closeDocument()
        self.theProject.setLastEdited(None)
        return

    def closeDocViewer(self):
        self.docViewer.clearViewer()
        self.theProject.setLastViewed(None)
        bPos = self.splitMain.sizes()
        self.viewPane.setVisible(False)
        vPos = [bPos[1],0]
        self.splitView.setSizes(vPos)
        return not self.viewPane.isVisible()

    def toggleZenMode(self):
        """Main GUI Zen Mode hides tree, view pane and optionally also
        statusbar and menu.
        """

        if self.docEditor.theHandle is None:
            logger.error("No document open, so not activating Zen Mode")
            return False

        self.isZenMode = not self.isZenMode
        if self.isZenMode:
            logger.debug("Activating Zen mode")
        else:
            logger.debug("Deactivating Zen mode")

        isVisible = not self.isZenMode
        self.treePane.setVisible(isVisible)
        self.statusBar.setVisible(isVisible)
        self.mainMenu.setVisible(isVisible)

        if self.viewPane.isVisible():
            self.viewPane.setVisible(False)
        elif self.docViewer.theHandle is not None:
            self.viewPane.setVisible(True)

        return True

    def toggleFullScreenMode(self):
        """Main GUI full screen mode. The mode is tracked by the flag
        in config. This only tracks whether the window has been
        maximised using the internal commands, and may not be correct
        if the user uses the system window manager. Currently, Qt
        doesn't have access to the exact state of the window.
        """

        self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)

        winState = self.windowState() & Qt.WindowFullScreen == Qt.WindowFullScreen
        if winState:
            logger.debug("Activated full screen mode")
        else:
            logger.debug("Deactivated full screen mode")

        self.mainConf.isFullScreen = winState

        return

    ##
    #  Internal Functions
    ##

    def _connectMenuActions(self):
        """Connect to the main window all menu actions that need to be
        available also when the main menu is hidden.
        """
        self.addAction(self.mainMenu.aSaveProject)
        self.addAction(self.mainMenu.aExitNW)
        self.addAction(self.mainMenu.aSaveDoc)
        self.addAction(self.mainMenu.aFileDetails)
        self.addAction(self.mainMenu.aZenMode)
        self.addAction(self.mainMenu.aFullScreen)
        self.addAction(self.mainMenu.aViewTimeLine)
        self.addAction(self.mainMenu.aEditUndo)
        self.addAction(self.mainMenu.aEditRedo)
        self.addAction(self.mainMenu.aEditCut)
        self.addAction(self.mainMenu.aEditCopy)
        self.addAction(self.mainMenu.aEditPaste)
        self.addAction(self.mainMenu.aSelectAll)
        self.addAction(self.mainMenu.aSelectPar)
        self.addAction(self.mainMenu.aFmtBold)
        self.addAction(self.mainMenu.aFmtItalic)
        self.addAction(self.mainMenu.aFmtULine)
        self.addAction(self.mainMenu.aFmtDQuote)
        self.addAction(self.mainMenu.aFmtSQuote)
        self.addAction(self.mainMenu.aFmtHead1)
        self.addAction(self.mainMenu.aFmtHead2)
        self.addAction(self.mainMenu.aFmtHead3)
        self.addAction(self.mainMenu.aFmtHead4)
        self.addAction(self.mainMenu.aFmtComment)
        self.addAction(self.mainMenu.aFmtNoFormat)
        self.addAction(self.mainMenu.aSpellCheck)
        self.addAction(self.mainMenu.aReRunSpell)
        self.addAction(self.mainMenu.aPreferences)
        self.addAction(self.mainMenu.aHelp)
        return True

    def _setWindowTitle(self, projName=None):
        winTitle = "%s" % nw.__package__
        if projName is not None:
            winTitle += " - %s" % projName
        self.setWindowTitle(winTitle)
        return True

    def _autoSaveProject(self):
        if (self.hasProject and self.theProject.projChanged and
            self.theProject.projPath is not None):
            logger.debug("Autosaving project")
            self.saveProject()
        return

    def _autoSaveDocument(self):
        if self.hasProject and self.docEditor.docChanged:
            logger.debug("Autosaving document")
            self.saveDocument()
        return

    def _makeStatusIcons(self):
        self.statusIcons = {}
        for sLabel, sCol, _ in self.theProject.statusItems:
            theIcon = QPixmap(32,32)
            theIcon.fill(QColor(*sCol))
            self.statusIcons[sLabel] = QIcon(theIcon)
        return

    def _makeImportIcons(self):
        self.importIcons = {}
        for sLabel, sCol, _ in self.theProject.importItems:
            theIcon = QPixmap(32,32)
            theIcon.fill(QColor(*sCol))
            self.importIcons[sLabel] = QIcon(theIcon)
        return

    ##
    #  Events
    ##

    def closeEvent(self, theEvent):
        if self.closeMain():
            theEvent.accept()
        else:
            theEvent.ignore()
        return

    ##
    #  Signal Handlers
    ##

    def _treeSingleClick(self):
        sHandle = self.treeView.getSelectedHandle()
        if sHandle is not None:
            self.treeMeta.buildViewBox(sHandle)
        return

    def _treeDoubleClick(self, tItem, colNo):
        tHandle = tItem.text(3)
        logger.verbose("User double clicked tree item with handle %s" % tHandle)
        nwItem = self.theProject.getItem(tHandle)
        if nwItem.itemType == nwItemType.FILE:
            logger.verbose("Requested item %s is a file" % tHandle)
            self.openDocument(tHandle)
        else:
            logger.verbose("Requested item %s is a folder" % tHandle)
        return

    def _treeKeyPressReturn(self):
        tHandle = self.treeView.getSelectedHandle()
        logger.verbose("User pressed return on tree item with handle %s" % tHandle)
        nwItem = self.theProject.getItem(tHandle)
        if nwItem.itemType == nwItemType.FILE:
            logger.verbose("Requested item %s is a file" % tHandle)
            self.openDocument(tHandle)
        else:
            logger.verbose("Requested item %s is a folder" % tHandle)
        return

    def _keyPressEscape(self):
        """When the escape key is pressed somewhere in the main window,
        do the following, in order.
        """
        if self.searchBar.isVisible():
            self.searchBar.setVisible(False)
            return
        elif self.isZenMode:
            self.toggleZenMode()
        return
示例#5
0
    def __init__(self, parent=None):
        super(StockDialog, self).__init__(parent)
        self.setWindowTitle("QT painter")

        mainSplitter = QSplitter(Qt.Horizontal)
        mainSplitter.setOpaqueResize(True)

        frame = QFrame(mainSplitter)
        mainLayout = QGridLayout(frame)
        # mainLayout.setMargin(10)
        mainLayout.setSpacing(6)

        label1 = QLabel("形状:")
        label2 = QLabel("画笔线宽:")
        label3 = QLabel("画笔颜色:")
        label4 = QLabel("画笔风格:")
        label5 = QLabel("画笔顶端:")
        label6 = QLabel("画笔连接点:")
        label7 = QLabel("画刷风格:")
        label8 = QLabel("画刷颜色:")

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Line", "Line")
        self.shapeComboBox.addItem("Rectangle", "Rectangle")
        self.shapeComboBox.addItem('Rounded Rectangle', 'Rounded Rectangle')
        self.shapeComboBox.addItem('Ellipse', 'Ellipse')
        self.shapeComboBox.addItem('Pie', 'Pie')
        self.shapeComboBox.addItem('Chord', 'Chord')
        self.shapeComboBox.addItem('Path', 'Path')
        self.shapeComboBox.addItem('Polygon', 'Polygon')
        self.shapeComboBox.addItem('Polyline', 'Polyline')
        self.shapeComboBox.addItem('Arc', 'Arc')
        self.shapeComboBox.addItem('Points', 'Points')
        self.shapeComboBox.addItem('Text', 'Text')
        self.shapeComboBox.addItem('Pixmap', 'Pixmap')

        self.widthSpinBox = QSpinBox()
        self.widthSpinBox.setRange(0, 20)

        self.penColorFrame = QFrame()
        self.penColorFrame.setAutoFillBackground(True)
        self.penColorFrame.setPalette(QPalette(Qt.blue))
        self.penColorPushButton = QPushButton("更改")

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem('Dash', Qt.DashLine)
        self.penStyleComboBox.addItem('Dot', Qt.DotLine)
        self.penStyleComboBox.addItem('Dash Dot', Qt.DashDotLine)
        self.penStyleComboBox.addItem('Dash Dot Dot', Qt.DashDotDotLine)
        self.penStyleComboBox.addItem('None', Qt.NoPen)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem('Square', Qt.SquareCap)
        self.penCapComboBox.addItem('Round', Qt.RoundCap)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem('Bebel', Qt.BevelJoin)
        self.penJoinComboBox.addItem('Round', Qt.RoundJoin)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                                        Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem('Radial Gradient',
                                        Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem('Conical Gradient',
                                        Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem('Texture', Qt.TexturePattern)
        self.brushStyleComboBox.addItem('Solid', Qt.SolidPattern)
        self.brushStyleComboBox.addItem('Horizontal', Qt.HorPattern)
        self.brushStyleComboBox.addItem('Vertical', Qt.VerPattern)
        self.brushStyleComboBox.addItem('Cross', Qt.CrossPattern)
        self.brushStyleComboBox.addItem('Backward Diagonal', Qt.BDiagPattern)
        self.brushStyleComboBox.addItem('Forward Diagonal', Qt.FDiagPattern)
        self.brushStyleComboBox.addItem('Diagonal Cross', Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem('Dense 1', Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem('Dense 2', Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem('Dense 3', Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem('Dense 4', Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem('Dense 5', Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem('Dense 6', Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem('Dense 7', Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem('None', Qt.NoBrush)

        self.brushColorFrame = QFrame()
        self.brushColorFrame.setAutoFillBackground(True)
        self.brushColorFrame.setPalette(QPalette(Qt.green))
        self.brushColorPushButton = QPushButton("更改")

        labelCol = 0
        contentCol = 1

        # 建立布局
        mainLayout.addWidget(label1, 1, labelCol)
        mainLayout.addWidget(self.shapeComboBox, 1, contentCol)
        mainLayout.addWidget(label2, 2, labelCol)
        mainLayout.addWidget(self.widthSpinBox, 2, contentCol)
        mainLayout.addWidget(label3, 4, labelCol)
        mainLayout.addWidget(self.penColorFrame, 4, contentCol)
        mainLayout.addWidget(self.penColorPushButton, 4, 3)
        mainLayout.addWidget(label4, 6, labelCol)
        mainLayout.addWidget(self.penStyleComboBox, 6, contentCol)
        mainLayout.addWidget(label5, 8, labelCol)
        mainLayout.addWidget(self.penCapComboBox, 8, contentCol)
        mainLayout.addWidget(label6, 10, labelCol)
        mainLayout.addWidget(self.penJoinComboBox, 10, contentCol)
        mainLayout.addWidget(label7, 12, labelCol)
        mainLayout.addWidget(self.brushStyleComboBox, 12, contentCol)
        mainLayout.addWidget(label8, 14, labelCol)
        mainLayout.addWidget(self.brushColorFrame, 14, contentCol)
        mainLayout.addWidget(self.brushColorPushButton, 14, 3)
        mainSplitter1 = QSplitter(Qt.Horizontal)
        mainSplitter1.setOpaqueResize(True)

        stack1 = QStackedWidget()
        stack1.setFrameStyle(QFrame.Panel | QFrame.Raised)
        self.area = PaintArea()
        stack1.addWidget(self.area)
        frame1 = QFrame(mainSplitter1)
        mainLayout1 = QVBoxLayout(frame1)
        # mainLayout1.setMargin(10)
        mainLayout1.setSpacing(6)
        mainLayout1.addWidget(stack1)

        layout = QGridLayout(self)
        layout.addWidget(mainSplitter1, 0, 0)
        layout.addWidget(mainSplitter, 0, 1)
        self.setLayout(layout)

        # 信号和槽函数
        self.shapeComboBox.activated.connect(self.slotShape)
        self.widthSpinBox.valueChanged.connect(self.slotPenWidth)
        self.penColorPushButton.clicked.connect(self.slotPenColor)
        self.penStyleComboBox.activated.connect(self.slotPenStyle)
        self.penCapComboBox.activated.connect(self.slotPenCap)
        self.penJoinComboBox.activated.connect(self.slotPenJoin)
        self.brushStyleComboBox.activated.connect(self.slotBrush)
        self.brushColorPushButton.clicked.connect(self.slotBrushColor)

        self.slotShape(self.shapeComboBox.currentIndex())
        self.slotPenWidth(self.widthSpinBox.value())
        self.slotBrush(self.brushStyleComboBox.currentIndex())
示例#6
0
class Ui_MainWindow(object):
    def setupUi(self, main_window):

        main_window.setObjectName("mainWindow")
        main_window.resize(1024, 768)
        main_window.setMinimumSize(QSize(1024, 768))
        main_window.setToolButtonStyle(Qt.ToolButtonIconOnly)

        self.central_widget = QWidget(main_window)
        self.central_widget.setObjectName("central_widget")

        self.horizontalLayout = QHBoxLayout(self.central_widget)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.topDownSplitter = QSplitter(self.central_widget)
        self.topDownSplitter.setOrientation(Qt.Vertical)
        self.topDownSplitter.setOpaqueResize(True)
        self.topDownSplitter.setHandleWidth(5)
        self.topDownSplitter.setObjectName("topDownSplitter")

        self.leftRightSplitter = QSplitter(self.topDownSplitter)
        self.leftRightSplitter.setOrientation(Qt.Horizontal)
        self.leftRightSplitter.setObjectName("leftRightSplitter")

        self.leftPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.leftPanel.sizePolicy().hasHeightForWidth())

        self.leftPanel.setSizePolicy(sizePolicy)
        self.leftPanel.setMinimumSize(QSize(245, 550))
        self.leftPanel.setMaximumSize(QSize(245, 16777215))
        self.leftPanel.setFrameShape(QFrame.StyledPanel)
        self.leftPanel.setFrameShadow(QFrame.Raised)
        self.leftPanel.setObjectName("leftPanel")

        self.leftPanelVLayout = QVBoxLayout(self.leftPanel)
        self.leftPanelVLayout.setObjectName("leftPanelVLayout")

        self.colorPickerFrame = QFrame(self.leftPanel)
        self.colorPickerFrame.setMinimumSize(QSize(0, 0))
        self.colorPickerFrame.setMaximumSize(QSize(16777215, 16777215))
        self.colorPickerFrame.setFrameShape(QFrame.StyledPanel)
        self.colorPickerFrame.setFrameShadow(QFrame.Raised)
        self.colorPickerFrame.setObjectName("colorPickerFrame")

        self.leftPanelVLayout.addWidget(self.colorPickerFrame)
        self.leftPanelVLayout.setStretch(0, 5)

        self.mainPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.mainPanel.sizePolicy().hasHeightForWidth())

        self.mainPanel.setSizePolicy(sizePolicy)
        self.mainPanel.setMinimumSize(QSize(320, 240))
        self.mainPanel.setAutoFillBackground(False)
        self.mainPanel.setFrameShape(QFrame.StyledPanel)
        self.mainPanel.setFrameShadow(QFrame.Raised)
        self.mainPanel.setObjectName("mainPanel")

        self.verticalLayout = QVBoxLayout(self.mainPanel)
        self.verticalLayout.setObjectName("verticalLayout")

        self.canvasFrame = QFrame(self.mainPanel)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.canvasFrame.sizePolicy().hasHeightForWidth())

        self.canvasFrame.setSizePolicy(sizePolicy)
        self.canvasFrame.setMinimumSize(310, 230)
        self.canvasFrame.setFrameShape(QFrame.StyledPanel)
        self.canvasFrame.setFrameShadow(QFrame.Raised)
        self.canvasFrame.setObjectName("canvasFrame")

        self.verticalLayout.addWidget(self.canvasFrame)
        self.verticalLayout.setStretch(0, 12)

        self.rightPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.rightPanel.sizePolicy().hasHeightForWidth())

        self.rightPanel.setSizePolicy(sizePolicy)
        self.rightPanel.setMinimumSize(QSize(245, 550))
        self.rightPanel.setMaximumSize(QSize(340, 16777215))
        self.rightPanel.setFrameShape(QFrame.StyledPanel)
        self.rightPanel.setFrameShadow(QFrame.Raised)
        self.rightPanel.setObjectName("rightPanel")

        self.rightPanelLayout = QVBoxLayout(self.rightPanel)
        self.rightPanelLayout.setObjectName("rightPanelLayout")

        self.previewFrame = QFrame(self.rightPanel)
        self.previewFrame.setMaximumSize(320, 500)
        self.previewFrame.setFrameShape(QFrame.StyledPanel)
        self.previewFrame.setFrameShadow(QFrame.Raised)
        self.previewFrame.setObjectName("previewFrame")

        self.rightPanelLayout.addWidget(self.previewFrame)

        self.layerListFrame = QFrame(self.rightPanel)
        self.layerListFrame.setFrameShape(QFrame.StyledPanel)
        self.layerListFrame.setFrameShadow(QFrame.Raised)
        self.layerListFrame.setObjectName("layerListFrame")

        self.rightPanelLayout.addWidget(self.layerListFrame)

        self.animationBarFrame = QFrame(self.topDownSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.animationBarFrame.sizePolicy().hasHeightForWidth())

        self.animationBarFrame.setSizePolicy(sizePolicy)
        self.animationBarFrame.setMinimumSize(QSize(600, 100))
        self.animationBarFrame.setMaximumSize(QSize(16777215, 100))
        self.animationBarFrame.setFrameShape(QFrame.StyledPanel)
        self.animationBarFrame.setFrameShadow(QFrame.Raised)
        self.animationBarFrame.setObjectName("animationBarFrame")

        self.horizontalLayout.addWidget(self.topDownSplitter)

        main_window.setCentralWidget(self.central_widget)

        self.toolBar = QToolBar(main_window)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.toolBar.sizePolicy().hasHeightForWidth())

        self.toolBar.setSizePolicy(sizePolicy)
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        self.toolBar.setObjectName("toolBar")

        main_window.addToolBar(Qt.TopToolBarArea, self.toolBar)

        self.actionNew = QAction(main_window)
        self.actionNew.setObjectName("actionNew")

        self.actionQuit = QAction(main_window)
        self.actionQuit.setObjectName("actionQuit")

        self.actionOpen = QAction(main_window)
        self.actionOpen.setObjectName("actionOpen")

        self.actionSave = QAction(main_window)
        self.actionSave.setObjectName("actionSave")

        self.actionSaveAs = QAction(main_window)
        self.actionSaveAs.setObjectName("actionSaveAs")

        self.actionClose = QAction(main_window)
        self.actionClose.setObjectName("actionClose")

        self.actionExport = QAction(main_window)
        self.actionExport.setObjectName("actionExport")

        self.actionImport = QAction(main_window)
        self.actionImport.setObjectName("actionImport")

        self.toolBar.addAction(self.actionNew)
        self.toolBar.addAction(self.actionOpen)
        self.toolBar.addAction(self.actionImport)
        self.toolBar.addAction(self.actionSave)
        self.toolBar.addAction(self.actionSaveAs)
        self.toolBar.addAction(self.actionExport)
        self.toolBar.addAction(self.actionClose)
        self.toolBar.addAction(self.actionQuit)

        self.retranslateUi(main_window)
        QMetaObject.connectSlotsByName(main_window)

    def retranslateUi(self, main_window):

        _translate = QCoreApplication.translate

        main_window.setWindowTitle(_translate("MainWindow", "SpriteMator"))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))

        self.actionNew.setText(_translate("MainWindow", "New"))
        self.actionNew.setIconText(_translate("MainWindow", "New"))
        self.actionNew.setToolTip(_translate("MainWindow", "New Sprite"))
        self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))

        self.actionQuit.setText(_translate("MainWindow", "Quit"))
        self.actionQuit.setToolTip(
            _translate("MainWindow", "Close Application"))
        self.actionQuit.setShortcut(_translate("MainWindow", "Esc"))

        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionOpen.setToolTip(_translate("MainWindow", "Open Sprite"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))

        self.actionSave.setText(_translate("MainWindow", "Save"))
        self.actionSave.setToolTip(_translate("MainWindow", "Save Sprite"))
        self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))

        self.actionSaveAs.setText(_translate("MainWindow", "SaveAs"))
        self.actionSaveAs.setToolTip(
            _translate("MainWindow", "Save Sprite with another name"))
        self.actionSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S"))

        self.actionClose.setText(_translate("MainWindow", "Close"))
        self.actionClose.setToolTip(_translate("MainWindow", "Close Sprite"))
        self.actionClose.setShortcut(_translate("MainWindow", "Ctrl+Q"))

        self.actionExport.setText(_translate("MainWindow", "Export"))
        self.actionExport.setToolTip(
            _translate(
                "MainWindow",
                "Export Sprite animations : Either as separate images or as a spritesheet"
            ))
        self.actionExport.setShortcut(_translate("MainWindow", "Ctrl+E"))

        self.actionImport.setText(_translate("MainWindow", "Import"))
        self.actionImport.setToolTip(
            _translate("MainWindow",
                       "Create a Sprite from one or more images"))
        self.actionImport.setShortcut(_translate("MainWindow", "Ctrl+I"))
示例#7
0
class MainWindow(QFrame):

    smx_file = core.SmxFile()
    hotplug = core.HotPlug()
    devices = []
    target = None
    worker = None

    def __init__(self):
        super().__init__()
        self.setWindowTitle('i.MX Smart-Boot Tool')
        self.setMinimumSize(600, 400)
        self.center()

        # create main box
        layout = QVBoxLayout()

        # --------------------------------------------------------------------------------------------------------------
        # Device selection drop-box with scan button
        # --------------------------------------------------------------------------------------------------------------
        box = QHBoxLayout()
        self.deviceBox = QComboBox()
        box.addWidget(self.deviceBox)

        self.scanButton = QPushButton("  Scan")
        self.scanButton.setFixedWidth(80)
        self.scanButton.setIcon(QIcon.fromTheme("view-refresh"))
        self.scanButton.clicked.connect(self.on_scan_button_clicked)
        box.addWidget(self.scanButton)
        layout.addLayout(box)

        # --------------------------------------------------------------------------------------------------------------
        # SMX File inbox with open button
        # --------------------------------------------------------------------------------------------------------------
        box = QHBoxLayout()
        self.smxEdit = QLineEdit()
        self.smxEdit.setReadOnly(True)
        box.addWidget(self.smxEdit)

        self.openButton = QPushButton(" Open")
        self.openButton.setFixedWidth(80)
        self.openButton.setIcon(QIcon.fromTheme("document-open"))
        self.openButton.clicked.connect(self.on_open_button_clicked)
        box.addWidget(self.openButton)
        layout.addLayout(box)

        # --------------------------------------------------------------------------------------------------------------
        # Body
        # --------------------------------------------------------------------------------------------------------------
        self.splitter = QSplitter()
        self.splitter.setHandleWidth(5)
        self.splitter.setMidLineWidth(0)
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setOpaqueResize(True)
        self.splitter.setChildrenCollapsible(False)

        self.scriptsList = QListWidget(self.splitter)
        self.scriptsList.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContents)
        self.scriptsList.setMinimumHeight(60)

        self.textEdit = QTextEdit(self.splitter)
        self.textEdit.setReadOnly(True)
        self.textEdit.setMinimumHeight(100)
        layout.addWidget(self.splitter)

        # Progress Bar
        self.pgTask = QProgressBar()
        self.pgTask.setRange(0, PGRANGE)
        self.pgTask.setFixedHeight(16)
        self.pgTask.setTextVisible(False)
        layout.addWidget(self.pgTask)

        # --------------------------------------------------------------------------------------------------------------
        # Buttons
        # --------------------------------------------------------------------------------------------------------------
        box = QHBoxLayout()
        box.setContentsMargins(-1, 5, -1, -1)

        # About Button
        self.aboutButton = QPushButton(" About")
        self.aboutButton.setMinimumSize(100, 40)
        self.aboutButton.setIcon(QIcon.fromTheme("help-contents"))
        self.aboutButton.clicked.connect(self.on_about_button_clicked)
        box.addWidget(self.aboutButton)

        # Device Info Button
        self.devInfoButton = QPushButton(" DevInfo")
        self.devInfoButton.setEnabled(False)
        self.devInfoButton.setMinimumSize(100, 40)
        self.devInfoButton.setIcon(QIcon.fromTheme("help-about"))
        self.devInfoButton.clicked.connect(self.on_info_button_clicked)
        box.addWidget(self.devInfoButton)

        # Spacer
        box.addItem(
            QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))

        # Start Button
        self.startButton = QPushButton(" Start")
        self.startButton.setEnabled(False)
        self.startButton.setMinimumSize(100, 40)
        self.startButton.setIcon(QIcon.fromTheme("media-playback-start"))
        self.startButton.clicked.connect(self.on_start_button_clicked)
        box.addWidget(self.startButton)

        # Start Button
        self.exitButton = QPushButton(" Exit")
        self.exitButton.setMinimumSize(100, 40)
        self.exitButton.setIcon(QIcon.fromTheme("application-exit"))
        self.exitButton.clicked.connect(self.on_exit_button_clicked)
        box.addWidget(self.exitButton)

        layout.addLayout(box)
        self.setLayout(layout)

        # USB hot-plug (Linux only)
        # self.hotplug.attach(self.scan_usb)
        # self.hotplug.start()
        # TODO: Fix USB hot-plug
        self.scan_usb()

    def center(self):
        # center point of screen
        cp = QDesktopWidget().availableGeometry().center()
        # move rectangle's center point to screen's center point
        qr = self.frameGeometry()
        qr.moveCenter(cp)
        # top left of rectangle becomes top left of window centering it
        self.move(qr.topLeft())

    ####################################################################################################################
    # Helper methods
    ####################################################################################################################
    def scan_usb(self, obj=None):
        self.devices = imx.sdp.scan_usb(self.target)
        self.deviceBox.clear()
        if self.devices:
            for dev in self.devices:
                self.deviceBox.addItem(dev.usbd.info())
            self.deviceBox.setCurrentIndex(0)
            self.deviceBox.setEnabled(True)
            self.devInfoButton.setEnabled(True)
            self.startButton.setEnabled(False if self.target is None else True)
        else:
            self.deviceBox.setEnabled(False)
            self.devInfoButton.setEnabled(False)
            self.startButton.setEnabled(False)

    def Logger(self, msg, clear):
        if clear:
            self.textEdit.clear()
        if msg:
            self.textEdit.append(msg)

    def ProgressBar(self, value):
        self.pgTask.setValue(min(value, PGRANGE))

    def ShowMesageBox(self, title, message, icon=QMessageBox.Warning):
        alert = QMessageBox()
        alert.setWindowTitle(title)
        alert.setText(message)
        alert.setIcon(icon)
        alert.exec_()

    ####################################################################################################################
    # Buttons callback methods
    ####################################################################################################################
    def on_scan_button_clicked(self):
        self.scan_usb()

    def on_open_button_clicked(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            "Choose a SmartBoot script file",
            BASEDIR,
            "i.MX SmartBoot Files (*.smx)",
            options=options)
        if fileName:
            self.smxEdit.clear()
            self.scriptsList.clear()
            try:
                self.smx_file.open(fileName, True)
            except Exception as e:
                self.ShowMesageBox("SMX File Open Error", str(e),
                                   QMessageBox.Warning)
                self.target = None
                self.startButton.setEnabled(False)
            else:
                self.target = self.smx_file.platform
                self.smxEdit.setText(fileName)
                for i, item in enumerate(self.smx_file.scripts):
                    self.scriptsList.addItem("{}.  {}  ({})".format(
                        i, item.name, item.description))
                self.scriptsList.setCurrentRow(0)
                self.scriptsList.adjustSize()
                # update usb device list
                self.scan_usb()

    def on_about_button_clicked(self):
        text = "<b>i.MX SmartBoot Tool</b> v {}".format(core.__version__)
        text += "<p>{}".format(core.DESCRIPTION)
        text += "<p>Copyright &copy; 2018 Martin Olejar."
        text += "<p>License: {}".format(core.__license__)
        text += "<p>Sources: <a href='https://github.com/molejar/imxsb'>https://github.com/molejar/imxsb</a>"
        QMessageBox.about(self, "About", text)

    def on_info_button_clicked(self):
        device = self.devices[self.deviceBox.currentIndex()]
        device.open()
        self.textEdit.clear()
        self.textEdit.append("Device: {} \n".format(device.device_name))
        device.close()

    def on_start_button_clicked(self):
        if self.startButton.text().endswith("Start"):
            try:
                device = self.devices[self.deviceBox.currentIndex()]
                script = self.smx_file.get_script(
                    self.scriptsList.currentRow())
            except Exception as e:
                self.ShowMesageBox("Script Load Error", str(e),
                                   QMessageBox.Warning)
            else:
                # Start Worker
                self.worker = Worker(device, script)
                self.worker.logger.connect(self.Logger)
                self.worker.finish.connect(self.on_finish)
                self.worker.prgbar.connect(self.ProgressBar)
                self.worker.daemon = True
                self.worker.start()

                self.startButton.setText(" Stop")
                self.startButton.setIcon(
                    QIcon.fromTheme("media-playback-stop"))
                self.scanButton.setEnabled(False)
                self.openButton.setEnabled(False)
                self.deviceBox.setEnabled(False)
                self.scriptsList.setEnabled(False)
                self.devInfoButton.setEnabled(False)
        else:
            # Stop Worker
            self.worker.stop()

    def on_finish(self, msg, done):
        self.textEdit.append(msg)
        self.startButton.setText(" Start")
        self.startButton.setIcon(QIcon.fromTheme("media-playback-start"))
        self.scanButton.setEnabled(True)
        self.scriptsList.setEnabled(True)
        self.openButton.setEnabled(True)
        if done:
            self.deviceBox.clear()
            self.startButton.setEnabled(False)
        else:
            self.scan_usb()

    def on_exit_button_clicked(self):
        self.close()
示例#8
0
class ChartDialog(QDialog):
    """The chart dialog"""

    def __init__(self, parent):
        if Figure is None:
            raise ModuleNotFoundError

        super().__init__(parent)

        self.actions = ChartDialogActions(self)

        self.chart_templates_toolbar = ChartTemplatesToolBar(self)

        self.setWindowTitle("Chart dialog")
        self.setModal(True)
        self.resize(800, 600)
        self.parent = parent

        self.actions = ChartDialogActions(self)

        self.dialog_ui()

    def on_template(self):
        """Event handler for pressing a template toolbar button"""

        chart_template_name = self.sender().data()
        chart_template_path = MPL_TEMPLATE_PATH / chart_template_name
        try:
            with open(chart_template_path) as template_file:
                chart_template_code = template_file.read()
        except OSError:
            return

        self.editor.insertPlainText(chart_template_code)

    def dialog_ui(self):
        """Sets up dialog UI"""

        msg = "Enter Python code into the editor to the left. Globals " + \
              "such as X, Y, Z, S are available as they are in the grid. " + \
              "The last line must result in a matplotlib figure.\n \n" + \
              "Pressing Apply displays the figure or an error message in " + \
              "the right area."

        self.message = QTextBrowser(self)
        self.message.setText(msg)
        self.editor = SpellTextEdit(self)
        self.splitter = QSplitter(self)

        buttonbox = self.create_buttonbox()

        self.splitter.addWidget(self.editor)
        self.splitter.addWidget(self.message)
        self.splitter.setOpaqueResize(False)
        self.splitter.setSizes([9999, 9999])

        # Layout
        layout = QVBoxLayout(self)
        layout.addWidget(self.chart_templates_toolbar)

        layout.addWidget(self.splitter)
        layout.addWidget(buttonbox)

        self.setLayout(layout)

    def apply(self):
        """Executes the code in the dialog and updates the canvas"""

        # Get current cell
        key = self.parent.grid.current
        code = self.editor.toPlainText()

        figure = self.parent.grid.model.code_array._eval_cell(key, code)

        if isinstance(figure, Figure):
            canvas = FigureCanvasQTAgg(figure)
            self.splitter.replaceWidget(1, canvas)
            canvas.draw()
        else:
            if isinstance(figure, Exception):
                self.message.setText("Error:\n{}".format(figure))
            else:
                msg_text = "Error:\n{} has type '{}', " + \
                           "which is no instance of {}."
                msg = msg_text.format(figure,
                                      type(figure).__name__,
                                      Figure)
                self.message.setText(msg)
            self.splitter.replaceWidget(1, self.message)

    def create_buttonbox(self):
        """Returns a QDialogButtonBox with Ok and Cancel"""

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Apply
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        button_box.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
        return button_box
示例#9
0
class HelpDialog(QObject, LogMixin):
    """Class implementing qthelp viewer dialog"""

    def __init__(self, qthelp_file, parent = None):
        """
        Constructor of HelpDialog

        :param qthelp_file: full path to qthelp helpfile

        """
        super(HelpDialog,self).__init__(parent)

        # instantiate help engine

        helpEngine = QHelpEngine(qthelp_file)
        helpEngine.setupData()
        self._helpEngine = helpEngine

        # base dialog widget
        self.ui = QDialog(None, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinMaxButtonsHint | QtCore.Qt.WindowCloseButtonHint )

        self.ui.setWindowTitle("HelpViewer")
        self.ui.setWindowIcon(QIcon(":/images/prog_icons/help/help.ico"))

        # Create webview for help information
        # and assign a custom URL scheme handler for scheme "qthelp)

        self._wv = QWebEngineView(self.ui)
        self._urlschemehandler = HelpSchemeHandler(self._helpEngine, self._wv.page().profile())
        self._wv.page().profile().installUrlSchemeHandler(b'qthelp', self._urlschemehandler)

        # get help content overview widget
        self._helpContent = self._helpEngine.contentWidget()
        self._helpIndex = self._helpEngine.indexWidget()
        self._helpSearchQuery = self._helpEngine.searchEngine().queryWidget()
        self._helpSearchResult = self._helpEngine.searchEngine().resultWidget()
        self._se = self._helpEngine.searchEngine()
        self._se.reindexDocumentation()

        self._helpSearchQuery.search.connect(self.search)

        # create QSplitter
        self._splitterMain = QSplitter(QtCore.Qt.Vertical)
        self._splitterMain.setOpaqueResize(False)
        self._splitterSearch = QSplitter(QtCore.Qt.Horizontal)
        self._splitterSearch.setOpaqueResize(False)
        self._splitterUpper = QSplitter(QtCore.Qt.Horizontal)
        self._splitterUpper.setOpaqueResize(False)
        self._splitterLower = QSplitter(QtCore.Qt.Horizontal)
        self._splitterLower.setOpaqueResize(False)

        # create horzLayout
        self._horzLayoutSearch = QHBoxLayout()
        self._horzLayoutUpper = QHBoxLayout()
        self._horzLayoutLower = QHBoxLayout()
        # create vertLayout
        self._vertLayout = QVBoxLayout()

        # main widgets
        self._upperWidget = QWidget()
        self._lowerWidget = QWidget()
        self._btnReset = QPushButton()
        self._btnReset.setMaximumHeight(23)
        self._btnReset.setMaximumWidth(100)

        # build search structure
        self._splitterSearch.insertWidget(0, self._helpSearchQuery)
        self._splitterSearch.insertWidget(1, self._btnReset)

        # build upper inner structure
        self._splitterUpper.insertWidget(0, self._helpContent)
        self._splitterUpper.insertWidget(1, self._wv)
        self._horzLayoutUpper.addWidget(self._splitterUpper)
        self._upperWidget.setLayout(self._horzLayoutUpper)

        # build lower inner structure
        self._splitterLower.insertWidget(0, self._helpIndex)
        self._splitterLower.insertWidget(1, self._helpSearchResult)
        self._horzLayoutLower.addWidget(self._splitterLower)
        self._lowerWidget.setLayout(self._horzLayoutLower)

        # build outer structure
        self._splitterMain.insertWidget(0, self._splitterSearch)
        self._splitterMain.insertWidget(1, self._upperWidget)
        self._splitterMain.insertWidget(2, self._lowerWidget)

        self._helpSearchResult.hide()
        self._btnReset.hide()

        self._vertLayout.addWidget(self._splitterMain)
        self.ui.setLayout(self._vertLayout)

        # set splitter width
        w = self._splitterUpper.geometry().width()
        self._splitterUpper.setSizes([w*(1/4), w*(3/4)])
        w = self._splitterLower.geometry().width()
        self._splitterLower.setSizes([w*(1/5), w*(4/5)])
        h = self._splitterMain.geometry().height()
        self._splitterMain.setSizes([h*(1/9), h*(7/9), h*(1/9)])

        self._helpContent.linkActivated.connect(self._wv.setUrl)
        self._helpIndex.linkActivated.connect(self._wv.setUrl)
        self._helpSearchResult.requestShowLink.connect(self._wv.setUrl)
        self._se.searchingFinished.connect(self.showResults)
        self._btnReset.clicked.connect(self.resetResult)

        self.retranslateMsg()

    def retranslateMsg(self):
        self.logger.debug("Retranslating further messages...")
        self._btnReset.setText(translate("HelpViewer", "Reset"))
        self._btnReset.setText(translate("HelpViewer", "Search"))

    def search(self):
        """Initiate qthelp search"""

        self._se.search(self._helpSearchQuery.query())

    def showResults(self):
        """Show search results, if any"""

        if self._se.hitCount() > 0:
            self._helpIndex.hide()
            h = self._splitterMain.geometry().height()
            self._splitterMain.setSizes([h*(1/3), h*(1/3), h*(1/3)])
            self._helpSearchResult.show()
            self._btnReset.show()

    def resetResult(self):
        """Reset search result widget"""

        self._helpSearchResult.hide()
        self._btnReset.hide()
        self._helpIndex.show()
        h = self._splitterMain.geometry().height()
        self._splitterMain.setSizes([h*(1/9), h*(7/9), h*(1/9)])
示例#10
0
class MainWindow(QMainWindow):

    frame = None
    jupyter_widget = None
    browser_widget = None
    addon_list = []
    current_addon = None  # currently shown addon

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setWindowTitle(main_window_title)
        self.setWindowIcon(QIcon(os.path.join(utils.get_exe_folder(), 
                           'appicon.ico')))

        self.init_jupyter_widget()
        self.init_addon_menu()  
        self.init_splitter()
        self.init_statusbar()
        self.init_help_menu()
        self.setCentralWidget(self.frame)

    def closeEvent(self, event):
        # close all the plots
        # plt.close("all")
        # nothing to close as
        # all the plots are in
        # console
        pass

    def init_help_menu(self):
        menubar = self.menuBar()
        self.__help_menu = menubar.addMenu('Help')

        action = QAction('User guide', self)
        self.__help_menu.addAction(action)
        action.triggered.connect(self.on_help_user_guide)

        action = QAction('License', self)
        self.__help_menu.addAction(action)
        action.triggered.connect(self.on_help_license)

        action = QAction('About...', self)
        self.__help_menu.addAction(action)
        action.triggered.connect(self.on_help_about)

    def on_help_license(self, q):
        self.browser_widget.load_page(license_url)

    def on_help_user_guide(self, q):
        self.browser_widget.load_page(user_guide_url)

    def on_help_about(self, q):
        # main_window_title, app_name, app_version
        text = (app_name + ' version ' + app_version
                + '.\nby ' + author + '.')
        QMessageBox.about(self, main_window_title, text)

    def init_statusbar(self):
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)

    def init_splitter(self):
        self.frame = QFrame()
        self.frame.setFrameShape(QFrame.StyledPanel)
        hbox = QHBoxLayout()  # here should be no 'self' argument
        self.browser_widget = bv.BrowserWidget(self)
        self.top_splitter = QSplitter(Qt.Horizontal)
        frame = QFrame()
        layout = QVBoxLayout()
        for addon in self.addon_list:
            layout.addWidget(addon)
            addon.hide()
        frame.setLayout(layout)        
        self.top_splitter.addWidget(frame)
        self.current_addon = self.addon_list[0]
        self.current_addon.show_itself()
        self.top_splitter.addWidget(self.browser_widget)
        self.top_splitter.setSizes([100, 200])

        handle_width = 6

        # https://stackoverflow.com/questions/2545577/qsplitter-becoming-undistinguishable-between-qwidget-and-qtabwidget
        self.top_splitter.setOpaqueResize(False)
        self.top_splitter.setChildrenCollapsible(False)
        self.top_splitter.setHandleWidth(handle_width)

        splitter2 = QSplitter(Qt.Vertical)
        splitter2.addWidget(self.top_splitter)
        splitter2.addWidget(self.jupyter_widget)
        splitter2.setOpaqueResize(False)
        splitter2.setChildrenCollapsible(False)
        splitter2.setHandleWidth(handle_width)

        hbox.addWidget(splitter2)

        self.frame.setLayout(hbox)

    def init_jupyter_widget(self):
        self.jupyter_widget = make_jupyter_widget_with_kernel()

    def shutdown_kernel(self):
        print('Shutting down kernel...')
        self.jupyter_widget.kernel_client.stop_channels()
        self.jupyter_widget.kernel_manager.shutdown_kernel()

    def init_addon_menu(self):
        self.__menubar = self.menuBar()
        addon_list = addon_data.addon_list
        self.__addon_menu = self.__menubar.addMenu('Addons')
        for addon_group in addon_list:
            group_menu = self.__addon_menu.addMenu(addon_group.menu_name)
            for addon in addon_group.addons:
                action = QAction(addon.menu_name, self)
                group_menu.addAction(action)
                self.inputs_widget = InputsWidget(self, addon)
                action.triggered.connect(self.inputs_widget.show_itself)
                self.addon_list.append(self.inputs_widget)
示例#11
0
class View(QMainWindow):
    def __init__(self, model, controller):
        super().__init__()

        self._model = model
        self._controller = controller
        self.segmentcursor = False
        self.togglecolors = {"#1f77b4": "m", "m": "#1f77b4"}

        #################################################################
        # define GUI layout and connect input widgets to external slots #
        #################################################################

        self.setWindowTitle("biopeaks")
        self.setGeometry(50, 50, 1750, 750)
        self.setWindowIcon(QIcon(":/python_icon.png"))

        # figure0 for signal
        self.figure0 = Figure()
        self.canvas0 = FigureCanvas(self.figure0)
        self.ax00 = self.figure0.add_subplot(1, 1, 1)
        self.ax00.set_frame_on(False)
        self.figure0.subplots_adjust(left=0.04, right=0.98, bottom=0.25)
        self.line00 = None
        self.scat = None
        self.segmentspan = None

        # figure1 for marker
        self.figure1 = Figure()
        self.canvas1 = FigureCanvas(self.figure1)
        self.ax10 = self.figure1.add_subplot(1, 1, 1, sharex=self.ax00)
        self.ax10.get_xaxis().set_visible(False)
        self.ax10.set_frame_on(False)
        self.figure1.subplots_adjust(left=0.04, right=0.98)
        self.line10 = None

        # figure2 for statistics
        self.figure2 = Figure()
        self.canvas2 = FigureCanvas(self.figure2)
        self.ax20 = self.figure2.add_subplot(3, 1, 1, sharex=self.ax00)
        self.ax20.get_xaxis().set_visible(False)
        self.ax20.set_frame_on(False)
        self.line20 = None
        self.ax21 = self.figure2.add_subplot(3, 1, 2, sharex=self.ax00)
        self.ax21.get_xaxis().set_visible(False)
        self.ax21.set_frame_on(False)
        self.line21 = None
        self.ax22 = self.figure2.add_subplot(3, 1, 3, sharex=self.ax00)
        self.ax22.get_xaxis().set_visible(False)
        self.ax22.set_frame_on(False)
        self.line22 = None
        self.figure2.subplots_adjust(left=0.04, right=0.98)

        # navigation bar
        self.navitools = CustomNavigationToolbar(self.canvas0, self)

        # peak editing
        self.editcheckbox = QCheckBox("editable", self)
        self.editcheckbox.stateChanged.connect(self._model.set_peakseditable)

        # peak saving batch
        self.savecheckbox = QCheckBox("save during batch processing", self)
        self.savecheckbox.stateChanged.connect(self._model.set_savebatchpeaks)

        # peak auto-correction batch
        self.correctcheckbox = QCheckBox("correct during batch processing",
                                         self)
        self.correctcheckbox.stateChanged.connect(
            self._model.set_correctbatchpeaks)

        # selecting stats for saving
        self.periodcheckbox = QCheckBox("period", self)
        self.periodcheckbox.stateChanged.connect(
            lambda: self.select_stats("period"))
        self.ratecheckbox = QCheckBox("rate", self)
        self.ratecheckbox.stateChanged.connect(
            lambda: self.select_stats("rate"))
        self.tidalampcheckbox = QCheckBox("tidal amplitude", self)
        self.tidalampcheckbox.stateChanged.connect(
            lambda: self.select_stats("tidalamp"))

        # channel selection
        self.sigchanmenulabel = QLabel("biosignal")
        self.sigchanmenu = QComboBox(self)
        self.sigchanmenu.addItem("A1")
        self.sigchanmenu.addItem("A2")
        self.sigchanmenu.addItem("A3")
        self.sigchanmenu.addItem("A4")
        self.sigchanmenu.addItem("A5")
        self.sigchanmenu.addItem("A6")
        self.sigchanmenu.currentTextChanged.connect(self._model.set_signalchan)
        # initialize with default value
        self._model.set_signalchan(self.sigchanmenu.currentText())

        self.markerchanmenulabel = QLabel("marker")
        self.markerchanmenu = QComboBox(self)
        self.markerchanmenu.addItem("none")
        self.markerchanmenu.addItem("I1")
        self.markerchanmenu.addItem("I2")
        self.markerchanmenu.addItem("A1")
        self.markerchanmenu.addItem("A2")
        self.markerchanmenu.addItem("A3")
        self.markerchanmenu.addItem("A4")
        self.markerchanmenu.addItem("A5")
        self.markerchanmenu.addItem("A6")
        self.markerchanmenu.currentTextChanged.connect(
            self._model.set_markerchan)
        # initialize with default value
        self._model.set_markerchan(self.markerchanmenu.currentText())

        # processing mode (batch or single file)
        self.batchmenulabel = QLabel("mode")
        self.batchmenu = QComboBox(self)
        self.batchmenu.addItem("single file")
        self.batchmenu.addItem("multiple files")
        self.batchmenu.currentTextChanged.connect(self._model.set_batchmode)
        self.batchmenu.currentTextChanged.connect(self.toggle_options)
        # initialize with default value
        self._model.set_batchmode(self.batchmenu.currentText())
        self.toggle_options(self.batchmenu.currentText())

        # modality selection
        self.modmenulabel = QLabel("modality")
        self.modmenu = QComboBox(self)
        self.modmenu.addItem("ECG")
        self.modmenu.addItem("PPG")
        self.modmenu.addItem("RESP")
        self.modmenu.currentTextChanged.connect(self._model.set_modality)
        self.modmenu.currentTextChanged.connect(self.toggle_options)
        # initialize with default value
        self._model.set_modality(self.modmenu.currentText())
        self.toggle_options(self.modmenu.currentText())

        # segment selection; this widget can be openend / set visible from
        # the menu and closed from within itself (see mapping of segmentermap);
        # it provides utilities to select a segment from the signal
        self.segmentermap = QSignalMapper(self)
        self.segmenter = QDockWidget("select a segment", self)
        # disable closing such that widget can only be closed by confirming
        # selection or custom button
        self.segmenter.setFeatures(QDockWidget.NoDockWidgetFeatures)
        # Limit number of decimals to four.
        regex = QRegExp("[0-9]*\.?[0-9]{4}")
        validator = QRegExpValidator(regex)

        self.startlabel = QLabel("start")
        self.startedit = QLineEdit()
        self.startedit.setValidator(validator)

        self.endlabel = QLabel("end")
        self.endedit = QLineEdit()
        self.endedit.setValidator(validator)

        segmentfromcursor = QAction(QIcon(":/mouse_icon.png"),
                                    "select with mouse", self)
        segmentfromcursor.triggered.connect(self.enable_segmentedit)
        self.startedit.addAction(segmentfromcursor, 1)
        self.endedit.addAction(segmentfromcursor, 1)

        self.previewedit = QPushButton("preview segment")
        lambdafn = lambda: self._model.set_segment(
            [self.startedit.text(), self.endedit.text()])
        self.previewedit.clicked.connect(lambdafn)

        self.confirmedit = QPushButton("confirm segment")
        self.confirmedit.clicked.connect(self._controller.segment_signal)
        self.confirmedit.clicked.connect(self.segmentermap.map)
        self.segmentermap.setMapping(self.confirmedit, 0)

        self.abortedit = QPushButton("abort segmentation")
        self.abortedit.clicked.connect(self.segmentermap.map)
        # reset the segment to None
        self.segmentermap.setMapping(self.abortedit, 2)

        self.segmenterlayout = QFormLayout()
        self.segmenterlayout.addRow(self.startlabel, self.startedit)
        self.segmenterlayout.addRow(self.endlabel, self.endedit)
        self.segmenterlayout.addRow(self.previewedit)
        self.segmenterlayout.addRow(self.confirmedit)
        self.segmenterlayout.addRow(self.abortedit)
        self.segmenterwidget = QWidget()
        self.segmenterwidget.setLayout(self.segmenterlayout)
        self.segmenter.setWidget(self.segmenterwidget)

        self.segmenter.setVisible(False)
        self.segmenter.setAllowedAreas(Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.RightDockWidgetArea, self.segmenter)

        # set up menubar
        menubar = self.menuBar()

        # signal menu
        signalmenu = menubar.addMenu("biosignal")

        openSignal = QAction("load", self)
        openSignal.triggered.connect(self._controller.get_fpaths)
        signalmenu.addAction(openSignal)

        segmentSignal = QAction("select segment", self)
        segmentSignal.triggered.connect(self.segmentermap.map)
        self.segmentermap.setMapping(segmentSignal, 1)
        signalmenu.addAction(segmentSignal)

        self.segmentermap.mapped.connect(self.toggle_segmenter)

        saveSignal = QAction("save", self)
        saveSignal.triggered.connect(self._controller.get_wpathsignal)
        signalmenu.addAction(saveSignal)

        # peak menu
        peakmenu = menubar.addMenu("peaks")

        findPeaks = QAction("find", self)
        findPeaks.triggered.connect(self._controller.find_peaks)
        peakmenu.addAction(findPeaks)

        autocorrectPeaks = QAction("autocorrect", self)
        autocorrectPeaks.triggered.connect(self._controller.autocorrect_peaks)
        peakmenu.addAction(autocorrectPeaks)

        savePeaks = QAction("save", self)
        savePeaks.triggered.connect(self._controller.get_wpathpeaks)
        peakmenu.addAction(savePeaks)

        loadPeaks = QAction("load", self)
        loadPeaks.triggered.connect(self._controller.get_rpathpeaks)
        peakmenu.addAction(loadPeaks)

        # stats menu
        statsmenu = menubar.addMenu("statistics")

        calculateStats = QAction("calculate", self)
        calculateStats.triggered.connect(self._controller.calculate_stats)
        statsmenu.addAction(calculateStats)

        saveStats = QAction("save", self)
        saveStats.triggered.connect(self._controller.get_wpathstats)
        statsmenu.addAction(saveStats)

        # set up status bar to display error messages and current file path
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, 1)
        self.statusBar.addPermanentWidget(self.progressBar)
        self.currentFile = QLabel()
        self.statusBar.addPermanentWidget(self.currentFile)

        # set up the central widget containing the plot and navigationtoolbar
        self.centwidget = QWidget()
        self.setCentralWidget(self.centwidget)

        # connect canvas0 to keyboard and mouse input for peak editing;
        # only widgets (e.g. canvas) that currently have focus capture
        # keyboard input: "You must enable keyboard focus for a widget if
        # it processes keyboard events."
        self.canvas0.setFocusPolicy(Qt.ClickFocus)
        self.canvas0.setFocus()
        self.canvas0.mpl_connect("key_press_event",
                                 self._controller.edit_peaks)
        self.canvas0.mpl_connect("button_press_event", self.get_xcursor)

        # arrange the three figure canvases in splitter object
        self.splitter = QSplitter(Qt.Vertical)
        # setting opaque resizing to false is important, since resizing gets
        # very slow otherwise once axes are populated
        self.splitter.setOpaqueResize(False)
        self.splitter.addWidget(self.canvas0)
        self.splitter.addWidget(self.canvas1)
        self.splitter.addWidget(self.canvas2)

        # define GUI layout
        self.vlayout0 = QVBoxLayout(self.centwidget)
        self.vlayout1 = QVBoxLayout()
        self.vlayoutA = QFormLayout()
        self.vlayoutB = QFormLayout()
        self.vlayoutC = QVBoxLayout()
        self.vlayoutD = QVBoxLayout()
        self.hlayout0 = QHBoxLayout()
        self.hlayout1 = QHBoxLayout()

        self.optionsgroupA = QGroupBox("processing options")
        self.vlayoutA.addRow(self.modmenulabel, self.modmenu)
        self.vlayoutA.addRow(self.batchmenulabel, self.batchmenu)
        self.optionsgroupA.setLayout(self.vlayoutA)

        self.optionsgroupB = QGroupBox("channels")
        self.vlayoutB.addRow(self.sigchanmenulabel, self.sigchanmenu)
        self.vlayoutB.addRow(self.markerchanmenulabel, self.markerchanmenu)
        self.optionsgroupB.setLayout(self.vlayoutB)

        self.optionsgroupC = QGroupBox("peak options")
        self.vlayoutC.addWidget(self.editcheckbox)
        self.vlayoutC.addWidget(self.savecheckbox)
        self.vlayoutC.addWidget(self.correctcheckbox)
        self.optionsgroupC.setLayout(self.vlayoutC)

        self.optionsgroupD = QGroupBox("select statistics for saving")
        self.vlayoutD.addWidget(self.periodcheckbox)
        self.vlayoutD.addWidget(self.ratecheckbox)
        self.vlayoutD.addWidget(self.tidalampcheckbox)
        self.optionsgroupD.setLayout(self.vlayoutD)

        self.vlayout1.addWidget(self.optionsgroupA)
        self.vlayout1.addWidget(self.optionsgroupB)
        self.vlayout1.addWidget(self.optionsgroupC)
        self.vlayout1.addWidget(self.optionsgroupD)
        self.hlayout0.addLayout(self.vlayout1)
        self.hlayout0.addWidget(self.splitter)
        self.hlayout0.setStretch(0, 1)
        self.hlayout0.setStretch(1, 15)
        self.vlayout0.addLayout(self.hlayout0)

        self.hlayout1.addWidget(self.navitools)
        self.vlayout0.addLayout(self.hlayout1)

        ##############################################
        # connect output widgets to external signals #
        ##############################################
        self._model.signal_changed.connect(self.plot_signal)
        self._model.marker_changed.connect(self.plot_marker)
        self._model.peaks_changed.connect(self.plot_peaks)
        self._model.period_changed.connect(self.plot_period)
        self._model.rate_changed.connect(self.plot_rate)
        self._model.tidalamp_changed.connect(self.plot_tidalamp)
        self._model.path_changed.connect(self.display_path)
        self._model.segment_changed.connect(self.plot_segment)
        self._model.status_changed.connect(self.display_status)
        self._model.progress_changed.connect(self.display_progress)
        self._model.model_reset.connect(self.reset_plot)

    ###########
    # methods #
    ###########

    def plot_signal(self, value):
        self.ax00.clear()
        self.ax00.relim()
        # reset navitools history
        self.navitools.update()
        self.line00 = self.ax00.plot(self._model.sec, value, zorder=1)
        self.ax00.set_xlabel("seconds", fontsize="large", fontweight="heavy")
        self.canvas0.draw()
#        print("plot_signal listening")
#        print(self.ax0.collections, self.ax0.patches, self.ax0.artists)

    def plot_peaks(self, value):
        # self.scat is listed in ax.collections
        if self.ax00.collections:
            self.ax00.collections[0].remove()
        self.scat = self.ax00.scatter(self._model.sec[value],
                                      self._model.signal[value],
                                      c="m",
                                      zorder=2)
        self.canvas0.draw()
#        print("plot_peaks listening")
#        print(self.ax0.collections, self.ax0.patches, self.ax0.artists)

    def plot_segment(self, value):
        # If an invalid signal has been selected reset the segmenter interface.
        if value is None:
            self.toggle_segmenter(1)
            return
        if self.ax00.patches:  # self.segementspan is listed in ax.patches
            self.ax00.patches[0].remove()
        self.segmentspan = self.ax00.axvspan(value[0],
                                             value[1],
                                             color="m",
                                             alpha=0.25)
        self.canvas0.draw()
        self.confirmedit.setEnabled(True)
#        print(self.ax0.collections, self.ax0.patches, self.ax0.artists)

    def plot_marker(self, value):
        self.ax10.clear()
        self.ax10.relim()
        self.line10 = self.ax10.plot(value[0], value[1])
        self.canvas1.draw()
#        print("plot_marker listening")

    def plot_period(self, value):
        self.ax20.clear()
        self.ax20.relim()
        self.navitools.home()
        if self._model.savestats["period"]:
            self.line20 = self.ax20.plot(self._model.sec, value, c="m")
        else:
            self.line20 = self.ax20.plot(self._model.sec, value)
        self.ax20.set_ylim(bottom=min(value), top=max(value))
        self.ax20.set_title("period", pad=0, fontweight="heavy")
        self.ax20.grid(True, axis="y")
        self.navitools.update()
        self.canvas2.draw()
#        print("plot_period listening")

    def plot_rate(self, value):
        self.ax21.clear()
        self.ax21.relim()
        self.navitools.home()
        if self._model.savestats["rate"]:
            self.line21 = self.ax21.plot(self._model.sec, value, c="m")
        else:
            self.line21 = self.ax21.plot(self._model.sec, value)
        self.ax21.set_ylim(bottom=min(value), top=max(value))
        self.ax21.set_title("rate", pad=0, fontweight="heavy")
        self.ax21.grid(True, axis="y")
        self.navitools.update()
        self.canvas2.draw()
#        print("plot_rate listening")

    def plot_tidalamp(self, value):
        self.ax22.clear()
        self.ax22.relim()
        self.navitools.home()
        if self._model.savestats["tidalamp"]:
            self.line22 = self.ax22.plot(self._model.sec, value, c="m")
        else:
            self.line22 = self.ax22.plot(self._model.sec, value)
        self.ax22.set_ylim(bottom=min(value), top=max(value))
        self.ax22.set_title("amplitude", pad=0, fontweight="heavy")
        self.ax22.grid(True, axis="y")
        self.navitools.update()
        self.canvas2.draw()
#        print("plot_tidalamp listening")

    def display_path(self, value):
        self.currentFile.setText(value)

    def display_status(self, status):
        # display status until new status is set
        self.statusBar.showMessage(status)

    def display_progress(self, value):
        # if value is 0, the progressbar indicates a busy state
        self.progressBar.setRange(0, value)

    def toggle_segmenter(self, value):
        if self._model.loaded:
            # Open segmenter when called from signalmenu or clear segmenter
            # upon selection of invalid segment.
            if value == 1:
                self.segmenter.setVisible(True)
                self.confirmedit.setEnabled(False)
                self.startedit.clear()
                self.endedit.clear()
                if self.ax00.patches:
                    self.ax00.patches[0].remove()
                    self.canvas0.draw()
            # Close segmenter after segment has been confirmed.
            elif value == 0:
                self.segmenter.setVisible(False)
                if self.ax00.patches:
                    self.ax00.patches[0].remove()
                    self.canvas0.draw()
            # Close segmenter after segmentation has been aborted (reset
            # segment).
            elif value == 2:
                self._model.set_segment(
                    [0, 0])  # This will reset the model to None
                self.segmenter.setVisible(False)
                if self.ax00.patches:
                    self.ax00.patches[0].remove()
                    self.canvas0.draw()

    def enable_segmentedit(self):
        # disable peak editing to avoid interference
        self.editcheckbox.setCheckState(0)
        if self.startedit.hasFocus():
            self.segmentcursor = "start"
        elif self.endedit.hasFocus():
            self.segmentcursor = "end"

    def get_xcursor(self, event):
        # event.button 1 corresponds to left mouse button
        if event.button == 1:
            # limit number of decimal places to two
            if self.segmentcursor == "start":
                self.startedit.selectAll()
                self.startedit.insert("{:.2f}".format(event.xdata))
            elif self.segmentcursor == "end":
                self.endedit.selectAll()
                self.endedit.insert("{:.2f}".format(event.xdata))
            # disable segment cursor again after value has been set
            self.segmentcursor = False

    def select_stats(self, event):
        """
        select or deselect statistics to be saved; toggle boolean with xor
        operator ^=, toggle color with dictionary
        """
        self._model.savestats[event] ^= True
        line = None
        if event == "period":
            if self.line20:
                line = self.line20[0]
        elif event == "rate":
            if self.line21:
                line = self.line21[0]
        elif event == "tidalamp":
            if self.line22:
                line = self.line22[0]
        if line:
            line.set_color(self.togglecolors[line.get_color()])
        self.canvas2.draw()

    def toggle_options(self, event):
        if event in ["ECG", "PPG"]:
            self.tidalampcheckbox.setEnabled(False)
            self.tidalampcheckbox.setChecked(False)
            self.ax22.set_visible(False)
            self.canvas2.draw()
        elif event == "RESP":
            self.tidalampcheckbox.setEnabled(True)
            self.ax22.set_visible(True)
            self.canvas2.draw()
        elif event == "multiple files":
            self.editcheckbox.setEnabled(False)
            self.editcheckbox.setChecked(False)
            self.savecheckbox.setEnabled(True)
            self.correctcheckbox.setEnabled(True)
            self.markerchanmenu.setEnabled(False)
        elif event == "single file":
            self.editcheckbox.setEnabled(True)
            self.markerchanmenu.setEnabled(True)
            self.savecheckbox.setEnabled(False)
            self.savecheckbox.setChecked(False)
            self.correctcheckbox.setEnabled(False)
            self.correctcheckbox.setChecked(False)

    def reset_plot(self):
        self.ax00.clear()
        self.ax00.relim()
        self.line00 = None
        self.scat = None
        self.segmentspan = None
        self.ax10.clear()
        self.ax10.relim()
        self.line10 = None
        self.ax20.clear()
        self.ax20.relim()
        self.line20 = None
        self.ax21.clear()
        self.ax21.relim()
        self.line21 = None
        self.ax22.clear()
        self.ax22.relim()
        self.line22 = None
        self.canvas0.draw()
        self.canvas1.draw()
        self.canvas2.draw()
        self.navitools.update()
        self.currentFile.clear()
示例#12
0
    def __init__(self, parent=None):
        super(StockDialog, self).__init__(parent)
        self.setWindowTitle(self.tr("渐变效果"))

        self.startColor = Qt.green
        self.endColor = Qt.blue
        self.style = QGradient.LinearGradient
        self.spread = QGradient.PadSpread

        mainSplitter = QSplitter(Qt.Horizontal)
        mainSplitter.setOpaqueResize(True)

        frame = QFrame(mainSplitter)
        mainLayout = QGridLayout(frame)
        # mainLayout.setContentsMargins()
        # mainLayout.setMargin(10)
        # mainLayout.setSpacing(6)

        stack1 = QStackedWidget()
        stack1.setFrameStyle(QFrame.Panel | QFrame.Raised)

        mainSplitter1 = QSplitter(Qt.Horizontal)
        mainSplitter1.setOpaqueResize(True)

        self.area = PaintArea(self)

        stack1.addWidget(self.area)
        frame1 = QFrame(mainSplitter1)
        mainLayout1 = QVBoxLayout(frame1)
        # mainLayout1.setMargin(10)
        # mainLayout1.setSpacing(6)
        mainLayout1.addWidget(stack1)

        self.startPushButton = QPushButton(self.tr("start"))
        self.startPushButton.setAutoFillBackground(True)
        self.startPushButton.setPalette(QPalette(Qt.green))

        self.endPushButton = QPushButton(self.tr("end"))
        self.endPushButton.setAutoFillBackground(True)
        self.endPushButton.setPalette(QPalette(Qt.blue))

        self.startPushButton.clicked.connect(self.slotStartColor)
        self.endPushButton.clicked.connect(self.slotEndColor)
        # self.connect(self.startPushButton, SIGNAL("clicked()"), self.slotStartColor)
        # self.connect(self.endPushButton, SIGNAL("clicked()"), self.slotEndColor)

        self.grdientComboBox = QComboBox()
        self.grdientComboBox.addItem(self.tr("Linear Gradient"), QGradient.LinearGradient)
        self.grdientComboBox.addItem(self.tr("Radial Gradient"), QGradient.RadialGradient)
        self.grdientComboBox.addItem(self.tr("Conical Gradient"), QGradient.ConicalGradient)
        self.grdientComboBox.activated.connect(self.slotSetStyle)
        # self.connect(self.grdientComboBox, SIGNAL("activated(int)"), self.slotSetStyle)

        self.spreadComboBox = QComboBox()
        self.spreadComboBox.addItem(self.tr("PadSpread"), QGradient.PadSpread)
        self.spreadComboBox.addItem(self.tr("RepeatSpread"), QGradient.RepeatSpread)
        self.spreadComboBox.addItem(self.tr("ReflctSpread"), QGradient.ReflectSpread)
        self.spreadComboBox.activated.connect(self.slotSetSpread)
        # self.connect(self.spreadComboBox, SIGNAL("activated(int)"), self.slotSetSpread)

        mainLayout.addWidget(self.startPushButton, 1, 0)
        mainLayout.addWidget(self.endPushButton, 1, 1)
        mainLayout.addWidget(self.grdientComboBox, 1, 2)
        mainLayout.addWidget(self.spreadComboBox, 1, 3)

        layout = QGridLayout(self)
        layout.addWidget(mainSplitter1, 0, 0)
        layout.addWidget(mainSplitter, 1, 0)
        self.setLayout(layout)