示例#1
0
    def __createLayout(self, varName, varType, varValue, isGlobal):
        """Creates the dialog layout"""
        varTypeParts = varType.split()
        if varTypeParts[0].lower() in ["string", "unicode", "qstring"]:
            length = str(len(varValue))
            lines = str(len(varValue.splitlines()))
            varType = varType.split("(")[0].strip() + \
                      " (lines: " + lines + ", characters: " + length + ")"

        self.resize(600, 250)
        self.setSizeGripEnabled(True)

        # Top level layout
        layout = QVBoxLayout(self)

        gridLayout = QGridLayout()
        gridLayout.setSpacing(4)
        varScopeLabel = QLabel("Scope:", self)
        gridLayout.addWidget(varScopeLabel, 0, 0, Qt.AlignCenter)
        varScopeValue = HeaderLabel('Global' if isGlobal else 'Local',
                                    parent=self)
        varScopeValue.setToolTip("Double click to copy")
        font = varScopeValue.font()
        font.setFamily(GlobalData().skin['monoFont'].family())
        gridLayout.addWidget(varScopeValue, 0, 1)

        varNameLabel = QLabel("Name:", self)
        gridLayout.addWidget(varNameLabel, 1, 0, Qt.AlignCenter)
        varNameValue = HeaderLabel(varName, parent=self)
        varNameValue.setToolTip("Double click to copy")
        gridLayout.addWidget(varNameValue, 1, 1)

        varTypeLabel = QLabel("Type:", self)
        gridLayout.addWidget(varTypeLabel, 2, 0, Qt.AlignCenter)
        varTypeValue = HeaderLabel(varType, parent=self)
        varTypeValue.setToolTip("Double click to copy")
        gridLayout.addWidget(varTypeValue, 2, 1)

        varValueLabel = QLabel("Value:", self)
        gridLayout.addWidget(varValueLabel, 3, 0, Qt.AlignTop)
        varValueValue = QTextEdit()
        varValueValue.setReadOnly(True)
        varValueValue.setFont(getZoomedMonoFont())
        # varValueValue.setLineWrapMode(QTextEdit.NoWrap)
        varValueValue.setAcceptRichText(False)
        varValueValue.setPlainText(varValue)
        gridLayout.addWidget(varValueValue, 3, 1)
        layout.addLayout(gridLayout)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        self.__OKButton = buttonBox.button(QDialogButtonBox.Ok)
        self.__OKButton.setDefault(True)
        buttonBox.accepted.connect(self.close)
        buttonBox.rejected.connect(self.close)
        layout.addWidget(buttonBox)

        varValueValue.setFocus()
示例#2
0
文件: ut.py 项目: topin89/codimension
class MainWindow(QMainWindow):
    """Main application window"""
    def __init__(self, verbose, fName, warning):
        QMainWindow.__init__(self)

        self.logWidget = None
        self.view = None
        self.scene = None
        self.fName = fName
        self.verbose = verbose
        self.cFlow = None

        self.resize(1400, 800)

        self.updateWindowTitle()
        self.statusBar()
        self.createToolbar()
        self.createLogWindow()
        self.createGraphicsView()

        self.setCentralWidget(self.view)

        if verbose:
            self.logMessage("Using cdmcfparser version " + VERSION)

        if warning:
            self.logMessage(warning)

        if fName:
            # To yeld the main message processing loop
            kickOffTimer = QTimer()
            kickOffTimer.singleShot(200, self.proceedWithFile)

    def createToolbar(self):
        """There are a few buttons on the main window toolbar.

           They are: open, reload, zoom out, zoom in, debug, clear log
        """
        openButton = QAction(QIcon('icons/open.png'), 'Open (Ctrl+O)', self)
        openButton.setShortcut('Ctrl+O')
        openButton.setStatusTip('Open python file')
        openButton.triggered.connect(self.openButtonClicked)

        reloadButton = QAction(QIcon('icons/reload.png'), 'Reload (F5)', self)
        reloadButton.setShortcut('F5')
        reloadButton.setStatusTip('Reload python file')
        reloadButton.triggered.connect(self.reloadButtonClicked)

        zoomoutButton = QAction(QIcon('icons/zoomOut.png'),
                                'Zoom Out (Ctrl+-)', self)
        zoomoutButton.setShortcut('Ctrl+-')
        zoomoutButton.setStatusTip('Zoom Out')
        zoomoutButton.triggered.connect(self.zoomOut)

        zoominButton = QAction(QIcon('icons/zoomIn.png'), 'Zoom In (Ctrl++)',
                               self)
        zoominButton.setShortcut('Ctrl++')
        zoominButton.setStatusTip('Zoom In')
        zoominButton.triggered.connect(self.zoomIn)

        clearLogButton = QAction(QIcon('icons/clear.png'),
                                 'Clear log (Ctrl+R)', self)
        clearLogButton.setShortcut('Ctrl+R')
        clearLogButton.setStatusTip('Clear log')
        clearLogButton.triggered.connect(self.clearButtonClicked)

        # A few separators
        separator = QAction(self)
        separator.setSeparator(True)
        separator1 = QAction(self)
        separator1.setSeparator(True)

        toolbar = self.addToolBar('Toolbar')
        toolbar.setIconSize(QSize(48, 48))
        toolbar.addAction(openButton)
        toolbar.addAction(reloadButton)
        toolbar.addAction(separator)
        toolbar.addAction(zoomoutButton)
        toolbar.addAction(zoominButton)
        toolbar.addAction(separator1)
        toolbar.addAction(clearLogButton)

    def createLogWindow(self):
        """Creates a dockable RO editor for logging"""
        self.logWidget = QTextEdit()
        self.logWidget.setReadOnly(True)
        self.logWidget.setFontFamily("Courier")
        self.logWidget.setFontPointSize(12.0)

        logDockWidget = QDockWidget("Log", self)
        logDockWidget.setObjectName("LogDockWidget")
        logDockWidget.setAllowedAreas(Qt.BottomDockWidgetArea)
        logDockWidget.setWidget(self.logWidget)

        self.addDockWidget(Qt.BottomDockWidgetArea, logDockWidget)

    def zoomIn(self):
        """zoom in the main window"""
        self.view.zoomIn()

    def zoomOut(self):
        """zoom out the main window"""
        self.view.zoomOut()

    def reloadButtonClicked(self):
        """reload button has been clicked"""
        self.proceedWithFile()

    def clearButtonClicked(self):
        """Deletes all the messages from the log window"""
        self.logWidget.clear()

    def createGraphicsView(self):
        """Creates the central widget"""
        self.scene = QGraphicsScene(self)

        self.view = CFGraphicsView(self)
        self.view.setScene(self.scene)

    def updateWindowTitle(self):
        """updates the main window title with the current so file"""
        if self.fName:
            self.setWindowTitle('Control flow for: ' + self.fName)
        else:
            self.setWindowTitle('Control flow for: no file selected')

    def logMessage(self, message):
        """Makes a log message visible in the user interface"""
        timestamp = datetime.datetime.now().strftime('%m-%d-%y %H:%M:%S.%f')
        self.logWidget.append(timestamp + " " + message)
        self.logWidget.update()

    def openButtonClicked(self):
        """Brings up an open dialogue"""
        # By some unknown reasons the following simple way of getting a file is
        # not working:
        # fileName = QFileDialog.getOpenFileName(self, 'Open file',
        #                                        QDir.currentPath())
        #
        # There is however a workaround. Here it is:
        dialog = QFileDialog(self)
        if dialog.exec_() != QDialog.Accepted:
            return

        fileNames = dialog.selectedFiles()
        fileName = str(fileNames[0])

        if not os.path.exists(fileName):
            QMessageBox.critical(
                self, 'Error',
                'The selected file (' + fileName + ') does not exist')
            return

        # Check that the file is a python one
        warning = isPythonFile(fileName)
        if warning is not None:
            QMessageBox.critical(self, 'Error', warning)
            return

        # set the new file name
        self.fName = fileName
        self.updateWindowTitle()

        # initiate the process
        self.proceedWithFile()

    def proceedWithFile(self, needToParse=True):
        """Taks the file from settings and processes it"""
        if needToParse:
            if self.verbose:
                self.logMessage("Parsing file " + self.fName)
            self.cFlow = getControlFlowFromFile(self.fName)
            if self.verbose:
                self.logMessage("Parsed file:")
                self.logMessage(formatFlow(str(self.cFlow)))

            if len(self.cFlow.errors) != 0:
                self.logMessage("No drawing due to parsing errors")
                return

            if len(self.cFlow.warnings) != 0:
                self.logMessage("Parser warnings: ")
                for warn in self.cFlow.warnings:
                    self.logMessage(str(warn[0]) + ": " + warn[1])
        else:
            if self.cFlow is None:
                self.logMessage("No control flow object")
                return
            if len(self.cFlow.errors) != 0:
                self.logMessage("No drawing due to parsing errors")
                return

        self.scene.clear()

        if self.verbose:
            self.logMessage("Layouting ...")
        try:
            # To pick up possibly changed settings
            importlib.reload(cflowsettings)
            cflowSettings = cflowsettings.getDefaultCflowSettings(self)
            if DEBUG:
                cflowSettings.debug = True

            # Top level canvas has no adress and no parent canvas
            canvas = vcanvas.VirtualCanvas(cflowSettings, None, None, None)
            canvas.layout(self.cFlow, CellElement.FILE_SCOPE)
            if self.verbose:
                self.logMessage("Layout is done:")
                self.logMessage(str(canvas))
                self.logMessage("Rendering ...")

            width, height = canvas.render()
            if self.verbose:
                self.logMessage("Rendering is done. Scene size: " +
                                str(width) + "x" + str(height) +
                                ". Drawing ...")

            self.scene.setSceneRect(0, 0, width, height)
            canvas.draw(self.scene, 0, 0)
        except Exception as exc:
            self.logMessage("Exception:\n" + str(exc))
            raise

        if self.verbose:
            self.logMessage("Drawing is done.")
示例#3
0
class PluginsDialog(QDialog):
    """Codimension plugins dialog"""
    def __init__(self, pluginManager, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle("Plugin Manager")

        self.__pluginManager = pluginManager
        self.__configFuncs = {}  # int -> callable

        self.__createLayout()
        self.__populate()

        self.__pluginsView.setFocus()
        self.__inItemChange = False

    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        layout = QVBoxLayout()

        # Plugins list
        self.__pluginsView = QTreeWidget()
        self.__pluginsView.setAlternatingRowColors(True)
        self.__pluginsView.setRootIsDecorated(False)
        self.__pluginsView.setItemsExpandable(False)
        self.__pluginsView.setSortingEnabled(True)
        self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__pluginsView.setUniformRowHeights(True)

        # Alert | system/user | Enable | Name | Version
        self.__pluginsHeader = QTreeWidgetItem(
            ["", "", "", "Name", "Version", ""])
        self.__pluginsView.setHeaderItem(self.__pluginsHeader)
        self.__pluginsView.header().setSortIndicator(NAME_COL,
                                                     Qt.AscendingOrder)
        self.__pluginsView.itemSelectionChanged.connect(
            self.__pluginSelectionChanged)
        self.__pluginsView.itemChanged.connect(self.__onItemChanged)

        layout.addWidget(self.__pluginsView)

        # Detailed information
        detailsLabel = QLabel("Detailed information")
        layout.addWidget(detailsLabel)
        self.__details = QTreeWidget()
        self.__details.setAlternatingRowColors(False)
        self.__details.setRootIsDecorated(False)
        self.__details.setItemsExpandable(False)
        self.__details.setSortingEnabled(False)
        self.__details.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__details.setUniformRowHeights(True)

        detailsHeader = QTreeWidgetItem(["", ""])
        self.__details.setHeaderItem(detailsHeader)
        self.__details.setHeaderHidden(True)

        metrics = QFontMetrics(self.__details.font())
        rect = metrics.boundingRect("X")
        self.__details.setFixedHeight(rect.height() * 6 + 5)
        layout.addWidget(self.__details)

        # Errors/warnings
        errorsLabel = QLabel("Errors / warnings")
        layout.addWidget(errorsLabel)
        self.__errorsText = QTextEdit()
        self.__errorsText.setReadOnly(True)
        self.__errorsText.setAcceptRichText(False)
        metrics = QFontMetrics(self.__errorsText.font())
        rect = metrics.boundingRect("X")
        self.__errorsText.setFixedHeight(rect.height() * 4 + 5)
        layout.addWidget(self.__errorsText)

        # Buttons box
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        self.__OKButton = buttonBox.button(QDialogButtonBox.Ok)
        self.__OKButton.setDefault(True)
        buttonBox.accepted.connect(self.close)
        buttonBox.rejected.connect(self.close)
        layout.addWidget(buttonBox)

        self.setLayout(layout)

    def __createConfigButton(self):
        """Creates a configure button for a plugin"""
        button = SettingsButton()
        button.CustomClick.connect(self.onPluginSettings)
        return button

    def __populate(self):
        """Populates the list with the plugins"""
        index = 0

        for category in self.__pluginManager.activePlugins:
            for cdmPlugin in self.__pluginManager.activePlugins[category]:
                newItem = PluginItem(self.__pluginManager, cdmPlugin, True,
                                     category)
                self.__pluginsView.addTopLevelItem(newItem)
                settingsButton = self.__createConfigButton()

                try:
                    configFunction = cdmPlugin.getObject().getConfigFunction()
                    if configFunction is None:
                        settingsButton.setToolTip(
                            "Plugin does not need configuring")
                        settingsButton.setEnabled(False)
                    else:
                        settingsButton.setToolTip("Click to configure")
                        settingsButton.setEnabled(True)
                        self.__configFuncs[index] = configFunction
                        settingsButton.index = index
                        index += 1
                except Exception:
                    settingsButton.setToolTip("Bad plugin interface. No "
                                              "configuration function "
                                              "received.")
                    settingsButton.setEnabled(False)

                self.__pluginsView.setItemWidget(newItem, SETTINGS_COL,
                                                 settingsButton)

        for category in self.__pluginManager.inactivePlugins:
            for cdmPlugin in self.__pluginManager.inactivePlugins[category]:
                newItem = PluginItem(self.__pluginManager, cdmPlugin, False,
                                     category)
                self.__pluginsView.addTopLevelItem(newItem)
                settingsButton = self.__createConfigButton()

                try:
                    configFunction = cdmPlugin.getObject().getConfigFunction()
                    if configFunction is None:
                        settingsButton.setToolTip(
                            "Plugin does not need configuring")
                        settingsButton.setEnabled(False)
                    else:
                        settingsButton.setToolTip(
                            "Enable plugin and then click to configure")
                        settingsButton.setEnabled(False)
                        self.__configFuncs[index] = configFunction
                        settingsButton.index = index
                        index += 1
                except:
                    settingsButton.setToolTip("Bad plugin interface. No "
                                              "configuration function "
                                              "received.")
                    settingsButton.setEnabled(False)

                self.__pluginsView.setItemWidget(newItem, SETTINGS_COL,
                                                 settingsButton)

        for cdmPlugin in self.__pluginManager.unknownPlugins:
            newItem = PluginItem(self.__pluginManager, cdmPlugin, False, None)
            self.__pluginsView.addTopLevelItem(newItem)
            settingsButton = self.__createConfigButton()
            settingsButton.setToolTip("Unknown plugins are not configurable")
            settingsButton.setEnabled(False)
            self.__pluginsView.setItemWidget(newItem, SETTINGS_COL,
                                             settingsButton)

        self.__sortPlugins()
        self.__resizePlugins()

    def __sortPlugins(self):
        """Sorts the plugins table"""
        self.__pluginsView.sortItems(
            self.__pluginsView.sortColumn(),
            self.__pluginsView.header().sortIndicatorOrder())

    def __resizePlugins(self):
        """Resizes the plugins table"""
        self.__pluginsView.header().setStretchLastSection(False)
        self.__pluginsView.header().resizeSections(
            QHeaderView.ResizeToContents)
        self.__pluginsView.header().resizeSection(STATE_COL, 28)
        self.__pluginsView.header().setSectionResizeMode(
            STATE_COL, QHeaderView.Fixed)
        self.__pluginsView.header().resizeSection(CONFLICT_COL, 28)
        self.__pluginsView.header().setSectionResizeMode(
            CONFLICT_COL, QHeaderView.Fixed)
        self.__pluginsView.header().resizeSection(TYPE_COL, 28)
        self.__pluginsView.header().setSectionResizeMode(
            TYPE_COL, QHeaderView.Fixed)

        self.__pluginsView.header().setSectionResizeMode(
            VERSION_COL, QHeaderView.Stretch)
        self.__pluginsView.header().resizeSection(SETTINGS_COL, 24)
        self.__pluginsView.header().setSectionResizeMode(
            SETTINGS_COL, QHeaderView.Fixed)

    def __pluginSelectionChanged(self):
        """Triggered when an item is selected"""
        selected = list(self.__pluginsView.selectedItems())
        if selected:
            self.__updateDetails(selected[0])
        else:
            self.__updateDetails(None)

    def __updateDetails(self, item):
        """Updates the content of the details and the error boxes"""
        self.__details.clear()
        self.__errorsText.setText("")

        if item is None:
            return

        self.__details.addTopLevelItem(
            QTreeWidgetItem(["Author", item.plugin.getAuthor()]))
        self.__details.addTopLevelItem(
            QTreeWidgetItem(["Path",
                             os.path.normpath(item.plugin.getPath())]))
        self.__details.addTopLevelItem(
            QTreeWidgetItem(["Description",
                             item.plugin.getDescription()]))
        self.__details.addTopLevelItem(
            QTreeWidgetItem(["Web site", item.plugin.getWebsite()]))

        copyright = item.plugin.getCopyright()
        if copyright is not None:
            if copyright.lower() != "unknown":
                self.__details.addTopLevelItem(
                    QTreeWidgetItem(["Copyright", copyright]))

        for name in item.plugin.getDetails():
            value = item.plugin.getDetails()[name]
            self.__details.addTopLevelItem(QTreeWidgetItem([name, value]))

        self.__errorsText.setText(item.plugin.conflictMessage)

    def __onItemChanged(self, item, column):
        """Triggered when an item is changed"""
        if self.__inItemChange:
            return

        if item.active:
            self.__inItemChange = True
            item.plugin.disable()
            item.active = False

            settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL)
            settingsButton.setEnabled(False)
            if settingsButton.index != -1:
                settingsButton.setToolTip(
                    "Enable plugin and then click to configure")

            if item.category in self.__pluginManager.inactivePlugins:
                self.__pluginManager. \
                    inactivePlugins[item.category].append(item.plugin)
            else:
                self.__pluginManager. \
                    inactivePlugins[item.category] = [item.plugin]
            self.__pluginManager. \
                activePlugins[item.category].remove(item.plugin)
            self.__pluginManager.saveDisabledPlugins()
            self.__inItemChange = False
            self.__pluginManager.sendPluginDeactivated(item.plugin)
            return

        self.__inItemChange = True
        message = self.__pluginManager.checkConflict(item.plugin)
        if message is not None:
            item.setCheckState(STATE_COL, Qt.Unchecked)
            self.__errorsText.setText(message)
            self.__inItemChange = False
            return

        try:
            item.plugin.enable()
            item.active = True
            if item.category in self.__pluginManager.activePlugins:
                self.__pluginManager. \
                    activePlugins[item.category].append(item.plugin)
            else:
                self.__pluginManager. \
                    activePlugins[item.category] = [item.plugin]
            self.__pluginManager. \
                inactivePlugins[item.category].remove(item.plugin)
            self.__pluginManager.saveDisabledPlugins()
            self.__errorsText.setText("")
            item.setIcon(CONFLICT_COL, getIcon('empty.png'))
            item.setToolTip(CONFLICT_COL, "")

            settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL)
            if settingsButton.index != -1:
                settingsButton.setToolTip("Click to configure")
                settingsButton.setEnabled(True)
            self.__pluginManager.sendPluginActivated(item.plugin)
        except Exception as exc:
            item.setCheckState(STATE_COL, Qt.Unchecked)
            self.__errorsText.setText(
                "Error activating the plugin, exception is generated:\n" +
                str(exc))
        except:
            item.setCheckState(STATE_COL, Qt.Unchecked)
            self.__errorsText.setText(
                "Error activating the plugin, unknown exception")

        self.__inItemChange = False

    def onPluginSettings(self, index):
        """Triggered when a configuring function is called"""
        if index not in self.__configFuncs:
            return

        try:
            self.__configFuncs[index]()
        except Exception as exc:
            logging.error("Error calling the plugin configuration function. "
                          "Message: " + str(exc))