Example #1
0
    def __createLayout(self, parent):
        """Creates the toolbar and layout"""
        del parent  # unused argument

        # Buttons etc.
        self.clearButton = QAction(getIcon('trash.png'),
                                   'Delete current results', self)
        self.clearButton.triggered.connect(self.__clear)

        self.prevButton = QAction(getIcon('1leftarrow.png'),
                                  'Previous results', self)
        self.prevButton.triggered.connect(self.__previous)

        self.nextButton = QAction(getIcon('1rightarrow.png'),
                                  'Next results', self)
        self.nextButton.triggered.connect(self.__next)

        self.doAgainButton = QAction(getIcon('searchagain.png'),
                                     'Do again', self)
        self.doAgainButton.triggered.connect(self.__doAgain)

        self.removeItemButton = QAction(getIcon('delitem.png'),
                                        'Remove currently selected item (Del)',
                                        self)
        self.removeItemButton.triggered.connect(self.__removeItem)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.prevButton)
        self.toolbar.addAction(self.nextButton)
        self.toolbar.addAction(self.doAgainButton)
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.removeItemButton)
        self.toolbar.addAction(self.clearButton)

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__results)
        self.__results.hide()

        self.setLayout(self.__hLayout)
Example #2
0
    def __createToolbar(self):
        """Creates the toolbar"""
        self.__toolbar = QToolBar(self)
        self.__toolbar.setOrientation(Qt.Vertical)
        self.__toolbar.setMovable(False)
        self.__toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.__toolbar.setIconSize(QSize(16, 16))
        self.__toolbar.setFixedWidth(30)
        self.__toolbar.setContentsMargins(0, 0, 0, 0)

        # Some control buttons could be added later
        self.printButton = QAction(getIcon('printer.png'), 'Print', self)
        self.printButton.triggered.connect(self.__onPrint)
        self.__toolbar.addAction(self.printButton)

        return self.__toolbar
Example #3
0
    def activate(self, ideSettings, ideGlobalData):
        """Activates the plugin.

        The plugin may override the method to do specific
        plugin activation handling.

        ideSettings - reference to the IDE Settings singleton
                      see codimension/src/utils/settings.py
        ideGlobalData - reference to the IDE global settings
                        see codimension/src/utils/globals.py

        Note: if overriden do not forget to call the
              base class activate()
        """
        WizardInterface.activate(self, ideSettings, ideGlobalData)

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:

            self.__where = self.__getConfiguredWhere()
            mainToolbar = self.ide.mainWindow.getToolbar()
            beforeWidget = mainToolbar.findChild(QAction, 'debugSpacer')
            self.__separator = mainToolbar.insertSeparator(beforeWidget)

            self.__memtopButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'memtop.png'), 'memtop report',
                mainToolbar)
            self.__memtopButton.triggered.connect(self.__onMemtop)
            mainToolbar.insertAction(beforeWidget, self.__memtopButton)

            self.__debuggerButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'debugger.png'), 'stop with debugger',
                mainToolbar)
            self.__debuggerButton.triggered.connect(self.__onDebugger)
            mainToolbar.insertAction(beforeWidget, self.__debuggerButton)

            self.__repeatButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'repeat.png'), 'Repeated actions',
                mainToolbar)
            self.__repeatButton.triggered.connect(self.__onRepeatedAction)
            mainToolbar.insertAction(beforeWidget, self.__repeatButton)

            self.__resetButton = QAction(QIcon(PLUGIN_HOME_DIR + 'reset.png'),
                                         'Reset the heap reference point',
                                         mainToolbar)
            self.__resetButton.triggered.connect(self.__onResetHeap)
            mainToolbar.insertAction(beforeWidget, self.__resetButton)

            self.hpy = hpy()
            self.hpy.setref()
        except:
            QApplication.restoreOverrideCursor()
            raise
        QApplication.restoreOverrideCursor()
Example #4
0
    def __addButton(self, tabWidget):
        """Adds a button to the editor toolbar"""
        pylintButton = QAction(QIcon(PLUGIN_HOME_DIR + 'pylint.png'),
                               'Run pylint (Ctrl+L)', tabWidget.toolbar)
        pylintButton.setEnabled(self.__canRun(tabWidget)[0])
        pylintButton.triggered.connect(self.__run)
        pylintButton.setObjectName('pylint')

        beforeWidget = tabWidget.toolbar.findChild(QAction,
                                                   'deadCodeScriptButton')
        tabWidget.toolbar.insertAction(beforeWidget, pylintButton)
        tabWidget.getEditor().modificationChanged.connect(
            self.__modificationChanged)
    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        printButton = QAction(getIcon('printer.png'), 'Print', self)
        # printButton.setShortcut('Ctrl+')
        printButton.triggered.connect(self.__onPrint)

        printPreviewButton = QAction(getIcon('printpreview.png'),
                                     'Print preview', self)
        # printPreviewButton.setShortcut('Ctrl+')
        printPreviewButton.triggered.connect(self.__onPrintPreview)

        fixedSpacer = QWidget()
        fixedSpacer.setFixedHeight(16)

        zoomInButton = QAction(getIcon('zoomin.png'), 'Zoom in (Ctrl+=)', self)
        zoomInButton.setShortcut('Ctrl+=')
        zoomInButton.triggered.connect(self.onZoomIn)

        zoomOutButton = QAction(getIcon('zoomout.png'), 'Zoom out (Ctrl+-)',
                                self)
        zoomOutButton.setShortcut('Ctrl+-')
        zoomOutButton.triggered.connect(self.onZoomOut)

        zoomResetButton = QAction(getIcon('zoomreset.png'),
                                  'Zoom reset (Ctrl+0)', self)
        zoomResetButton.setShortcut('Ctrl+0')
        zoomResetButton.triggered.connect(self.onZoomReset)

        # Toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)
        # toolbar.addAction(printPreviewButton)
        # toolbar.addAction(printButton)
        # toolbar.addWidget(fixedSpacer)
        toolbar.addAction(zoomInButton)
        toolbar.addAction(zoomOutButton)
        toolbar.addAction(zoomResetButton)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(self.__viewer)
        hLayout.addWidget(toolbar)

        self.setLayout(hLayout)
Example #6
0
class ProfileResultsWidget(QWidget, MainWindowTabWidgetBase):

    """Profiling results widget"""

    sigEscapePressed = pyqtSignal()

    def __init__(self, scriptName, params, reportTime, dataFile, parent=None):
        MainWindowTabWidgetBase.__init__(self)
        QWidget.__init__(self, parent)

        # The same stats object is needed for both - a table and a graph
        # So, parse profile output once and then pass the object further
        stats = pstats.Stats(dataFile)
        stats.calc_callees()

        self.__profTable = ProfileTableViewer(scriptName, params, reportTime,
                                              dataFile, stats, self)
        self.__profGraph = ProfileGraphViewer(scriptName, params, reportTime,
                                              dataFile, stats, self)
        self.__profTable.hide()

        self.__profTable.sigEscapePressed.connect(self.__onEsc)
        self.__profGraph.sigEscapePressed.connect(self.__onEsc)

        self.__createLayout()

    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        self.__toggleViewButton = QAction(getIcon('tableview.png'),
                                          'Switch to table view', self)
        self.__toggleViewButton.setCheckable(True)
        self.__toggleViewButton.toggled.connect(self.__switchView)

        self.__togglePathButton = QAction(getIcon('longpath.png'),
                                          'Show full paths for item location',
                                          self)
        self.__togglePathButton.setCheckable(True)
        self.__togglePathButton.toggled.connect(self.__togglePath)
        self.__togglePathButton.setEnabled(False)

        self.__printButton = QAction(getIcon('printer.png'), 'Print', self)
        self.__printButton.triggered.connect(self.__onPrint)
        self.__printButton.setEnabled(False)

        self.__printPreviewButton = QAction(getIcon('printpreview.png'),
                                            'Print preview', self)
        self.__printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.__printPreviewButton.setEnabled(False)

        fixedSpacer = QWidget()
        fixedSpacer.setFixedHeight(16)

        self.__zoomInButton = QAction(getIcon('zoomin.png'),
                                      'Zoom in (Ctrl+=)', self)
        self.__zoomInButton.setShortcut('Ctrl+=')
        self.__zoomInButton.triggered.connect(self.onZoomIn)

        self.__zoomOutButton = QAction(getIcon('zoomout.png'),
                                       'Zoom out (Ctrl+-)', self)
        self.__zoomOutButton.setShortcut('Ctrl+-')
        self.__zoomOutButton.triggered.connect(self.onZoomOut)

        self.__zoomResetButton = QAction(getIcon('zoomreset.png'),
                                         'Zoom reset (Ctrl+0)', self)
        self.__zoomResetButton.setShortcut('Ctrl+0')
        self.__zoomResetButton.triggered.connect(self.onZoomReset)

        # Toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(self.__toggleViewButton)
        toolbar.addAction(self.__togglePathButton)
        toolbar.addAction(self.__printPreviewButton)
        toolbar.addAction(self.__printButton)
        toolbar.addWidget(fixedSpacer)
        toolbar.addAction(self.__zoomInButton)
        toolbar.addAction(self.__zoomOutButton)
        toolbar.addAction(self.__zoomResetButton)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(self.__profTable)
        hLayout.addWidget(self.__profGraph)
        hLayout.addWidget(toolbar)

        self.setLayout(hLayout)

    def setFocus(self):
        """Overriden setFocus"""
        if self.__profTable.isVisible():
            self.__profTable.setFocus()
        else:
            self.__profGraph.setFocus()

    def __onEsc(self):
        """Triggered when Esc is pressed"""
        self.sigEscapePressed.emit()

    def __switchView(self, state):
        """Triggered when view is to be switched"""
        if state:
            self.__profGraph.hide()
            self.__profTable.show()
            self.__toggleViewButton.setIcon(getIcon('profdgmview.png'))
            self.__toggleViewButton.setToolTip('Switch to diagram view')
            self.__zoomInButton.setEnabled(False)
            self.__zoomOutButton.setEnabled(False)
            self.__zoomResetButton.setEnabled(False)
            self.__togglePathButton.setEnabled(True)
            self.__profTable.setFocus()
        else:
            self.__profTable.hide()
            self.__profGraph.show()
            self.__toggleViewButton.setIcon(getIcon('tableview.png'))
            self.__toggleViewButton.setToolTip('Switch to table view')
            self.__zoomInButton.setEnabled(True)
            self.__zoomOutButton.setEnabled(True)
            self.__zoomResetButton.setEnabled(True)
            self.__togglePathButton.setEnabled(False)
            self.__profGraph.setFocus()

    def __togglePath(self, state):
        """Triggered when full path/file name is switched"""
        self.__profTable.togglePath(state)
        if state:
            fName = 'shortpath.png'
            tip = 'Show file names only for item location'
        else:
            fName = 'longpath.png'
            tip = 'Show full paths for item location'
        self.__togglePathButton.setIcon(getIcon(fName))
        self.__togglePathButton.setToolTip(tip)

    def __onPrint(self):
        """Triggered on the 'print' button"""
        pass

    def __onPrintPreview(self):
        """Triggered on the 'print preview' button"""
        pass

    def isZoomApplicable(self):
        """Should the zoom menu items be available"""
        return self.__profGraph.isVisible()

    def onZoomIn(self):
        """Triggered on the 'zoom in' button"""
        if self.__profGraph.isVisible():
            self.__profGraph.zoomIn()

    def onZoomOut(self):
        """Triggered on the 'zoom out' button"""
        if self.__profGraph.isVisible():
            self.__profGraph.zoomOut()

    def onZoomReset(self):
        """Triggered on the 'zoom reset' button"""
        if self.__profGraph.isVisible():
            self.__profGraph.resetZoom()

    def isCopyAvailable(self):
        """Tells id the main menu copy item should be switched on"""
        return self.__profGraph.isVisible()

    def isDiagramActive(self):
        """Tells if the diagram is active"""
        return self.__profGraph.isVisible()

    def onCopy(self):
        """Ctrl+C triggered"""
        if self.__profGraph.isVisible():
            self.__profGraph.onCopy()

    def onSaveAs(self, fileName):
        """Saves the diagram into a file"""
        if self.__profGraph.isVisible():
            self.__profGraph.onSaveAs(fileName)
        else:
            self.__profTable.onSaveAs(fileName)

    # Mandatory interface part is below

    def isModified(self):
        """Tells if the file is modified"""
        return False

    def getRWMode(self):
        """Tells if the file is read only"""
        return "RO"

    def getType(self):
        """Tells the widget type"""
        return MainWindowTabWidgetBase.ProfileViewer

    def getLanguage(self):
        """Tells the content language"""
        return "Profiler"

    def setFileName(self, name):
        """Sets the file name - not applicable"""
        raise Exception("Setting a file name for profile results "
                        "is not applicable")

    def setEncoding(self, newEncoding):
        """Not applicable for the profiler results viewer"""
        return

    def getShortName(self):
        """Tells the display name"""
        return "Profiling results"

    def setShortName(self, name):
        """Sets the display name - not applicable"""
        raise Exception("Setting a file name for profiler "
                        "results is not applicable")
Example #7
0
class CallTraceViewer(QWidget):
    """Implements the call trace viewer"""
    def __init__(self, debugger, parent=None):
        QWidget.__init__(self, parent)

        self.__debugger = debugger
        self.__createLayout()

        self.__debugger.sigClientCallTrace.connect(self.__onCallTrace)
        GlobalData().project.sigProjectChanged.connect(self.__onProjectChanged)

    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what == CodimensionProject.CompleteProject:
            self.clear()
            self.calltraceList.onProjectChanged()

    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__calltraceLabel = QLabel("Call Trace", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('calltraceheader')
        self.headerFrame.setStyleSheet('QFrame#calltraceheader {' +
                                       getLabelStyle(self.__calltraceLabel) +
                                       '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__calltraceLabel)
        self.headerFrame.setLayout(headerLayout)

        self.calltraceList = CallTraceBrowser(self)

        self.__startButton = QAction(getIcon('calltracestart.png'),
                                     "Start call tracing", self)
        self.__startButton.triggered.connect(self.__onStart)
        self.__startButton.setEnabled(not Settings()['calltrace'])

        self.__stopButton = QAction(getIcon('calltracestop.png'),
                                    "Stop call tracing", self)
        self.__stopButton.triggered.connect(self.__onStop)
        self.__stopButton.setEnabled(Settings()['calltrace'])

        self.__resizeButton = QAction(getIcon('resizecolumns.png'),
                                      "Resize the columns to their contents",
                                      self)
        self.__resizeButton.triggered.connect(self.__onResize)
        self.__resizeButton.setEnabled(True)

        self.__clearButton = QAction(getIcon('trash.png'), "Clear", self)
        self.__clearButton.triggered.connect(self.__onClear)
        self.__clearButton.setEnabled(False)

        self.__copyButton = QAction(getIcon('copymenu.png'),
                                    "Copy to clipboard", self)
        self.__copyButton.triggered.connect(self.__onCopy)
        self.__copyButton.setEnabled(False)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__startButton)
        self.toolbar.addAction(self.__stopButton)

        fixedSpacer2 = QWidget()
        fixedSpacer2.setFixedWidth(15)
        self.toolbar.addWidget(fixedSpacer2)
        self.toolbar.addAction(self.__resizeButton)
        self.toolbar.addAction(self.__copyButton)
        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        fixedSpacer4 = QWidget()
        fixedSpacer4.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer4)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__clearButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.calltraceList)

    def __onCallTrace(self, isCall, fromFile, fromLine, fromFunction, toFile,
                      toLine, toFunction):
        """Call trace message received"""
        self.calltraceList.addCallTrace(isCall, fromFile, fromLine,
                                        fromFunction, toFile, toLine,
                                        toFunction)
        self.__clearButton.setEnabled(True)
        self.__copyButton.setEnabled(True)
        self.__updateHeader()

    def __updateHeader(self):
        """Updates the header"""
        count = self.calltraceList.count
        if count:
            self.__calltraceLabel.setText('Call Trace (' + str(count) + ')')
        else:
            self.__calltraceLabel.setText('Call Trace')

    def __onStart(self):
        """Start collecting calltrace"""
        self.__startButton.setEnabled(False)
        self.__stopButton.setEnabled(True)
        Settings()['calltrace'] = True
        self.__debugger.startCalltrace()

    def __onStop(self):
        """Stop collecting calltrace"""
        self.__startButton.setEnabled(True)
        self.__stopButton.setEnabled(False)
        Settings()['calltrace'] = False
        self.__debugger.stopCalltrace()

    def __onResize(self):
        """Resize the columns to its width"""
        for column in range(self.calltraceList.columnCount()):
            self.calltraceList.resizeColumnToContents(column)

    def __onClear(self):
        """Clears the view"""
        self.calltraceList.clear()
        self.__clearButton.setEnabled(False)
        self.__copyButton.setEnabled(False)
        self.__updateHeader()

    def clear(self):
        """Clears the view"""
        self.__onClear()

    def __onCopy(self):
        """Copy the content as text to clipboard"""
        content = []
        lhsMaxLength = 0
        try:
            item = self.calltraceList.topLevelItem(0)
            while item is not None:
                call = '<-'
                if item.data(0, Qt.UserRole):
                    call = '->'
                lhs = item.text(1)
                lhsLength = len(lhs)
                lhsMaxLength = max(lhsMaxLength, lhsLength)

                content.append([lhs, lhsLength, call + ' ' + item.text(2)])
                item = self.calltraceList.itemBelow(item)

            for index in range(len(content)):
                content[index] = \
                    content[index][0] + \
                    ' ' * (lhsMaxLength - content[index][1] + 1) + \
                    content[index][2]

            QApplication.clipboard().setText('\n'.join(content))
        except Exception as exc:
            logging.error('Error copying the call trace to clipboard: ' +
                          str(exc))
Example #8
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__calltraceLabel = QLabel("Call Trace", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('calltraceheader')
        self.headerFrame.setStyleSheet('QFrame#calltraceheader {' +
                                       getLabelStyle(self.__calltraceLabel) +
                                       '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__calltraceLabel)
        self.headerFrame.setLayout(headerLayout)

        self.calltraceList = CallTraceBrowser(self)

        self.__startButton = QAction(getIcon('calltracestart.png'),
                                     "Start call tracing", self)
        self.__startButton.triggered.connect(self.__onStart)
        self.__startButton.setEnabled(not Settings()['calltrace'])

        self.__stopButton = QAction(getIcon('calltracestop.png'),
                                    "Stop call tracing", self)
        self.__stopButton.triggered.connect(self.__onStop)
        self.__stopButton.setEnabled(Settings()['calltrace'])

        self.__resizeButton = QAction(getIcon('resizecolumns.png'),
                                      "Resize the columns to their contents",
                                      self)
        self.__resizeButton.triggered.connect(self.__onResize)
        self.__resizeButton.setEnabled(True)

        self.__clearButton = QAction(getIcon('trash.png'), "Clear", self)
        self.__clearButton.triggered.connect(self.__onClear)
        self.__clearButton.setEnabled(False)

        self.__copyButton = QAction(getIcon('copymenu.png'),
                                    "Copy to clipboard", self)
        self.__copyButton.triggered.connect(self.__onCopy)
        self.__copyButton.setEnabled(False)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__startButton)
        self.toolbar.addAction(self.__stopButton)

        fixedSpacer2 = QWidget()
        fixedSpacer2.setFixedWidth(15)
        self.toolbar.addWidget(fixedSpacer2)
        self.toolbar.addAction(self.__resizeButton)
        self.toolbar.addAction(self.__copyButton)
        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        fixedSpacer4 = QWidget()
        fixedSpacer4.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer4)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__clearButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.calltraceList)
class ClientExceptionsViewer(QWidget):

    """Implements the client exceptions viewer for a debugger"""

    sigClientExceptionsCleared = pyqtSignal()

    def __init__(self, parent, ignoredExceptionsViewer):
        QWidget.__init__(self, parent)

        self.__ignoredExceptionsViewer = ignoredExceptionsViewer
        self.__currentItem = None

        self.__createPopupMenu()
        self.__createLayout()

        GlobalData().project.sigProjectChanged.connect(self.__onProjectChanged)

    def setFocus(self):
        """Sets the widget focus"""
        self.exceptionsList.setFocus()

    def __createPopupMenu(self):
        """Creates the popup menu"""
        self.__excptMenu = QMenu()
        self.__addToIgnoreMenuItem = self.__excptMenu.addAction(
            "Add to ignore list", self.__onAddToIgnore)
        self.__jumpToCodeMenuItem = self.__excptMenu.addAction(
            "Jump to code", self.__onJumpToCode)

    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__excptLabel = QLabel("Exceptions", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('excpt')
        self.headerFrame.setStyleSheet('QFrame#excpt {' +
                                       getLabelStyle(self.__excptLabel) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__excptLabel)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(True)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.__addToIgnoreButton = QAction(
            getIcon('add.png'), "Add exception to the list of ignored", self)
        self.__addToIgnoreButton.triggered.connect(self.__onAddToIgnore)
        self.__addToIgnoreButton.setEnabled(False)

        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)

        self.__jumpToCodeButton = QAction(
            getIcon('gotoline.png'), "Jump to the code", self)
        self.__jumpToCodeButton.triggered.connect(self.__onJumpToCode)
        self.__jumpToCodeButton.setEnabled(False)

        self.__delAllButton = QAction(
            getIcon('trash.png'), "Delete all the client exceptions", self)
        self.__delAllButton.triggered.connect(self.__onDelAll)
        self.__delAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__addToIgnoreButton)
        self.toolbar.addAction(self.__jumpToCodeButton)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__delAllButton)

        self.exceptionsList.itemDoubleClicked.connect(
            self.__onExceptionDoubleClicked)
        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)

        self.exceptionsList.setHeaderLabels(["Exception",
                                             "Function", "Arguments"])

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)

    def clear(self):
        """Clears the content"""
        self.exceptionsList.clear()
        self.__updateExceptionsLabel()
        self.__addToIgnoreButton.setEnabled(False)
        self.__jumpToCodeButton.setEnabled(False)
        self.__delAllButton.setEnabled(False)
        self.__currentItem = None
        self.sigClientExceptionsCleared.emit()

    def __onExceptionDoubleClicked(self, item, column):
        """Triggered when an exception is double clicked"""
        del item    # unused argument
        del column  # unused argument
        if self.__currentItem is not None:
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                self.__onJumpToCode()
                return

            # This is an exception item itself.
            # Open a separate dialog window with th detailed info.

    def __showContextMenu(self, coord):
        """Shows the frames list context menu"""
        self.__currentItem = self.exceptionsList.itemAt(coord)

        self.__addToIgnoreMenuItem.setEnabled(
            self.__addToIgnoreButton.isEnabled())
        self.__jumpToCodeMenuItem.setEnabled(
            self.__jumpToCodeButton.isEnabled())

        if self.__currentItem is not None:
            self.__excptMenu.popup(QCursor.pos())

    def __onAddToIgnore(self):
        """Adds an exception into the ignore list"""
        if self.__currentItem is not None:
            self.__ignoredExceptionsViewer.addExceptionFilter(
                str(self.__currentItem.getExceptionType()))
            self.__addToIgnoreButton.setEnabled(False)

    def __onJumpToCode(self):
        """Jumps to the corresponding source code line"""
        if self.__currentItem is not None:
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                fileName = self.__currentItem.getFileName()
                if '<' not in fileName and '>' not in fileName:
                    lineNumber = self.__currentItem.getLineNumber()

                    editorsManager = GlobalData().mainWindow.editorsManager()
                    editorsManager.openFile(fileName, lineNumber)
                    editor = editorsManager.currentWidget().getEditor()
                    editor.gotoLine(lineNumber)
                    editorsManager.currentWidget().setFocus()

    def __onDelAll(self):
        """Triggered when all the exceptions should be deleted"""
        self.clear()

    def addException(self, exceptionType, exceptionMessage, stackTrace):
        """Adds the exception to the view"""
        for index in range(self.exceptionsList.topLevelItemCount()):
            item = self.exceptionsList.topLevelItem(index)
            if item.equal(exceptionType, exceptionMessage, stackTrace):
                item.incrementCounter()
                self.exceptionsList.clearSelection()
                self.exceptionsList.setCurrentItem(item)
                self.__updateExceptionsLabel()
                return

        item = ExceptionItem(self.exceptionsList, exceptionType,
                             exceptionMessage, stackTrace)
        self.exceptionsList.clearSelection()
        self.exceptionsList.setCurrentItem(item)
        self.__updateExceptionsLabel()
        self.__delAllButton.setEnabled(True)

    def __updateExceptionsLabel(self):
        """Updates the exceptions header label"""
        total = self.getTotalCount()
        if total > 0:
            self.__excptLabel.setText("Exceptions (total: " + str(total) + ")")
        else:
            self.__excptLabel.setText("Exceptions")

    def getTotalCount(self):
        """Provides the total number of exceptions"""
        count = 0
        for index in range(self.exceptionsList.topLevelItemCount()):
            count += self.exceptionsList.topLevelItem(index).getCount()
        return count

    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what == CodimensionProject.CompleteProject:
            self.clear()

    def __onSelectionChanged(self):
        """Triggered when the current item is changed"""
        selected = list(self.exceptionsList.selectedItems())
        if selected:
            self.__currentItem = selected[0]
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                fileName = self.__currentItem.getFileName()
                if '<' in fileName or '>' in fileName:
                    self.__jumpToCodeButton.setEnabled(False)
                else:
                    self.__jumpToCodeButton.setEnabled(True)
                self.__addToIgnoreButton.setEnabled(False)
            else:
                self.__jumpToCodeButton.setEnabled(False)
                excType = str(self.__currentItem.getExceptionType())
                if self.__ignoredExceptionsViewer.isIgnored(excType) or \
                   " " in excType or excType.startswith("unhandled"):
                    self.__addToIgnoreButton.setEnabled(False)
                else:
                    self.__addToIgnoreButton.setEnabled(True)
        else:
            self.__currentItem = None
            self.__addToIgnoreButton.setEnabled(False)
            self.__jumpToCodeButton.setEnabled(False)
    def __createLayout(self):
        """Creates the toolbar and layout"""
        self.__settingsMenu = QMenu(self)
        self.__settingsMenu.aboutToShow.connect(self.__settingsAboutToShow)
        self.__wrapLongLinesAct = self.__settingsMenu.addAction(
            "Wrap long lines")
        self.__wrapLongLinesAct.setCheckable(True)
        self.__wrapLongLinesAct.triggered.connect(self.__onWrapLongLines)
        self.__showWhitespacesAct = self.__settingsMenu.addAction(
            "Show whitespaces")
        self.__showWhitespacesAct.setCheckable(True)
        self.__showWhitespacesAct.triggered.connect(self.__onShowWhitespaces)
        self.__autoscrollAct = self.__settingsMenu.addAction("Autoscroll")
        self.__autoscrollAct.setCheckable(True)
        self.__autoscrollAct.triggered.connect(self.__onAutoscroll)

        self.__settingsButton = QToolButton(self)
        self.__settingsButton.setIcon(getIcon('iosettings.png'))
        self.__settingsButton.setToolTip('View settings')
        self.__settingsButton.setPopupMode(QToolButton.InstantPopup)
        self.__settingsButton.setMenu(self.__settingsMenu)
        self.__settingsButton.setFocusPolicy(Qt.NoFocus)

        if self.kind != DEBUG:
            fixedSpacer = QWidget()
            fixedSpacer.setFixedHeight(8)

            self.__stopButton = QAction(getIcon('runconsolestop.png'),
                                        'Stop process', self)
            self.__stopButton.triggered.connect(self.stop)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__clearButton = QAction(getIcon('trash.png'), 'Clear', self)
        self.__clearButton.triggered.connect(self.clear)

        # The toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addWidget(self.__settingsButton)

        if self.kind != DEBUG:
            toolbar.addWidget(fixedSpacer)
            toolbar.addAction(self.__stopButton)

        toolbar.addWidget(spacer)
        toolbar.addAction(self.__clearButton)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(toolbar)
        hLayout.addWidget(self.__viewer)

        self.setLayout(hLayout)
Example #11
0
class IntrospectionPlugin(WizardInterface):
    """Codimension introspection plugin"""
    def __init__(self):
        WizardInterface.__init__(self)
        self.__where = IntrospectionPluginConfigDialog.CONSOLE
        self.heap = None

    @staticmethod
    def isIDEVersionCompatible(ideVersion):
        """Checks if the IDE version is compatible with the plugin.

        Codimension makes this call before activating a plugin.
        The passed ideVersion is a string representing
        the current IDE version.
        True should be returned if the plugin is compatible with the IDE.
        """
        return StrictVersion(ideVersion) >= StrictVersion('4.7.0')

    def activate(self, ideSettings, ideGlobalData):
        """Activates the plugin.

        The plugin may override the method to do specific
        plugin activation handling.

        ideSettings - reference to the IDE Settings singleton
                      see codimension/src/utils/settings.py
        ideGlobalData - reference to the IDE global settings
                        see codimension/src/utils/globals.py

        Note: if overriden do not forget to call the
              base class activate()
        """
        WizardInterface.activate(self, ideSettings, ideGlobalData)

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:

            self.__where = self.__getConfiguredWhere()
            mainToolbar = self.ide.mainWindow.getToolbar()
            beforeWidget = mainToolbar.findChild(QAction, 'debugSpacer')
            self.__separator = mainToolbar.insertSeparator(beforeWidget)

            self.__memtopButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'memtop.png'), 'memtop report',
                mainToolbar)
            self.__memtopButton.triggered.connect(self.__onMemtop)
            mainToolbar.insertAction(beforeWidget, self.__memtopButton)

            self.__debuggerButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'debugger.png'), 'stop with debugger',
                mainToolbar)
            self.__debuggerButton.triggered.connect(self.__onDebugger)
            mainToolbar.insertAction(beforeWidget, self.__debuggerButton)

            self.__repeatButton = QAction(
                QIcon(PLUGIN_HOME_DIR + 'repeat.png'), 'Repeated actions',
                mainToolbar)
            self.__repeatButton.triggered.connect(self.__onRepeatedAction)
            mainToolbar.insertAction(beforeWidget, self.__repeatButton)

            self.__resetButton = QAction(QIcon(PLUGIN_HOME_DIR + 'reset.png'),
                                         'Reset the heap reference point',
                                         mainToolbar)
            self.__resetButton.triggered.connect(self.__onResetHeap)
            mainToolbar.insertAction(beforeWidget, self.__resetButton)

            self.hpy = hpy()
            self.hpy.setref()
        except:
            QApplication.restoreOverrideCursor()
            raise
        QApplication.restoreOverrideCursor()

    def deactivate(self):
        """Deactivates the plugin.

        The plugin may override the method to do specific
        plugin deactivation handling.
        Note: if overriden do not forget to call the
              base class deactivate()
        """
        self.hpy = None

        self.__memtopButton.disconnect()
        self.__debuggerButton.disconnect()
        self.__repeatButton.disconnect()
        self.__resetButton.disconnect()

        mainToolbar = self.ide.mainWindow.getToolbar()
        mainToolbar.removeAction(self.__separator)
        mainToolbar.removeAction(self.__debuggerButton)
        mainToolbar.removeAction(self.__memtopButton)
        mainToolbar.removeAction(self.__repeatButton)
        mainToolbar.removeAction(self.__resetButton)

        self.__separator.deleteLater()
        self.__memtopButton.deleteLater()
        self.__debuggerButton.deleteLater()
        self.__repeatButton.deleteLater()
        self.__resetButton.deleteLater()

        WizardInterface.deactivate(self)

    def getConfigFunction(self):
        """Provides a plugun configuration function.

        The plugin can provide a function which will be called when the
        user requests plugin configuring.
        If a plugin does not require any config parameters then None
        should be returned.
        By default no configuring is required.
        """
        return self.configure

    def populateMainMenu(self, parentMenu):
        """Populates the main menu"""
        del parentMenu  # unused argument

    def populateFileContextMenu(self, parentMenu):
        """Populates the file context menu"""
        del parentMenu  # unused argument

    def populateDirectoryContextMenu(self, parentMenu):
        """Populates the directory context menu"""
        del parentMenu  # unused argument

    def populateBufferContextMenu(self, parentMenu):
        """Populates the editing buffer context menu"""
        del parentMenu

    def configure(self):
        """Configure dialog"""
        dlg = IntrospectionPluginConfigDialog(PLUGIN_HOME_DIR,
                                              self.ide.mainWindow)
        if dlg.exec_() == QDialog.Accepted:
            newWhere = dlg.getCheckedOption()
            if newWhere != self.__where:
                self.__where = newWhere
                self.__saveConfiguredWhere()

    def __getConfigFile(self):
        """Provides a directory name where a configuration is stored"""
        return self.ide.settingsDir + "introspection.plugin.json"

    def __getConfiguredWhere(self):
        """Provides the saved configured value"""
        defaultSettings = {'where': IntrospectionPluginConfigDialog.CONSOLE}
        configFile = self.__getConfigFile()
        if not os.path.exists(configFile):
            values = defaultSettings
        else:
            values = loadJSON(configFile, "introspection plugin settings",
                              defaultSettings)
        try:
            value = values['where']
            if value < IntrospectionPluginConfigDialog.LOG or \
               value > IntrospectionPluginConfigDialog.NEW_TAB:
                return IntrospectionPluginConfigDialog.CONSOLE
            return value
        except:
            return IntrospectionPluginConfigDialog.CONSOLE

    def __saveConfiguredWhere(self):
        """Saves the configured where"""
        saveJSON(self.__getConfigFile(), {'where': self.__where},
                 "introspection plugin settings")

    def __onMemtop(self):
        """mem_top report"""
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            print(mem_top(limit=100, width=400))
        except Exception as exc:
            logging.error(str(exc))
        QApplication.restoreOverrideCursor()

    def __onDebugger(self):
        """Brings up a debugger"""
        heap = self.hpy.heap()
        unreachable = self.hpy.heapu()
        logging.error(
            "Use 'heap' and 'unreachable' objects. Type 'c' when finished.")
        QApplication.processEvents()

        oldstdin = sys.stdin
        oldstdout = sys.stdout
        oldstderr = sys.stderr

        sys.stdin = sys.__stdin__
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

        pyqtRemoveInputHook()
        pdb.set_trace()
        pyqtRestoreInputHook()

        sys.stdin = oldstdin
        sys.stdout = oldstdout
        sys.stderr = oldstderr

    def __onRepeatedAction(self):
        """Repeated action"""
        for x in range(100):
            self.ide.mainWindow.em.newTabClicked(initialContent=None,
                                                 shortName=str(x) + '.py',
                                                 mime='text/x-python')
            QApplication.processEvents()
            self.ide.mainWindow.em.onCloseTab()
            QApplication.processEvents()

    def __onResetHeap(self):
        """Resets the heap reference point"""
        self.hpy.setref()
Example #12
0
class MDWidget(QWidget):
    """The MD rendered content widget which goes along with the text editor"""

    sigEscapePressed = pyqtSignal()

    def __init__(self, editor, parent):
        QWidget.__init__(self, parent)

        self.setVisible(False)

        self.__editor = editor
        self.__parentWidget = parent
        self.__connected = False

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)

        # Make pylint happy
        self.__toolbar = None
        self.__topBar = None

        # Create the update timer
        self.__updateTimer = QTimer(self)
        self.__updateTimer.setSingleShot(True)
        self.__updateTimer.timeout.connect(self.process)

        vLayout.addWidget(self.__createTopBar())
        vLayout.addWidget(self.__createMDView())

        hLayout.addLayout(vLayout)
        hLayout.addWidget(self.__createToolbar())
        self.setLayout(hLayout)

        # Connect to the change file type signal
        self.__mainWindow = GlobalData().mainWindow
        editorsManager = self.__mainWindow.em
        editorsManager.sigFileTypeChanged.connect(self.__onFileTypeChanged)

    def __createToolbar(self):
        """Creates the toolbar"""
        self.__toolbar = QToolBar(self)
        self.__toolbar.setOrientation(Qt.Vertical)
        self.__toolbar.setMovable(False)
        self.__toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.__toolbar.setIconSize(QSize(16, 16))
        self.__toolbar.setFixedWidth(30)
        self.__toolbar.setContentsMargins(0, 0, 0, 0)

        # Some control buttons could be added later
        self.printButton = QAction(getIcon('printer.png'), 'Print', self)
        self.printButton.triggered.connect(self.__onPrint)
        self.__toolbar.addAction(self.printButton)

        return self.__toolbar

    def __createTopBar(self):
        """Creates the top bar"""
        self.__topBar = MDTopBar(self)
        return self.__topBar

    def __createMDView(self):
        """Creates the graphics view"""
        self.mdView = MDViewer(self)
        self.mdView.sigEscapePressed.connect(self.__onEsc)
        return self.mdView

    def __onPrint(self):
        """Print the markdown page"""
        dialog = QPrintDialog(self)
        if dialog.exec_() == QDialog.Accepted:
            printer = dialog.printer()
            self.mdView.print_(printer)

    def __onEsc(self):
        """Triggered when Esc is pressed"""
        self.sigEscapePressed.emit()

    def process(self):
        """Parses the content and displays the results"""
        if not self.__connected:
            self.__connectEditorSignals()

        renderedText, errors, warnings = renderMarkdown(
            self.getUUID(), self.__editor.text, self.getFileName())
        if errors:
            self.__topBar.updateInfoIcon(self.__topBar.STATE_BROKEN_UTD)
            self.__topBar.setErrors(errors)
            return
        if renderedText is None:
            self.__topBar.updateInfoIcon(self.__topBar.STATE_BROKEN_UTD)
            self.__topBar.setErrors(['Unknown markdown rendering error'])
            return

        # That will clear the error tooltip as well
        self.__topBar.updateInfoIcon(self.__topBar.STATE_OK_UTD)

        if warnings:
            self.__topBar.setWarnings(warnings)
        else:
            self.__topBar.clearWarnings()

        hsbValue, vsbValue = self.getScrollbarPositions()
        self.mdView.setHtml(renderedText)
        self.setScrollbarPositions(hsbValue, vsbValue)

    def __onFileTypeChanged(self, fileName, uuid, newFileType):
        """Triggered when a buffer content type has changed"""
        if self.getUUID() != uuid:
            return

        if not isMarkdownMime(newFileType):
            self.__disconnectEditorSignals()
            self.__updateTimer.stop()
            self.setVisible(False)
            self.__topBar.updateInfoIcon(self.__topBar.STATE_UNKNOWN)
            return

        # Update the bar and show it
        self.setVisible(True)
        self.process()

        # The buffer type change event comes when the content is loaded first
        # time. So this is a good point to restore the position
        _, _, _, hPos, vPos = getFilePosition(fileName)
        self.setScrollbarPositions(hPos, vPos)

    def terminate(self):
        """Called when a tab is to be closed"""
        self.mdView.terminate()
        self.mdView.deleteLater()

        if self.__updateTimer.isActive():
            self.__updateTimer.stop()
        self.__updateTimer.deleteLater()

        self.__disconnectEditorSignals()

        editorsManager = self.__mainWindow.em
        editorsManager.sigFileTypeChanged.disconnect(self.__onFileTypeChanged)

        self.printButton.triggered.disconnect(self.__onPrint)
        self.printButton.deleteLater()

        self.__topBar.deleteLater()
        self.__toolbar.deleteLater()

        self.__editor = None
        self.__parentWidget = None

    def __connectEditorSignals(self):
        """When it is a python file - connect to the editor signals"""
        if not self.__connected:
            self.__editor.cursorPositionChanged.connect(
                self.__cursorPositionChanged)
            self.__editor.textChanged.connect(self.__onBufferChanged)
            self.__connected = True

    def __disconnectEditorSignals(self):
        """Disconnect the editor signals when the file is not a python one"""
        if self.__connected:
            self.__editor.cursorPositionChanged.disconnect(
                self.__cursorPositionChanged)
            self.__editor.textChanged.disconnect(self.__onBufferChanged)
            self.__connected = False

    def __cursorPositionChanged(self):
        """Cursor position changed"""
        # The timer should be reset only in case if the redrawing was delayed
        if self.__updateTimer.isActive():
            self.__updateTimer.stop()
            self.__updateTimer.start(IDLE_TIMEOUT)

    def __onBufferChanged(self):
        """Triggered to update status icon and to restart the timer"""
        self.__updateTimer.stop()
        if self.__topBar.getCurrentState() in [
                self.__topBar.STATE_OK_UTD, self.__topBar.STATE_OK_CHN,
                self.__topBar.STATE_UNKNOWN
        ]:
            self.__topBar.updateInfoIcon(self.__topBar.STATE_OK_CHN)
        else:
            self.__topBar.updateInfoIcon(self.__topBar.STATE_BROKEN_CHN)
        self.__updateTimer.start(IDLE_TIMEOUT)

    def redrawNow(self):
        """Redraw the diagram regardless of the timer"""
        if self.__updateTimer.isActive():
            self.__updateTimer.stop()
        self.process()

    def getScrollbarPositions(self):
        """Provides the scrollbar positions"""
        return self.mdView.getScrollbarPositions()

    def setScrollbarPositions(self, hPos, vPos):
        """Sets the scrollbar positions for the view"""
        self.mdView.setScrollbarPositions(hPos, vPos)

    def getFileName(self):
        return self.__parentWidget.getFileName()

    def getUUID(self):
        return self.__parentWidget.getUUID()
Example #13
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__excptLabel = QLabel("Ignored exception types", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('ignexcpt')
        self.headerFrame.setStyleSheet('QFrame#ignexcpt {' +
                                       getLabelStyle(self.__excptLabel) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(getIcon('less.png'))
        self.__showHideButton.setFixedSize(HEADER_BUTTON, HEADER_BUTTON)
        self.__showHideButton.setToolTip("Hide ignored exceptions list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__excptLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(False)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)
        self.exceptionsList.setHeaderLabels(["Exception type"])

        self.__excTypeEdit = QLineEdit()
        self.__excTypeEdit.setFixedHeight(26)
        self.__excTypeEdit.textChanged.connect(self.__onNewFilterChanged)
        self.__excTypeEdit.returnPressed.connect(self.__onAddExceptionFilter)
        self.__addButton = QPushButton("Add")
        # self.__addButton.setFocusPolicy(Qt.NoFocus)
        self.__addButton.setEnabled(False)
        self.__addButton.clicked.connect(self.__onAddExceptionFilter)

        expandingSpacer2 = QWidget()
        expandingSpacer2.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        self.__removeButton = QAction(getIcon('delitem.png'),
                                      "Remove selected exception type", self)
        self.__removeButton.triggered.connect(self.__onRemoveFromIgnore)
        self.__removeButton.setEnabled(False)

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

        self.__removeAllButton = QAction(getIcon('ignexcptdelall.png'),
                                         "Remove all the exception types",
                                         self)
        self.__removeAllButton.triggered.connect(self.__onRemoveAllFromIgnore)
        self.__removeAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addWidget(expandingSpacer2)
        self.toolbar.addAction(self.__removeButton)
        self.toolbar.addWidget(fixedSpacer1)
        self.toolbar.addAction(self.__removeAllButton)

        addLayout = QHBoxLayout()
        addLayout.setContentsMargins(1, 1, 1, 1)
        addLayout.setSpacing(1)
        addLayout.addWidget(self.__excTypeEdit)
        addLayout.addWidget(self.__addButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__calltraceLabel = HeaderFitLabel(self)
        self.__calltraceLabel.setText('Call Trace')
        self.__calltraceLabel.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Fixed)
        self.__calltraceLabel.setMinimumWidth(10)

        self.headerToolbar = QToolBar(self)
        self.headerToolbar.setIconSize(QSize(18, 18))
        self.headerToolbar.setContentsMargins(1, 1, 1, 1)
        self.headerToolbar.addWidget(self.__calltraceLabel)

        self.calltraceList = CallTraceBrowser(self)

        self.__startButton = QAction(getIcon('calltracestart.png'),
                                     "Start call tracing", self)
        self.__startButton.triggered.connect(self.__onStart)
        self.__startButton.setEnabled(not Settings()['calltrace'])

        self.__stopButton = QAction(getIcon('calltracestop.png'),
                                    "Stop call tracing", self)
        self.__stopButton.triggered.connect(self.__onStop)
        self.__stopButton.setEnabled(Settings()['calltrace'])

        self.__resizeButton = QAction(getIcon('resizecolumns.png'),
                                      "Resize the columns to their contents",
                                      self)
        self.__resizeButton.triggered.connect(self.__onResize)
        self.__resizeButton.setEnabled(True)

        self.__clearButton = QAction(getIcon('trash.png'), "Clear", self)
        self.__clearButton.triggered.connect(self.__onClear)
        self.__clearButton.setEnabled(False)

        self.__copyButton = QAction(getIcon('copymenu.png'),
                                    "Copy to clipboard", self)
        self.__copyButton.triggered.connect(self.__onCopy)
        self.__copyButton.setEnabled(False)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__startButton)
        self.toolbar.addAction(self.__stopButton)

        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 15))
        self.toolbar.addAction(self.__resizeButton)
        self.toolbar.addAction(self.__copyButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.__clearButton)

        verticalLayout.addWidget(self.headerToolbar)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.calltraceList)
Example #15
0
class IgnoredExceptionsViewer(QWidget):
    """Implements the client exceptions viewer for a debugger"""
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.__createPopupMenu()
        self.__createLayout()
        self.__ignored = []
        self.__currentItem = None

        GlobalData().project.sigProjectChanged.connect(self.__onProjectChanged)

        if not Settings()['showIgnoredExcViewer']:
            self.__onShowHide(True)

    def __createPopupMenu(self):
        """Creates the popup menu"""
        self.__excptMenu = QMenu()
        self.__removeMenuItem = self.__excptMenu.addAction(
            getIcon('ignexcptdel.png'), "Remove from ignore list",
            self.__onRemoveFromIgnore)

    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__excptLabel = QLabel("Ignored exception types", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('ignexcpt')
        self.headerFrame.setStyleSheet('QFrame#ignexcpt {' +
                                       getLabelStyle(self.__excptLabel) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(getIcon('less.png'))
        self.__showHideButton.setFixedSize(HEADER_BUTTON, HEADER_BUTTON)
        self.__showHideButton.setToolTip("Hide ignored exceptions list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__excptLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(False)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)
        self.exceptionsList.setHeaderLabels(["Exception type"])

        self.__excTypeEdit = QLineEdit()
        self.__excTypeEdit.setFixedHeight(26)
        self.__excTypeEdit.textChanged.connect(self.__onNewFilterChanged)
        self.__excTypeEdit.returnPressed.connect(self.__onAddExceptionFilter)
        self.__addButton = QPushButton("Add")
        # self.__addButton.setFocusPolicy(Qt.NoFocus)
        self.__addButton.setEnabled(False)
        self.__addButton.clicked.connect(self.__onAddExceptionFilter)

        expandingSpacer2 = QWidget()
        expandingSpacer2.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        self.__removeButton = QAction(getIcon('delitem.png'),
                                      "Remove selected exception type", self)
        self.__removeButton.triggered.connect(self.__onRemoveFromIgnore)
        self.__removeButton.setEnabled(False)

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

        self.__removeAllButton = QAction(getIcon('ignexcptdelall.png'),
                                         "Remove all the exception types",
                                         self)
        self.__removeAllButton.triggered.connect(self.__onRemoveAllFromIgnore)
        self.__removeAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addWidget(expandingSpacer2)
        self.toolbar.addAction(self.__removeButton)
        self.toolbar.addWidget(fixedSpacer1)
        self.toolbar.addAction(self.__removeAllButton)

        addLayout = QHBoxLayout()
        addLayout.setContentsMargins(1, 1, 1, 1)
        addLayout.setSpacing(1)
        addLayout.addWidget(self.__excTypeEdit)
        addLayout.addWidget(self.__addButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)

    def clear(self):
        """Clears the content"""
        self.exceptionsList.clear()
        self.__excTypeEdit.clear()
        self.__addButton.setEnabled(False)
        self.__ignored = []
        self.__currentItem = None
        self.__updateTitle()

    def __onShowHide(self, startup=False):
        """Triggered when show/hide button is clicked"""
        if startup or self.exceptionsList.isVisible():
            self.exceptionsList.setVisible(False)
            self.__excTypeEdit.setVisible(False)
            self.__addButton.setVisible(False)
            self.__removeButton.setVisible(False)
            self.__removeAllButton.setVisible(False)
            self.__showHideButton.setIcon(getIcon('more.png'))
            self.__showHideButton.setToolTip("Show ignored exceptions list")

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight(self.headerFrame.height())
            self.setMaximumHeight(self.headerFrame.height())

            Settings()['showIgnoredExcViewer'] = False
        else:
            self.exceptionsList.setVisible(True)
            self.__excTypeEdit.setVisible(True)
            self.__addButton.setVisible(True)
            self.__removeButton.setVisible(True)
            self.__removeAllButton.setVisible(True)
            self.__showHideButton.setIcon(getIcon('less.png'))
            self.__showHideButton.setToolTip("Hide ignored exceptions list")

            self.setMinimumHeight(self.__minH)
            self.setMaximumHeight(self.__maxH)

            Settings()['showIgnoredExcViewer'] = True

    def __onSelectionChanged(self):
        """Triggered when the current item is changed"""
        selected = list(self.exceptionsList.selectedItems())
        if selected:
            self.__currentItem = selected[0]
            self.__removeButton.setEnabled(True)
        else:
            self.__currentItem = None
            self.__removeButton.setEnabled(False)

    def __showContextMenu(self, coord):
        """Shows the frames list context menu"""
        contextItem = self.exceptionsList.itemAt(coord)
        if contextItem is not None:
            self.__currentItem = contextItem
            self.__excptMenu.popup(QCursor.pos())

    def __updateTitle(self):
        """Updates the section title"""
        count = self.exceptionsList.topLevelItemCount()
        if count == 0:
            self.__excptLabel.setText("Ignored exception types")
        else:
            self.__excptLabel.setText("Ignored exception types (total: " +
                                      str(count) + ")")
        self.__removeAllButton.setEnabled(count != 0)

    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        project = GlobalData().project
        if project.isLoaded():
            self.__ignored = list(project.exceptionFilters)
        else:
            self.__ignored = Settings()['ignoredExceptions']

        for exceptionType in self.__ignored:
            item = QTreeWidgetItem(self.exceptionsList)
            item.setText(0, exceptionType)
        self.__updateTitle()

    def __onNewFilterChanged(self, text):
        """Triggered when the text is changed"""
        text = str(text).strip()
        if text == "":
            self.__addButton.setEnabled(False)
            return
        if " " in text:
            self.__addButton.setEnabled(False)
            return

        if text in self.__ignored:
            self.__addButton.setEnabled(False)
            return

        self.__addButton.setEnabled(True)

    def __onAddExceptionFilter(self):
        """Adds an item into the ignored exceptions list"""
        text = self.__excTypeEdit.text().strip()
        self.addExceptionFilter(text)

    def addExceptionFilter(self, excType):
        """Adds a new item into the ignored exceptions list"""
        if excType == "":
            return
        if " " in excType:
            return
        if excType in self.__ignored:
            return

        item = QTreeWidgetItem(self.exceptionsList)
        item.setText(0, excType)

        project = GlobalData().project
        if project.isLoaded():
            project.addExceptionFilter(excType)
        else:
            Settings().addExceptionFilter(excType)
        self.__ignored.append(excType)
        self.__updateTitle()

    def __onRemoveFromIgnore(self):
        """Removes an item from the ignored exception types list"""
        if self.__currentItem is None:
            return

        text = self.__currentItem.text(0)

        # Find the item index and remove it
        index = 0
        while True:
            if self.exceptionsList.topLevelItem(index).text(0) == text:
                self.exceptionsList.takeTopLevelItem(index)
                break
            index += 1

        project = GlobalData().project
        if project.isLoaded():
            project.deleteExceptionFilter(text)
        else:
            Settings().deleteExceptionFilter(text)
        self.__ignored.remove(text)
        self.__updateTitle()

    def __onRemoveAllFromIgnore(self):
        """Triggered when all the ignored exceptions should be deleted"""
        self.clear()

        project = GlobalData().project
        if project.isLoaded():
            project.setExceptionFilters([])
        else:
            Settings().setExceptionFilters([])

    def isIgnored(self, exceptionType):
        """Returns True if this exception type should be ignored"""
        return exceptionType in self.__ignored
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__excptLabel = HeaderFitLabel(self)
        self.__excptLabel.setText('Ignored exception types')
        self.__excptLabel.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Fixed)
        self.__excptLabel.setMinimumWidth(10)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(getIcon('less.png'))
        self.__showHideButton.setFixedSize(self.__excptLabel.height(),
                                           self.__excptLabel.height())
        self.__showHideButton.setToolTip('Hide ignored exceptions list')
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.onShowHide)

        self.headerToolbar = QToolBar(self)
        self.headerToolbar.setIconSize(QSize(16, 16))
        self.headerToolbar.setContentsMargins(1, 1, 1, 1)
        self.headerToolbar.addWidget(self.__excptLabel)
        self.headerToolbar.addWidget(self.__showHideButton)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(False)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)
        self.exceptionsList.setHeaderLabels(["Exception type"])

        self.__excTypeEdit = QLineEdit()
        self.__excTypeEdit.setFixedHeight(26)
        self.__excTypeEdit.textChanged.connect(self.__onNewFilterChanged)
        self.__excTypeEdit.returnPressed.connect(self.__onAddExceptionFilter)
        self.__addButton = QPushButton("Add")
        # self.__addButton.setFocusPolicy(Qt.NoFocus)
        self.__addButton.setEnabled(False)
        self.__addButton.clicked.connect(self.__onAddExceptionFilter)

        self.__removeButton = QAction(getIcon('delitem.png'),
                                      "Remove selected exception type", self)
        self.__removeButton.triggered.connect(self.__onRemoveFromIgnore)
        self.__removeButton.setEnabled(False)

        self.__removeAllButton = QAction(getIcon('ignexcptdelall.png'),
                                         "Remove all the exception types",
                                         self)
        self.__removeAllButton.triggered.connect(self.__onRemoveAllFromIgnore)
        self.__removeAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.__removeButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addAction(self.__removeAllButton)

        addLayout = QHBoxLayout()
        addLayout.setContentsMargins(1, 1, 1, 1)
        addLayout.setSpacing(1)
        addLayout.addWidget(self.__excTypeEdit)
        addLayout.addWidget(self.__addButton)

        verticalLayout.addWidget(self.headerToolbar)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)
Example #17
0
class SearchResultsViewer(QWidget):

    """Search results viewer tab widget"""

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.__results = QStackedWidget(self)

        self.__bufferChangeConnected = False

        # Prepare members for reuse
        self.__noneLabel = QLabel("\nNo results available")

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin['nolexerPaper'])
        self.__noneLabel.setPalette(noneLabelPalette)

        self.__createLayout(parent)
        self.__updateButtonsStatus()

        GlobalData().project.sigProjectChanged.connect(self.__onProjectChanged)

    def __createLayout(self, parent):
        """Creates the toolbar and layout"""
        del parent  # unused argument

        # Buttons etc.
        self.clearButton = QAction(getIcon('trash.png'),
                                   'Delete current results', self)
        self.clearButton.triggered.connect(self.__clear)

        self.prevButton = QAction(getIcon('1leftarrow.png'),
                                  'Previous results', self)
        self.prevButton.triggered.connect(self.__previous)

        self.nextButton = QAction(getIcon('1rightarrow.png'),
                                  'Next results', self)
        self.nextButton.triggered.connect(self.__next)

        self.doAgainButton = QAction(getIcon('searchagain.png'),
                                     'Do again', self)
        self.doAgainButton.triggered.connect(self.__doAgain)

        self.removeItemButton = QAction(getIcon('delitem.png'),
                                        'Remove currently selected item (Del)',
                                        self)
        self.removeItemButton.triggered.connect(self.__removeItem)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.prevButton)
        self.toolbar.addAction(self.nextButton)
        self.toolbar.addAction(self.doAgainButton)
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.removeItemButton)
        self.toolbar.addAction(self.clearButton)

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__results)
        self.__results.hide()

        self.setLayout(self.__hLayout)

    def __isReportShown(self):
        """True is any of the reports is shown"""
        return self.__results.count() > 0

    def getResultsViewer(self):
        """Provides a reference to the results tree"""
        return self.__results

    def __updateButtonsStatus(self):
        """Updates the buttons status"""
        if self.__isReportShown():
            index = self.__results.currentIndex()
            widget = self.__results.currentWidget()
            self.prevButton.setEnabled(index > 0)
            self.nextButton.setEnabled(index < self.__results.count() - 1)
            self.doAgainButton.setEnabled(widget.canDoAgain())
            self.removeItemButton.setEnabled(widget.selectedItem is not None)
            self.clearButton.setEnabled(True)
        else:
            self.prevButton.setEnabled(False)
            self.nextButton.setEnabled(False)
            self.doAgainButton.setEnabled(False)
            self.removeItemButton.setEnabled(False)
            self.clearButton.setEnabled(False)

    def __updateIndicators(self):
        """Updates all the indicators"""
        total = self.__results.count()
        for index in range(total):
            self.__results.widget(index).updateIndicator(index + 1, total)

    def setFocus(self):
        """Overridden setFocus"""
        self.__hLayout.setFocus()

    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what == CodimensionProject.CompleteProject:
            self.__saveProjectResults()
            self.__populateForProject()

    def __connectBufferChange(self):
        """Connects the sigBufferChange"""
        if not self.__bufferChangeConnected:
            self.__bufferChangeConnected = True
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.sigBufferModified.connect(self.onBufferModified)

    def __disconnectBufferChange(self):
        """Disconnects the sigBufferModified signal"""
        if self.__bufferChangeConnected:
            self.__bufferChangeConnected = False
            mainWindow = GlobalData().mainWindow
            editorsManager = mainWindow.editorsManagerWidget.editorsManager
            editorsManager.sigBufferModified.disconnect(self.onBufferModified)

    def onBufferModified(self, fileName, uuid):
        """Triggered when a buffer is modified"""
        for index in range(self.__results.count()):
            self.__results.widget(index).resultsTree.onBufferModified(
                fileName, uuid)

    def __previous(self):
        """Switch to the previous results"""
        if self.__isReportShown():
            index = self.__results.currentIndex()
            if index > 0:
                self.__results.setCurrentIndex(index - 1)
                self.__updateButtonsStatus()

    def __next(self):
        """Switch to the next results"""
        if self.__isReportShown():
            index = self.__results.currentIndex()
            if index < self.__results.count() - 1:
                self.__results.setCurrentIndex(index + 1)
                self.__updateButtonsStatus()

    def keyPressEvent(self, event):
        """Del key processing"""
        if event.key() == Qt.Key_Delete:
            event.accept()
            self.__removeItem()
        else:
            QWidget.keyPressEvent(self, event)

    def __removeItem(self):
        """Removes one entry of the search"""
        widget = self.__results.currentWidget()
        if widget.selectedItem is None:
            return

        widget.removeSelectedItem()
        if widget.resultsTree.topLevelItemCount() == 0:
            # The last result, need to remove the search result
            self.__clear()
        else:
            self.__updateButtonsStatus()

    def __clear(self):
        """Clears the content of the vertical layout"""
        if not self.__isReportShown():
            return

        index = self.__results.currentIndex()
        widget = self.__results.currentWidget()
        widget.clear()

        if self.__results.count() == 1:
            self.__results.hide()
            self.__noneLabel.show()
            self.__disconnectBufferChange()

        self.__results.removeWidget(widget)
        widget.deleteLater()

        if self.__results.count() > 0:
            if index >= self.__results.count():
                index -= 1
            self.__results.setCurrentIndex(index)

        self.__updateButtonsStatus()
        self.__updateIndicators()

    def __doAgain(self):
        """Performs the action once again"""
        if self.__isReportShown():
            self.__results.currentWidget().doAgain(self)

    def showReport(self, providerId, results, parameters, searchId=None):
        """Shows the find in files results"""
        # Memorize the screen width
        searchTooltip.setScreenWidth(
            GlobalData().application.desktop().screenGeometry().width())

        if searchId is None:
            resultWidget = ResultsViewerWidget(providerId, results,
                                               parameters,
                                               str(uuid1()), self)
            index = self.__results.addWidget(resultWidget)
        else:
            # Find the widget with this searchId
            found = False
            for index in range(self.__results.count()):
                if self.__results.widget(index).searchId == searchId:
                    found = True
                    break
            if not found:
                # add as a new one
                resultWidget = ResultsViewerWidget(providerId, results,
                                                   parameters,
                                                   str(uuid1()), self)
                index = self.__results.addWidget(resultWidget)
            else:
                # Repopulate it
                widget = self.__results.widget(index)
                widget.populate(results)

        self.__results.setCurrentIndex(index)

        # Show the complete information
        self.__noneLabel.hide()
        self.__results.show()

        self.__updateButtonsStatus()
        self.__updateIndicators()
        self.__connectBufferChange()

    def __populateForProject(self):
        """Load the project saved search results"""

    def __saveProjectResults(self):
        """Serialize to the disk the search results"""
Example #18
0
    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        self.__toggleViewButton = QAction(getIcon('tableview.png'),
                                          'Switch to table view', self)
        self.__toggleViewButton.setCheckable(True)
        self.__toggleViewButton.toggled.connect(self.__switchView)

        self.__togglePathButton = QAction(getIcon('longpath.png'),
                                          'Show full paths for item location',
                                          self)
        self.__togglePathButton.setCheckable(True)
        self.__togglePathButton.toggled.connect(self.__togglePath)
        self.__togglePathButton.setEnabled(False)

        self.__printButton = QAction(getIcon('printer.png'), 'Print', self)
        self.__printButton.triggered.connect(self.__onPrint)
        self.__printButton.setEnabled(False)

        self.__printPreviewButton = QAction(getIcon('printpreview.png'),
                                            'Print preview', self)
        self.__printPreviewButton.triggered.connect(self.__onPrintPreview)
        self.__printPreviewButton.setEnabled(False)

        fixedSpacer = QWidget()
        fixedSpacer.setFixedHeight(16)

        self.__zoomInButton = QAction(getIcon('zoomin.png'),
                                      'Zoom in (Ctrl+=)', self)
        self.__zoomInButton.setShortcut('Ctrl+=')
        self.__zoomInButton.triggered.connect(self.onZoomIn)

        self.__zoomOutButton = QAction(getIcon('zoomout.png'),
                                       'Zoom out (Ctrl+-)', self)
        self.__zoomOutButton.setShortcut('Ctrl+-')
        self.__zoomOutButton.triggered.connect(self.onZoomOut)

        self.__zoomResetButton = QAction(getIcon('zoomreset.png'),
                                         'Zoom reset (Ctrl+0)', self)
        self.__zoomResetButton.setShortcut('Ctrl+0')
        self.__zoomResetButton.triggered.connect(self.onZoomReset)

        # Toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(self.__toggleViewButton)
        toolbar.addAction(self.__togglePathButton)
        toolbar.addAction(self.__printPreviewButton)
        toolbar.addAction(self.__printButton)
        toolbar.addWidget(fixedSpacer)
        toolbar.addAction(self.__zoomInButton)
        toolbar.addAction(self.__zoomOutButton)
        toolbar.addAction(self.__zoomResetButton)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(self.__profTable)
        hLayout.addWidget(self.__profGraph)
        hLayout.addWidget(toolbar)

        self.setLayout(hLayout)
Example #19
0
    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        printButton = QAction(getIcon('printer.png'), 'Print (Ctrl+P)', self)
        printButton.triggered.connect(self.__onPrint)

        printPreviewButton = QAction(getIcon('printpreview.png'),
                                     'Print preview', self)
        printPreviewButton.triggered.connect(self.__onPrintPreview)
        printPreviewButton.setEnabled(False)
        printPreviewButton.setVisible(False)

        printSpacer = QWidget()
        printSpacer.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        printSpacer.setFixedHeight(8)

        # Imports diagram and its menu
        importsMenu = QMenu(self)
        importsDlgAct = importsMenu.addAction(getIcon('detailsdlg.png'),
                                              'Fine tuned imports diagram')
        importsDlgAct.triggered.connect(self.onImportDgmTuned)
        self.importsDiagramButton = QToolButton(self)
        self.importsDiagramButton.setIcon(getIcon('importsdiagram.png'))
        self.importsDiagramButton.setToolTip('Generate imports diagram')
        self.importsDiagramButton.setPopupMode(QToolButton.DelayedPopup)
        self.importsDiagramButton.setMenu(importsMenu)
        self.importsDiagramButton.setFocusPolicy(Qt.NoFocus)
        self.importsDiagramButton.clicked.connect(self.onImportDgm)
        self.importsDiagramButton.setEnabled(False)

        # Run script and its menu
        runScriptMenu = QMenu(self)
        runScriptDlgAct = runScriptMenu.addAction(getIcon('detailsdlg.png'),
                                                  'Set run/debug parameters')
        runScriptDlgAct.triggered.connect(self.onRunScriptDlg)
        self.runScriptButton = QToolButton(self)
        self.runScriptButton.setIcon(getIcon('run.png'))
        self.runScriptButton.setToolTip('Run script')
        self.runScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.runScriptButton.setMenu(runScriptMenu)
        self.runScriptButton.setFocusPolicy(Qt.NoFocus)
        self.runScriptButton.clicked.connect(self.onRunScript)
        self.runScriptButton.setEnabled(False)

        # Profile script and its menu
        profileScriptMenu = QMenu(self)
        profileScriptDlgAct = profileScriptMenu.addAction(
            getIcon('detailsdlg.png'), 'Set profile parameters')
        profileScriptDlgAct.triggered.connect(self.onProfileScriptDlg)
        self.profileScriptButton = QToolButton(self)
        self.profileScriptButton.setIcon(getIcon('profile.png'))
        self.profileScriptButton.setToolTip('Profile script')
        self.profileScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.profileScriptButton.setMenu(profileScriptMenu)
        self.profileScriptButton.setFocusPolicy(Qt.NoFocus)
        self.profileScriptButton.clicked.connect(self.onProfileScript)
        self.profileScriptButton.setEnabled(False)

        # Debug script and its menu
        debugScriptMenu = QMenu(self)
        debugScriptDlgAct = debugScriptMenu.addAction(
            getIcon('detailsdlg.png'), 'Set run/debug parameters')
        debugScriptDlgAct.triggered.connect(self.onDebugScriptDlg)
        self.debugScriptButton = QToolButton(self)
        self.debugScriptButton.setIcon(getIcon('debugger.png'))
        self.debugScriptButton.setToolTip('Debug script')
        self.debugScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.debugScriptButton.setMenu(debugScriptMenu)
        self.debugScriptButton.setFocusPolicy(Qt.NoFocus)
        self.debugScriptButton.clicked.connect(self.onDebugScript)
        self.debugScriptButton.setEnabled(False)

        # Disassembling
        disasmScriptMenu = QMenu(self)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (no optimization)',
                                   self.__editor._onDisasm0)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (optimization level 1)',
                                   self.__editor._onDisasm1)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (optimization level 2)',
                                   self.__editor._onDisasm2)
        self.disasmScriptButton = QToolButton(self)
        self.disasmScriptButton.setIcon(getIcon('disassembly.png'))
        self.disasmScriptButton.setToolTip('Disassembly script')
        self.disasmScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.disasmScriptButton.setMenu(disasmScriptMenu)
        self.disasmScriptButton.setFocusPolicy(Qt.NoFocus)
        self.disasmScriptButton.clicked.connect(self.__editor._onDisasm0)
        self.disasmScriptButton.setEnabled(False)

        # Dead code
        self.deadCodeScriptButton = QAction(getIcon('deadcode.png'),
                                            'Find dead code', self)
        self.deadCodeScriptButton.triggered.connect(self.__onDeadCode)
        self.deadCodeScriptButton.setEnabled(False)

        undoSpacer = QWidget()
        undoSpacer.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        undoSpacer.setFixedHeight(8)

        self.__undoButton = QAction(getIcon('undo.png'), 'Undo (Ctrl+Z)', self)
        self.__undoButton.setShortcut('Ctrl+Z')
        self.__undoButton.triggered.connect(self.__editor.onUndo)
        self.__undoButton.setEnabled(False)

        self.__redoButton = QAction(getIcon('redo.png'), 'Redo (Ctrl+Y)', self)
        self.__redoButton.setShortcut('Ctrl+Y')
        self.__redoButton.triggered.connect(self.__editor.onRedo)
        self.__redoButton.setEnabled(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.removeTrailingSpacesButton = QAction(getIcon('trailingws.png'),
                                                  'Remove trailing spaces',
                                                  self)
        self.removeTrailingSpacesButton.triggered.connect(
            self.onRemoveTrailingWS)
        self.expandTabsButton = QAction(getIcon('expandtabs.png'),
                                        'Expand tabs (4 spaces)', self)
        self.expandTabsButton.triggered.connect(self.onExpandTabs)

        # The toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(30)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(printPreviewButton)
        toolbar.addAction(printButton)
        toolbar.addWidget(printSpacer)
        toolbar.addWidget(self.importsDiagramButton)
        toolbar.addWidget(self.runScriptButton)
        toolbar.addWidget(self.profileScriptButton)
        toolbar.addWidget(self.debugScriptButton)
        toolbar.addWidget(self.disasmScriptButton)
        toolbar.addAction(self.deadCodeScriptButton)
        toolbar.addWidget(undoSpacer)
        toolbar.addAction(self.__undoButton)
        toolbar.addAction(self.__redoButton)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.removeTrailingSpacesButton)
        toolbar.addAction(self.expandTabsButton)

        self.importsBar = ImportListWidget(self.__editor)
        self.importsBar.hide()

        self.__outsideChangesBar = OutsideChangeWidget(self.__editor)
        self.__outsideChangesBar.sigReloadRequest.connect(self.__onReload)
        self.__outsideChangesBar.reloadAllNonModifiedRequest.connect(
            self.reloadAllNonModified)
        self.__outsideChangesBar.hide()

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)

        self.__navigationBar = NavigationBar(self.__editor, self)
        vLayout.addWidget(self.__navigationBar)
        vLayout.addWidget(self.__editor)

        hLayout.addLayout(vLayout)
        hLayout.addWidget(toolbar)
        widget = QWidget()
        widget.setLayout(hLayout)

        self.__splitter = QSplitter(Qt.Horizontal, self)

        self.__flowUI = FlowUIWidget(self.__editor, self)
        self.__mdView = MDWidget(self.__editor, self)

        self.__renderLayout = QVBoxLayout()
        self.__renderLayout.setContentsMargins(0, 0, 0, 0)
        self.__renderLayout.setSpacing(0)
        self.__renderLayout.addWidget(self.__flowUI)
        self.__renderLayout.addWidget(self.__mdView)
        self.__renderWidget = QWidget()
        self.__renderWidget.setLayout(self.__renderLayout)

        self.__splitter.addWidget(widget)
        self.__splitter.addWidget(self.__renderWidget)

        containerLayout = QHBoxLayout()
        containerLayout.setContentsMargins(0, 0, 0, 0)
        containerLayout.setSpacing(0)
        containerLayout.addWidget(self.__splitter)
        self.setLayout(containerLayout)

        self.__renderWidget.setVisible(False)

        self.__splitter.setSizes(Settings()['flowSplitterSizes'])
        self.__splitter.splitterMoved.connect(self.flowSplitterMoved)
        Settings().sigFlowSplitterChanged.connect(self.otherFlowSplitterMoved)
Example #20
0
    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)
Example #21
0
class BreakPointViewer(QWidget):
    """Implements the break point viewer for a debugger"""
    def __init__(self, parent, bpointsModel):
        QWidget.__init__(self, parent)

        self.__currentItem = None
        self.__createLayout(bpointsModel)

        GlobalData().project.sigProjectChanged.connect(self.__onProjectChanged)
        GlobalData().project.sigProjectAboutToUnload.connect(
            self.__onProjectAboutToUnload)
        self.bpointsList.sigSelectionChanged.connect(self.__onSelectionChanged)
        bpointsModel.sigBreakpoinsChanged.connect(self.__onModelChanged)

    def setFocus(self):
        """Sets the widget focus"""
        self.bpointsList.setFocus()

    def __createLayout(self, bpointsModel):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('bpheader')
        self.headerFrame.setStyleSheet('QFrame#bpheader {' +
                                       getLabelStyle(self) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        self.__breakpointLabel = QLabel("Breakpoints")

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__breakpointLabel)
        self.headerFrame.setLayout(headerLayout)

        self.bpointsList = BreakPointView(self, bpointsModel)

        self.__editButton = QAction(getIcon('bpprops.png'),
                                    "Edit breakpoint properties", self)
        self.__editButton.triggered.connect(self.__onEdit)
        self.__editButton.setEnabled(False)

        self.__jumpToCodeButton = QAction(getIcon('gotoline.png'),
                                          "Jump to the code", self)
        self.__jumpToCodeButton.triggered.connect(self.__onJumpToCode)
        self.__jumpToCodeButton.setEnabled(False)

        self.__enableButton = QAction(getIcon('bpenable.png'),
                                      "Enable selected breakpoint", self)
        self.__enableButton.triggered.connect(self.__onEnableDisable)
        self.__enableButton.setEnabled(False)

        self.__disableButton = QAction(getIcon('bpdisable.png'),
                                       "Disable selected breakpoint", self)
        self.__disableButton.triggered.connect(self.__onEnableDisable)
        self.__disableButton.setEnabled(False)

        self.__enableAllButton = QAction(getIcon('bpenableall.png'),
                                         "Enable all the breakpoint", self)
        self.__enableAllButton.triggered.connect(self.__onEnableAll)
        self.__enableAllButton.setEnabled(False)

        self.__disableAllButton = QAction(getIcon('bpdisableall.png'),
                                          "Disable all the breakpoint", self)
        self.__disableAllButton.triggered.connect(self.__onDisableAll)
        self.__disableAllButton.setEnabled(False)

        self.__delButton = QAction(getIcon('delitem.png'),
                                   "Delete selected breakpoint", self)
        self.__delButton.triggered.connect(self.__onDel)
        self.__delButton.setEnabled(False)

        self.__delAllButton = QAction(getIcon('bpdelall.png'),
                                      "Delete all the breakpoint", self)
        self.__delAllButton.triggered.connect(self.__onDelAll)
        self.__delAllButton.setEnabled(False)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__editButton)
        self.toolbar.addAction(self.__jumpToCodeButton)
        fixedSpacer2 = QWidget()
        fixedSpacer2.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer2)
        self.toolbar.addAction(self.__enableButton)
        self.toolbar.addAction(self.__enableAllButton)
        fixedSpacer3 = QWidget()
        fixedSpacer3.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer3)
        self.toolbar.addAction(self.__disableButton)
        self.toolbar.addAction(self.__disableAllButton)
        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        fixedSpacer4 = QWidget()
        fixedSpacer4.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer4)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__delButton)
        fixedSpacer5 = QWidget()
        fixedSpacer5.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer5)
        self.toolbar.addAction(self.__delAllButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.bpointsList)

    def clear(self):
        """Clears the content"""
        self.__onDelAll()
        self.__updateBreakpointsLabel()
        self.__currentItem = None

    def __updateBreakpointsLabel(self):
        """Updates the breakpoints header label"""
        enableCount, \
        disableCount = self.bpointsList.model().sourceModel().getCounts()
        total = enableCount + disableCount
        if total > 0:
            self.__breakpointLabel.setText("Breakpoints (total: " +
                                           str(total) + ")")
        else:
            self.__breakpointLabel.setText("Breakpoints")

    def __onProjectChanged(self, what):
        """Triggered when a project is changed"""
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        model = self.bpointsList.model().sourceModel()
        project = GlobalData().project
        if project.isLoaded():
            bpoints = project.breakpoints
        else:
            bpoints = Settings().breakpoints

        for bpoint in bpoints:
            newBpoint = Breakpoint()
            try:
                if not newBpoint.deserialize(bpoint):
                    # Non valid
                    continue
            except:
                continue
            # Need to check if it still points to a breakable line
            line = newBpoint.getLineNumber()
            fileName = newBpoint.getAbsoluteFileName()
            breakableLines = getBreakpointLines(fileName, None, True)
            if breakableLines is not None and line in breakableLines:
                model.addBreakpoint(newBpoint)
            else:
                logging.warning("Breakpoint at " + fileName + ":" + str(line) +
                                " does not point to a breakable "
                                "line anymore (the file is invalid or was "
                                "modified outside of the "
                                "IDE etc.). The breakpoint is deleted.")

    def __onProjectAboutToUnload(self):
        """Triggered before the project is unloaded"""
        self.__serializeBreakpoints()

    def __serializeBreakpoints(self):
        """Saves the breakpoints into a file"""
        model = self.bpointsList.model().sourceModel()

        project = GlobalData().project
        if project.isLoaded():
            project.breakpoints = model.serialize()
        else:
            Settings().breakpoints = model.serialize()

    def __onSelectionChanged(self, index):
        """Triggered when the current item is changed"""
        if index.isValid():
            srcModel = self.bpointsList.model().sourceModel()
            sindex = self.bpointsList.toSourceIndex(index)
            self.__currentItem = srcModel.getBreakPointByIndex(sindex)
        else:
            self.__currentItem = None
        self.__updateButtons()

    def __updateButtons(self):
        """Updates the buttons status"""
        enableCount, \
        disableCount = self.bpointsList.model().sourceModel().getCounts()

        if self.__currentItem is None:
            self.__editButton.setEnabled(False)
            self.__enableButton.setEnabled(False)
            self.__disableButton.setEnabled(False)
            self.__jumpToCodeButton.setEnabled(False)
            self.__delButton.setEnabled(False)
        else:
            self.__editButton.setEnabled(True)
            self.__enableButton.setEnabled(not self.__currentItem.isEnabled())
            self.__disableButton.setEnabled(self.__currentItem.isEnabled())
            self.__jumpToCodeButton.setEnabled(True)
            self.__delButton.setEnabled(True)

        self.__enableAllButton.setEnabled(disableCount > 0)
        self.__disableAllButton.setEnabled(enableCount > 0)
        self.__delAllButton.setEnabled(enableCount + disableCount > 0)

    def __onEnableDisable(self):
        """Triggered when a breakpoint should be enabled/disabled"""
        if self.__currentItem is not None:
            if self.__currentItem.isEnabled():
                self.bpointsList.disableBreak()
            else:
                self.bpointsList.enableBreak()

    def __onEdit(self):
        """Triggered when a breakpoint should be edited"""
        if self.__currentItem is None:
            return

        dlg = BreakpointEditDialog(self.__currentItem)
        if dlg.exec_() == QDialog.Accepted:
            newBpoint = dlg.getData()
            if newBpoint == self.__currentItem:
                return
            model = self.bpointsList.model().sourceModel()
            index = model.getBreakPointIndex(
                self.__currentItem.getAbsoluteFileName(),
                self.__currentItem.getLineNumber())
            model.setBreakPointByIndex(index, newBpoint)
            self.bpointsList.layoutDisplay()

    def __onJumpToCode(self):
        """Triggered when should jump to source"""
        if self.__currentItem is None:
            return
        self.bpointsList.jumpToCode(self.__currentItem.getAbsoluteFileName(),
                                    self.__currentItem.getLineNumber())

    def __onEnableAll(self):
        """Triggered when all the breakpoints should be enabled"""
        self.bpointsList.enableAllBreaks()

    def __onDisableAll(self):
        """Triggered when all the breakpoints should be disabled"""
        self.bpointsList.disableAllBreaks()

    def __onDel(self):
        """Triggered when a breakpoint should be deleted"""
        if self.__currentItem is not None:
            self.bpointsList.deleteBreak()

    def __onDelAll(self):
        """Triggered when all the breakpoints should be deleted"""
        self.bpointsList.deleteAllBreaks()

    def __onModelChanged(self):
        """Triggered when something has changed in any of the breakpoints"""
        self.__updateBreakpointsLabel()
        self.__updateButtons()
        self.bpointsList.layoutDisplay()

        self.__serializeBreakpoints()
Example #22
0
    def __createLayout(self, pluginHomeDir):
        """Creates the layout"""
        self.clearButton = QAction(getIcon('trash.png'), 'Clear', self)
        self.clearButton.triggered.connect(self.clear)

        self.outputButton = QAction(QIcon(pluginHomeDir + 'output.png'),
                                    'Show pylint raw stdout and stderr', self)
        self.outputButton.triggered.connect(self.__showOutput)

        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.outputButton)
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.clearButton)

        self.__resultsTree = QTreeWidget(self)
        self.__resultsTree.setAlternatingRowColors(True)
        self.__resultsTree.setRootIsDecorated(True)
        self.__resultsTree.setItemsExpandable(True)
        self.__resultsTree.setUniformRowHeights(True)
        self.__resultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ['Message type / line', 'id', 'Message']
        self.__resultsTree.setHeaderLabels(headerLabels)
        self.__resultsTree.itemActivated.connect(self.__resultActivated)

        self.__fileLabel = HeaderFitPathLabel(None, self)
        self.__fileLabel.setAlignment(Qt.AlignLeft)
        self.__fileLabel.setMinimumWidth(50)
        self.__fileLabel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.__fileLabel.doubleClicked.connect(self.onPathLabelDoubleClick)
        self.__fileLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self.__fileLabel.customContextMenuRequested.connect(
            self.showPathLabelContextMenu)

        self.__rateLabel = HeaderLabel()
        self.__rateLabel.setToolTip('pylint analysis rate out of 10 '
                                    '(previous run if there was one)')
        self.__timestampLabel = HeaderLabel()
        self.__timestampLabel.setToolTip('pylint analysis timestamp')
        self.__labelLayout = QHBoxLayout()
        self.__labelLayout.setSpacing(4)
        self.__labelLayout.addWidget(self.__fileLabel)
        self.__labelLayout.addWidget(self.__rateLabel)
        self.__labelLayout.addWidget(self.__timestampLabel)

        self.__vLayout = QVBoxLayout()
        self.__vLayout.setSpacing(4)
        self.__vLayout.addLayout(self.__labelLayout)
        self.__vLayout.addWidget(self.__resultsTree)

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addLayout(self.__vLayout)

        self.setLayout(self.__hLayout)
        self.__updateButtons()
Example #23
0
class PylintResultViewer(QWidget):

    """Pylint results viewer"""

    def __init__(self, ide, pluginHomeDir, parent=None):
        QWidget.__init__(self, parent)

        self.__results = None
        self.__ide = ide
        self.__pluginHomeDir = pluginHomeDir

        self.__noneLabel = QLabel("\nNo results available")
        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        font = self.__noneLabel.font()
        font.setPointSize(font.pointSize() + 4)
        self.__noneLabel.setFont(font)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin['nolexerPaper'])
        self.__noneLabel.setPalette(noneLabelPalette)

        self.__createLayout(self.__pluginHomeDir)

    def __createLayout(self, pluginHomeDir):
        """Creates the layout"""
        self.clearButton = QAction(getIcon('trash.png'), 'Clear', self)
        self.clearButton.triggered.connect(self.clear)

        self.outputButton = QAction(QIcon(pluginHomeDir + 'output.png'),
                                    'Show pylint raw stdout and stderr', self)
        self.outputButton.triggered.connect(self.__showOutput)

        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.outputButton)
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.clearButton)

        self.__resultsTree = QTreeWidget(self)
        self.__resultsTree.setAlternatingRowColors(True)
        self.__resultsTree.setRootIsDecorated(True)
        self.__resultsTree.setItemsExpandable(True)
        self.__resultsTree.setUniformRowHeights(True)
        self.__resultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ['Message type / line', 'id', 'Message']
        self.__resultsTree.setHeaderLabels(headerLabels)
        self.__resultsTree.itemActivated.connect(self.__resultActivated)

        self.__fileLabel = HeaderFitPathLabel(None, self)
        self.__fileLabel.setAlignment(Qt.AlignLeft)
        self.__fileLabel.setMinimumWidth(50)
        self.__fileLabel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.__fileLabel.doubleClicked.connect(self.onPathLabelDoubleClick)
        self.__fileLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self.__fileLabel.customContextMenuRequested.connect(
            self.showPathLabelContextMenu)

        self.__rateLabel = HeaderLabel()
        self.__rateLabel.setToolTip('pylint analysis rate out of 10 '
                                    '(previous run if there was one)')
        self.__timestampLabel = HeaderLabel()
        self.__timestampLabel.setToolTip('pylint analysis timestamp')
        self.__labelLayout = QHBoxLayout()
        self.__labelLayout.setSpacing(4)
        self.__labelLayout.addWidget(self.__fileLabel)
        self.__labelLayout.addWidget(self.__rateLabel)
        self.__labelLayout.addWidget(self.__timestampLabel)

        self.__vLayout = QVBoxLayout()
        self.__vLayout.setSpacing(4)
        self.__vLayout.addLayout(self.__labelLayout)
        self.__vLayout.addWidget(self.__resultsTree)

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addLayout(self.__vLayout)

        self.setLayout(self.__hLayout)
        self.__updateButtons()

    def __updateButtons(self):
        """Updates the toolbar buttons approprietly"""
        self.clearButton.setEnabled(self.__results is not None)

        if self.__results is not None:
            stdout = self.__results.get('StdOut', None)
            stderr = self.__results.get('StdErr', None)
            self.outputButton.setEnabled(stdout is not None or
                                         stderr is not None)
        else:
            self.outputButton.setEnabled(False)

    def showResults(self, results):
        """Populates the analysis results"""
        self.clear()
        self.__noneLabel.setVisible(False)
        self.__fileLabel.setVisible(True)
        self.__rateLabel.setVisible(True)
        self.__timestampLabel.setVisible(True)
        self.__resultsTree.setVisible(True)

        self.__results = results
        self.__updateButtons()

        tooltip = ' '.join(['pylint results for',
                            os.path.basename(results['FileName']),
                            'at',
                            results['Timestamp']])
        self.__ide.sideBars['bottom'].setTabToolTip('pylint', tooltip)

        self.__fileLabel.setPath(results['FileName'])
        if 'Rate' in results:
            text = str(results['Rate'])
            if 'PreviousRunRate' in results:
                text += ' (' + str(results['PreviousRunRate']) + ')'
            self.__rateLabel.setText(' ' + text + ' ')
        else:
            self.__rateLabel.setVisible(False)
        self.__timestampLabel.setText(results['Timestamp'])

        totalMessages = 0
        totalMessages += self.__populateMessages('Errors')
        totalMessages += self.__populateMessages('Warnings')
        totalMessages += self.__populateMessages('Refactoring')
        totalMessages += self.__populateMessages('Cosmetics')

        # Update the header with the total number of matches
        headerLabels = ['Message type / line', 'id',
                        'Message (total messages: ' + str(totalMessages) + ')']
        self.__resultsTree.setHeaderLabels(headerLabels)

        # Resizing
        self.__resultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)

    def __populateMessages(self, title):
        """Populates the analysis messages"""
        count = len(self.__results[title[0]])
        if count > 0:
            suffix = '' if count == 1 else 's'
            messageTypeItem = MessageTypeTableItem(
                [title, '', '(' + str(count) + ' message' + suffix + ')'])
            self.__resultsTree.addTopLevelItem(messageTypeItem)
            for item in self.__results[title[0]]:
                columns = [str(item[1]), item[3], item[2]]
                messageItem = MessageTableItem(columns)
                messageTypeItem.addChild(messageItem)
            messageTypeItem.setExpanded(True)
        return count

    def clear(self):
        """Clears the results view"""
        self.__results = None
        self.__updateButtons()

        tooltip = 'No results available'
        self.__ide.sideBars['bottom'].setTabToolTip('pylint', tooltip)
        self.__noneLabel.setVisible(True)

        self.__fileLabel.setVisible(False)
        self.__rateLabel.setVisible(False)
        self.__timestampLabel.setVisible(False)
        self.__resultsTree.setVisible(False)
        self.__resultsTree.clear()

    def __resultActivated(self, item, column):
        """Handles the double click (or Enter) on a message"""
        del column  # unused argument
        if self.__results:
            if isinstance(item, MessageTableItem):
                fileName = self.__results['FileName']
                lineNumber = int(item.data(0, Qt.DisplayRole))
                self.__ide.mainWindow.openFile(fileName, lineNumber)

    def __showOutput(self):
        """Shows the analysis stdout and stderr"""
        if self.__results is None:
            return

        # Show a separate dialog
        PylintStdoutStderrViewer(self.__ide.mainWindow,
                                 self.__results).exec_()

    def onPathLabelDoubleClick(self):
        """Double click on the path label"""
        txt = self.__getPathLabelFilePath()
        if txt.lower():
            QApplication.clipboard().setText(txt)

    def __getPathLabelFilePath(self):
        """Provides undecorated path label content"""
        txt = str(self.__fileLabel.getPath())
        if txt.startswith('File: '):
            return txt.replace('File: ', '')
        return txt

    def showPathLabelContextMenu(self, pos):
        """Triggered when a context menu is requested for the path label"""
        contextMenu = QMenu(self)
        contextMenu.addAction(getIcon('copymenu.png'),
                              'Copy full path to clipboard (double click)',
                              self.onPathLabelDoubleClick)
        contextMenu.addSeparator()
        contextMenu.addAction(getIcon(''), 'Copy directory path to clipboard',
                              self.onCopyDirToClipboard)
        contextMenu.addAction(getIcon(''), 'Copy file name to clipboard',
                              self.onCopyFileNameToClipboard)
        contextMenu.popup(self.__fileLabel.mapToGlobal(pos))

    def onCopyDirToClipboard(self):
        """Copies the dir path of the current file into the clipboard"""
        txt = self.__getPathLabelFilePath()
        if txt.lower():
            try:
                QApplication.clipboard().setText(os.path.dirname(txt) +
                                                 os.path.sep)
            except:
                pass

    def onCopyFileNameToClipboard(self):
        """Copies the file name of the current file into the clipboard"""
        txt = self.__getPathLabelFilePath()
        if txt.lower():
            try:
                QApplication.clipboard().setText(os.path.basename(txt))
            except:
                pass
Example #24
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__excptLabel = QLabel("Exceptions", self)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('excpt')
        self.headerFrame.setStyleSheet('QFrame#excpt {' +
                                       getLabelStyle(self.__excptLabel) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__excptLabel)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(True)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.__addToIgnoreButton = QAction(
            getIcon('add.png'), "Add exception to the list of ignored", self)
        self.__addToIgnoreButton.triggered.connect(self.__onAddToIgnore)
        self.__addToIgnoreButton.setEnabled(False)

        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)

        self.__jumpToCodeButton = QAction(
            getIcon('gotoline.png'), "Jump to the code", self)
        self.__jumpToCodeButton.triggered.connect(self.__onJumpToCode)
        self.__jumpToCodeButton.setEnabled(False)

        self.__delAllButton = QAction(
            getIcon('trash.png'), "Delete all the client exceptions", self)
        self.__delAllButton.triggered.connect(self.__onDelAll)
        self.__delAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__addToIgnoreButton)
        self.toolbar.addAction(self.__jumpToCodeButton)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__delAllButton)

        self.exceptionsList.itemDoubleClicked.connect(
            self.__onExceptionDoubleClicked)
        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)

        self.exceptionsList.setHeaderLabels(["Exception",
                                             "Function", "Arguments"])

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
class IOConsoleWidget(QWidget):

    """IO Console widget"""

    sigSettingsUpdated = pyqtSignal()
    sigUserInput = pyqtSignal(str, str)
    sigKillIOConsoleProcess = pyqtSignal(str)
    sigCloseIOConsole = pyqtSignal(int)

    def __init__(self, procuuid, kind, parent=None):
        QWidget.__init__(self, parent)
        self.procuuid = procuuid
        self.kind = kind    # RUN/DEBUG/PROFILE

        self.__viewer = RedirectedIOConsole(self)
        self.__viewer.sigUserInput.connect(self.__onUserInput)

        self.__createLayout()

    def setFocus(self):
        """Overridden setFocus"""
        self.__viewer.setFocus()

    def __onUserInput(self, userInput):
        """The user finished input in the redirected IO console"""
        self.sigUserInput.emit(self.procuuid, userInput)
        self.__clearButton.setEnabled(True)

    def __createLayout(self):
        """Creates the toolbar and layout"""
        self.__settingsMenu = QMenu(self)
        self.__settingsMenu.aboutToShow.connect(self.__settingsAboutToShow)
        self.__wrapLongLinesAct = self.__settingsMenu.addAction(
            "Wrap long lines")
        self.__wrapLongLinesAct.setCheckable(True)
        self.__wrapLongLinesAct.triggered.connect(self.__onWrapLongLines)
        self.__showWhitespacesAct = self.__settingsMenu.addAction(
            "Show whitespaces")
        self.__showWhitespacesAct.setCheckable(True)
        self.__showWhitespacesAct.triggered.connect(self.__onShowWhitespaces)
        self.__autoscrollAct = self.__settingsMenu.addAction("Autoscroll")
        self.__autoscrollAct.setCheckable(True)
        self.__autoscrollAct.triggered.connect(self.__onAutoscroll)

        self.__settingsButton = QToolButton(self)
        self.__settingsButton.setIcon(getIcon('iosettings.png'))
        self.__settingsButton.setToolTip('View settings')
        self.__settingsButton.setPopupMode(QToolButton.InstantPopup)
        self.__settingsButton.setMenu(self.__settingsMenu)
        self.__settingsButton.setFocusPolicy(Qt.NoFocus)

        if self.kind != DEBUG:
            fixedSpacer = QWidget()
            fixedSpacer.setFixedHeight(8)

            self.__stopButton = QAction(getIcon('runconsolestop.png'),
                                        'Stop process', self)
            self.__stopButton.triggered.connect(self.stop)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__clearButton = QAction(getIcon('trash.png'), 'Clear', self)
        self.__clearButton.triggered.connect(self.clear)

        # The toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addWidget(self.__settingsButton)

        if self.kind != DEBUG:
            toolbar.addWidget(fixedSpacer)
            toolbar.addAction(self.__stopButton)

        toolbar.addWidget(spacer)
        toolbar.addAction(self.__clearButton)

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(toolbar)
        hLayout.addWidget(self.__viewer)

        self.setLayout(hLayout)

    def __settingsAboutToShow(self):
        """Settings menu is about to show"""
        self.__wrapLongLinesAct.setChecked(Settings()['ioconsolelinewrap'])
        self.__showWhitespacesAct.setChecked(Settings()['ioconsoleshowspaces'])
        self.__autoscrollAct.setChecked(Settings()['ioconsoleautoscroll'])

    def __onWrapLongLines(self):
        """Triggered when long lines setting is changed"""
        Settings()['ioconsolelinewrap'] = not Settings()['ioconsolelinewrap']
        self.sigSettingsUpdated.emit()

    def __onShowWhitespaces(self):
        """Triggered when show whitespaces is changed"""
        Settings()['ioconsoleshowspaces'] = \
            not Settings()['ioconsoleshowspaces']
        self.sigSettingsUpdated.emit()

    @staticmethod
    def __onAutoscroll():
        """Triggered when autoscroll is changed"""
        Settings()['ioconsoleautoscroll'] = \
            not Settings()['ioconsoleautoscroll']

    def clear(self):
        """Triggered when requested to clear the console"""
        self.__viewer.clearAll()

    def consoleSettingsUpdated(self):
        """Triggered when one of the consoles updated a common setting"""
        self.__viewer.updateSettings()

    def resizeEvent(self, event):
        """Handles the widget resize"""
        QWidget.resizeEvent(self, event)

    def writeFile(self, fileName):
        """Writes the text to a file"""
        return self.__viewer.writeFile(fileName)

    def appendIDEMessage(self, text):
        """Appends an IDE message"""
        return self.__viewer.appendIDEMessage(text)

    def appendStdoutMessage(self, _, text):
        """Appends an stdout message"""
        return self.__viewer.appendStdoutMessage(text)

    def appendStderrMessage(self, _, text):
        """Appends an stderr message"""
        return self.__viewer.appendStderrMessage(text)

    def onTextZoomChanged(self):
        """Triggered when a text zoom is changed"""
        self.__viewer.onTextZoomChanged()

    def input(self, procuuid, prompt, echo):
        """Triggered when input is requested"""
        self.__viewer.inputEcho = echo
        if prompt:
            self.appendStdoutMessage(procuuid, prompt)
        self.__clearButton.setEnabled(False)
        self.__viewer.switchMode(self.__viewer.MODE_INPUT)

    def sessionStopped(self):
        """Triggered when redirecting session is stopped"""
        self.__viewer.switchMode(self.__viewer.MODE_OUTPUT)
        self.__clearButton.setEnabled(True)

    def stop(self):
        """Triggered when the user requesed to stop the process"""
        self.sigKillIOConsoleProcess.emit(self.procuuid)

    def scriptFinished(self):
        """Triggered when the script process finished"""
        if self.kind != DEBUG:
            self.__stopButton.setEnabled(False)
        self.__viewer.switchMode(self.__viewer.MODE_OUTPUT)
        self.__clearButton.setEnabled(True)

    def onReuse(self, procuuid):
        """Triggered when the console is reused"""
        self.procuuid = procuuid
        if self.kind != DEBUG:
            self.__stopButton.setEnabled(True)
Example #26
0
class TextEditorTabWidget(QWidget):
    """Plain text editor tab widget"""

    sigReloadRequest = pyqtSignal()
    reloadAllNonModifiedRequest = pyqtSignal()
    sigTabRunChanged = pyqtSignal(bool)

    def __init__(self, parent, debugger):
        QWidget.__init__(self, parent)

        extendInstance(self, MainWindowTabWidgetBase)
        MainWindowTabWidgetBase.__init__(self)

        self.__navigationBar = None
        self.__editor = TextEditor(self, debugger)
        self.__fileName = ""
        self.__shortName = ""

        self.__createLayout()

        self.__editor.redoAvailable.connect(self.__redoAvailable)
        self.__editor.undoAvailable.connect(self.__undoAvailable)
        self.__editor.modificationChanged.connect(self.modificationChanged)
        self.__editor.sigCFlowSyncRequested.connect(self.cflowSyncRequested)
        self.__editor.languageChanged.connect(self.__languageChanged)

        self.__diskModTime = None
        self.__diskSize = None
        self.__reloadDlgShown = False

        self.__debugMode = False

        self.__vcsStatus = None

    def onTextZoomChanged(self):
        """Triggered when a text zoom is changed"""
        self.__editor.onTextZoomChanged()

    def onFlowZoomChanged(self):
        """Triggered when a flow zoom is changed"""
        self.__flowUI.onFlowZoomChanged()

    def getNavigationBar(self):
        """Provides a reference to the navigation bar"""
        return self.__navigationBar

    def shouldAcceptFocus(self):
        """True if it can accept the focus"""
        return self.__outsideChangesBar.isHidden()

    def readFile(self, fileName):
        """Reads the text from a file"""
        self.__editor.readFile(fileName)
        self.setFileName(fileName)
        self.__editor.restoreBreakpoints()

        # Memorize the modification date
        path = os.path.realpath(fileName)
        self.__diskModTime = os.path.getmtime(path)
        self.__diskSize = os.path.getsize(path)

    def writeFile(self, fileName):
        """Writes the text to a file"""
        if self.__editor.writeFile(fileName):
            # Memorize the modification date
            path = os.path.realpath(fileName)
            self.__diskModTime = os.path.getmtime(path)
            self.__diskSize = os.path.getsize(path)
            self.setFileName(fileName)
            self.__editor.restoreBreakpoints()
            return True
        return False

    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        printButton = QAction(getIcon('printer.png'), 'Print (Ctrl+P)', self)
        printButton.triggered.connect(self.__onPrint)

        printPreviewButton = QAction(getIcon('printpreview.png'),
                                     'Print preview', self)
        printPreviewButton.triggered.connect(self.__onPrintPreview)
        printPreviewButton.setEnabled(False)
        printPreviewButton.setVisible(False)

        printSpacer = QWidget()
        printSpacer.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        printSpacer.setFixedHeight(8)

        # Imports diagram and its menu
        importsMenu = QMenu(self)
        importsDlgAct = importsMenu.addAction(getIcon('detailsdlg.png'),
                                              'Fine tuned imports diagram')
        importsDlgAct.triggered.connect(self.onImportDgmTuned)
        self.importsDiagramButton = QToolButton(self)
        self.importsDiagramButton.setIcon(getIcon('importsdiagram.png'))
        self.importsDiagramButton.setToolTip('Generate imports diagram')
        self.importsDiagramButton.setPopupMode(QToolButton.DelayedPopup)
        self.importsDiagramButton.setMenu(importsMenu)
        self.importsDiagramButton.setFocusPolicy(Qt.NoFocus)
        self.importsDiagramButton.clicked.connect(self.onImportDgm)
        self.importsDiagramButton.setEnabled(False)

        # Run script and its menu
        runScriptMenu = QMenu(self)
        runScriptDlgAct = runScriptMenu.addAction(getIcon('detailsdlg.png'),
                                                  'Set run/debug parameters')
        runScriptDlgAct.triggered.connect(self.onRunScriptDlg)
        self.runScriptButton = QToolButton(self)
        self.runScriptButton.setIcon(getIcon('run.png'))
        self.runScriptButton.setToolTip('Run script')
        self.runScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.runScriptButton.setMenu(runScriptMenu)
        self.runScriptButton.setFocusPolicy(Qt.NoFocus)
        self.runScriptButton.clicked.connect(self.onRunScript)
        self.runScriptButton.setEnabled(False)

        # Profile script and its menu
        profileScriptMenu = QMenu(self)
        profileScriptDlgAct = profileScriptMenu.addAction(
            getIcon('detailsdlg.png'), 'Set profile parameters')
        profileScriptDlgAct.triggered.connect(self.onProfileScriptDlg)
        self.profileScriptButton = QToolButton(self)
        self.profileScriptButton.setIcon(getIcon('profile.png'))
        self.profileScriptButton.setToolTip('Profile script')
        self.profileScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.profileScriptButton.setMenu(profileScriptMenu)
        self.profileScriptButton.setFocusPolicy(Qt.NoFocus)
        self.profileScriptButton.clicked.connect(self.onProfileScript)
        self.profileScriptButton.setEnabled(False)

        # Debug script and its menu
        debugScriptMenu = QMenu(self)
        debugScriptDlgAct = debugScriptMenu.addAction(
            getIcon('detailsdlg.png'), 'Set run/debug parameters')
        debugScriptDlgAct.triggered.connect(self.onDebugScriptDlg)
        self.debugScriptButton = QToolButton(self)
        self.debugScriptButton.setIcon(getIcon('debugger.png'))
        self.debugScriptButton.setToolTip('Debug script')
        self.debugScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.debugScriptButton.setMenu(debugScriptMenu)
        self.debugScriptButton.setFocusPolicy(Qt.NoFocus)
        self.debugScriptButton.clicked.connect(self.onDebugScript)
        self.debugScriptButton.setEnabled(False)

        # Disassembling
        disasmScriptMenu = QMenu(self)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (no optimization)',
                                   self.__editor._onDisasm0)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (optimization level 1)',
                                   self.__editor._onDisasm1)
        disasmScriptMenu.addAction(getIcon(''),
                                   'Disassembly (optimization level 2)',
                                   self.__editor._onDisasm2)
        self.disasmScriptButton = QToolButton(self)
        self.disasmScriptButton.setIcon(getIcon('disassembly.png'))
        self.disasmScriptButton.setToolTip('Disassembly script')
        self.disasmScriptButton.setPopupMode(QToolButton.DelayedPopup)
        self.disasmScriptButton.setMenu(disasmScriptMenu)
        self.disasmScriptButton.setFocusPolicy(Qt.NoFocus)
        self.disasmScriptButton.clicked.connect(self.__editor._onDisasm0)
        self.disasmScriptButton.setEnabled(False)

        # Dead code
        self.deadCodeScriptButton = QAction(getIcon('deadcode.png'),
                                            'Find dead code', self)
        self.deadCodeScriptButton.triggered.connect(self.__onDeadCode)
        self.deadCodeScriptButton.setEnabled(False)

        undoSpacer = QWidget()
        undoSpacer.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        undoSpacer.setFixedHeight(8)

        self.__undoButton = QAction(getIcon('undo.png'), 'Undo (Ctrl+Z)', self)
        self.__undoButton.setShortcut('Ctrl+Z')
        self.__undoButton.triggered.connect(self.__editor.onUndo)
        self.__undoButton.setEnabled(False)

        self.__redoButton = QAction(getIcon('redo.png'), 'Redo (Ctrl+Y)', self)
        self.__redoButton.setShortcut('Ctrl+Y')
        self.__redoButton.triggered.connect(self.__editor.onRedo)
        self.__redoButton.setEnabled(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.removeTrailingSpacesButton = QAction(getIcon('trailingws.png'),
                                                  'Remove trailing spaces',
                                                  self)
        self.removeTrailingSpacesButton.triggered.connect(
            self.onRemoveTrailingWS)
        self.expandTabsButton = QAction(getIcon('expandtabs.png'),
                                        'Expand tabs (4 spaces)', self)
        self.expandTabsButton.triggered.connect(self.onExpandTabs)

        # The toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(30)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(printPreviewButton)
        toolbar.addAction(printButton)
        toolbar.addWidget(printSpacer)
        toolbar.addWidget(self.importsDiagramButton)
        toolbar.addWidget(self.runScriptButton)
        toolbar.addWidget(self.profileScriptButton)
        toolbar.addWidget(self.debugScriptButton)
        toolbar.addWidget(self.disasmScriptButton)
        toolbar.addAction(self.deadCodeScriptButton)
        toolbar.addWidget(undoSpacer)
        toolbar.addAction(self.__undoButton)
        toolbar.addAction(self.__redoButton)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.removeTrailingSpacesButton)
        toolbar.addAction(self.expandTabsButton)

        self.importsBar = ImportListWidget(self.__editor)
        self.importsBar.hide()

        self.__outsideChangesBar = OutsideChangeWidget(self.__editor)
        self.__outsideChangesBar.sigReloadRequest.connect(self.__onReload)
        self.__outsideChangesBar.reloadAllNonModifiedRequest.connect(
            self.reloadAllNonModified)
        self.__outsideChangesBar.hide()

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)

        self.__navigationBar = NavigationBar(self.__editor, self)
        vLayout.addWidget(self.__navigationBar)
        vLayout.addWidget(self.__editor)

        hLayout.addLayout(vLayout)
        hLayout.addWidget(toolbar)
        widget = QWidget()
        widget.setLayout(hLayout)

        self.__splitter = QSplitter(Qt.Horizontal, self)

        self.__flowUI = FlowUIWidget(self.__editor, self)
        self.__mdView = MDWidget(self.__editor, self)

        self.__renderLayout = QVBoxLayout()
        self.__renderLayout.setContentsMargins(0, 0, 0, 0)
        self.__renderLayout.setSpacing(0)
        self.__renderLayout.addWidget(self.__flowUI)
        self.__renderLayout.addWidget(self.__mdView)
        self.__renderWidget = QWidget()
        self.__renderWidget.setLayout(self.__renderLayout)

        self.__splitter.addWidget(widget)
        self.__splitter.addWidget(self.__renderWidget)

        containerLayout = QHBoxLayout()
        containerLayout.setContentsMargins(0, 0, 0, 0)
        containerLayout.setSpacing(0)
        containerLayout.addWidget(self.__splitter)
        self.setLayout(containerLayout)

        self.__renderWidget.setVisible(False)

        self.__splitter.setSizes(Settings()['flowSplitterSizes'])
        self.__splitter.splitterMoved.connect(self.flowSplitterMoved)
        Settings().sigFlowSplitterChanged.connect(self.otherFlowSplitterMoved)

    def flowSplitterMoved(self, pos, index):
        """Splitter has been moved"""
        del pos  # unused argument
        del index  # unused argument
        Settings()['flowSplitterSizes'] = list(self.__splitter.sizes())

    def otherFlowSplitterMoved(self):
        """Other window has changed the splitter position"""
        self.__splitter.setSizes(Settings()['flowSplitterSizes'])

    def updateStatus(self):
        """Updates the toolbar buttons status"""
        self.__updateRunDebugButtons()
        isPythonFile = isPythonMime(self.__editor.mime)
        self.importsDiagramButton.setEnabled(
            isPythonFile and GlobalData().graphvizAvailable)
        self.__editor.diagramsMenu.setEnabled(
            self.importsDiagramButton.isEnabled())
        self.__editor.toolsMenu.setEnabled(self.runScriptButton.isEnabled())

    def onNavigationBar(self):
        """Triggered when navigation bar focus is requested"""
        if self.__navigationBar.isVisible():
            self.__navigationBar.setFocusToLastCombo()
        return True

    def __onPrint(self):
        """Triggered when the print button is pressed"""
        self.__editor._onShortcutPrint()

    def __onPrintPreview(self):
        """Triggered when the print preview button is pressed"""
        pass

    def __onDeadCode(self):
        """Triggered when vulture analysis is requested"""
        GlobalData().mainWindow.tabDeadCodeClicked()

    def __redoAvailable(self, available):
        """Reports redo ops available"""
        self.__redoButton.setEnabled(available)

    def __undoAvailable(self, available):
        """Reports undo ops available"""
        self.__undoButton.setEnabled(available)

    def __languageChanged(self, _=None):
        """Language changed"""
        isPython = self.__editor.isPythonBuffer()
        isMarkdown = self.__editor.isMarkdownBuffer()
        self.disasmScriptButton.setEnabled(isPython)
        self.__renderWidget.setVisible(not Settings()['floatingRenderer']
                                       and (isPython or isMarkdown))

    # Arguments: modified
    def modificationChanged(self, _=None):
        """Triggered when the content is changed"""
        self.__updateRunDebugButtons()

    def __updateRunDebugButtons(self):
        """Enables/disables the run and debug buttons as required"""
        enable = isPythonMime(self.__editor.mime) and \
                 not self.isModified() and \
                 not self.__debugMode and \
                 os.path.isabs(self.__fileName)

        if enable != self.runScriptButton.isEnabled():
            self.runScriptButton.setEnabled(enable)
            self.profileScriptButton.setEnabled(enable)
            self.debugScriptButton.setEnabled(enable)
            self.deadCodeScriptButton.setEnabled(enable)
            self.sigTabRunChanged.emit(enable)

    def isTabRunEnabled(self):
        """Tells the status of run-like buttons"""
        return self.runScriptButton.isEnabled()

    def replaceAll(self, newText):
        """Replaces the current buffer content with a new text"""
        # Unfortunately, the setText() clears the undo history so it cannot be
        # used. The selectAll() and replacing selected text do not suite
        # because after undo the cursor does not jump to the previous position.
        # So, there is an ugly select -> replace manipulation below...
        with self.__editor:
            origLine, origPos = self.__editor.cursorPosition
            self.__editor.setSelection(0, 0, origLine, origPos)
            self.__editor.removeSelectedText()
            self.__editor.insert(newText)
            self.__editor.setCurrentPosition(len(newText))
            line, pos = self.__editor.cursorPosition
            lastLine = self.__editor.lines()
            self.__editor.setSelection(line, pos, lastLine - 1,
                                       len(self.__editor.text(lastLine - 1)))
            self.__editor.removeSelectedText()
            self.__editor.cursorPosition = origLine, origPos

            # These two for the proper cursor positioning after redo
            self.__editor.insert("s")
            self.__editor.cursorPosition = origLine, origPos + 1
            self.__editor.deleteBack()
            self.__editor.cursorPosition = origLine, origPos

    def onRemoveTrailingWS(self):
        """Triggers when the trailing spaces should be wiped out"""
        self.__editor.removeTrailingWhitespaces()

    def onExpandTabs(self):
        """Expands tabs if there are any"""
        self.__editor.expandTabs(4)

    def setFocus(self):
        """Overridden setFocus"""
        if self.__outsideChangesBar.isHidden():
            self.__editor.setFocus()
        else:
            self.__outsideChangesBar.setFocus()

    def onImportDgmTuned(self):
        """Runs the settings dialog first"""
        if self.isModified():
            what = ImportsDiagramDialog.SingleBuffer
            if not os.path.isabs(self.getFileName()):
                logging.warning("Imports diagram can only be generated for "
                                "a file. Save the editor buffer "
                                "and try again.")
                return
        else:
            what = ImportsDiagramDialog.SingleFile
        dlg = ImportsDiagramDialog(what, self.getFileName(), self)
        if dlg.exec_() == QDialog.Accepted:
            # Should proceed with the diagram generation
            self.__generateImportDiagram(what, dlg.options)

    # Arguments: action
    def onImportDgm(self, _=None):
        """Runs the generation process with default options"""
        if self.isModified():
            what = ImportsDiagramDialog.SingleBuffer
            if not os.path.isabs(self.getFileName()):
                logging.warning("Imports diagram can only be generated for "
                                "a file. Save the editor buffer "
                                "and try again.")
                return
        else:
            what = ImportsDiagramDialog.SingleFile
        self.__generateImportDiagram(what, ImportDiagramOptions())

    def __generateImportDiagram(self, what, options):
        """Show the generation progress and display the diagram"""
        if self.isModified():
            progressDlg = ImportsDiagramProgress(what, options,
                                                 self.getFileName(),
                                                 self.__editor.text)
            tooltip = "Generated for modified buffer (" + \
                      self.getFileName() + ")"
        else:
            progressDlg = ImportsDiagramProgress(what, options,
                                                 self.getFileName())
            tooltip = "Generated for file " + self.getFileName()
        if progressDlg.exec_() == QDialog.Accepted:
            GlobalData().mainWindow.openDiagram(progressDlg.scene, tooltip)

    def onOpenImport(self):
        """Triggered when Ctrl+I is received"""
        if isPythonMime(self.__editor.mime):
            # Take all the file imports and resolve them
            fileImports = getImportsList(self.__editor.text)
            if not fileImports:
                GlobalData().mainWindow.showStatusBarMessage(
                    "There are no imports")
            else:
                self.__onImportList(self.__fileName, fileImports)

    def __onImportList(self, fileName, imports):
        """Works with a list of imports"""
        # It has already been checked that the file is a Python one
        resolvedList, errors = resolveImports(fileName, imports)
        del errors  # errors are OK here
        if resolvedList:
            # Display the import selection widget
            self.importsBar.showResolvedImports(resolvedList)
        else:
            GlobalData().mainWindow.showStatusBarMessage(
                "Could not resolve any imports")

    def resizeEvent(self, event):
        """Resizes the import selection dialogue if necessary"""
        self.__editor.hideCompleter()
        QWidget.resizeEvent(self, event)
        self.resizeBars()

    def resizeBars(self):
        """Resize the bars if they are shown"""
        if not self.importsBar.isHidden():
            self.importsBar.resize()
        if not self.__outsideChangesBar.isHidden():
            self.__outsideChangesBar.resize()
        self.__editor.resizeCalltip()

    def showOutsideChangesBar(self, allEnabled):
        """Shows the bar for the editor for the user to choose the action"""
        self.setReloadDialogShown(True)
        self.__outsideChangesBar.showChoice(self.isModified(), allEnabled)

    def __onReload(self):
        """Triggered when a request to reload the file is received"""
        self.sigReloadRequest.emit()

    def reload(self):
        """Called (from the editors manager) to reload the file"""
        # Re-read the file with updating the file timestamp
        self.readFile(self.__fileName)

        # Hide the bars, just in case both of them
        if not self.importsBar.isHidden():
            self.importsBar.hide()
        if not self.__outsideChangesBar.isHidden():
            self.__outsideChangesBar.hide()

        # Set the shown flag
        self.setReloadDialogShown(False)

    def reloadAllNonModified(self):
        """Request to reload all the non-modified files"""
        self.reloadAllNonModifiedRequest.emit()

    @staticmethod
    def onRunScript(action=None):
        """Runs the script"""
        del action  # unused argument
        GlobalData().mainWindow.onRunTab()

    @staticmethod
    def onRunScriptDlg():
        """Shows the run parameters dialogue"""
        GlobalData().mainWindow.onRunTabDlg()

    @staticmethod
    def onProfileScript(action=None):
        """Profiles the script"""
        del action  # unused argument
        GlobalData().mainWindow.onProfileTab()

    @staticmethod
    def onProfileScriptDlg():
        """Shows the profile parameters dialogue"""
        GlobalData().mainWindow.onProfileTabDlg()

    @staticmethod
    def onDebugScript(action=None):
        """Starts debugging"""
        del action  # unused argument
        GlobalData().mainWindow.onDebugTab()

    @staticmethod
    def onDebugScriptDlg():
        """Shows the debug parameters dialogue"""
        GlobalData().mainWindow.onDebugTabDlg()

    def getCFEditor(self):
        """Provides a reference to the control flow widget"""
        return self.__flowUI

    def cflowSyncRequested(self, absPos, line, pos):
        """Highlight the item closest to the absPos"""
        self.__flowUI.highlightAtAbsPos(absPos, line, pos)

    def passFocusToFlow(self):
        """Sets the focus to the graphics part"""
        if isPythonMime(self.__editor.mime):
            self.__flowUI.setFocus()
            return True
        return False

    def getMDView(self):
        """Provides a reference to the MD rendered view"""
        return self.__mdView

    # Mandatory interface part is below

    def getEditor(self):
        """Provides the editor widget"""
        return self.__editor

    def isModified(self):
        """Tells if the file is modified"""
        return self.__editor.document().isModified()

    def getRWMode(self):
        """Tells if the file is read only"""
        if not os.path.exists(self.__fileName):
            return None
        return 'RW' if QFileInfo(self.__fileName).isWritable() else 'RO'

    def getMime(self):
        """Provides the buffer mime"""
        return self.__editor.mime

    @staticmethod
    def getType():
        """Tells the widget type"""
        return MainWindowTabWidgetBase.PlainTextEditor

    def getLanguage(self):
        """Tells the content language"""
        editorLanguage = self.__editor.language()
        if editorLanguage:
            return editorLanguage
        return self.__editor.mime if self.__editor.mime else 'n/a'

    def getFileName(self):
        """Tells what file name of the widget content"""
        return self.__fileName

    def setFileName(self, name):
        """Sets the file name"""
        self.__fileName = name
        self.__shortName = os.path.basename(name)

    def getEol(self):
        """Tells the EOL style"""
        return self.__editor.getEolIndicator()

    def getLine(self):
        """Tells the cursor line"""
        line, _ = self.__editor.cursorPosition
        return line

    def getPos(self):
        """Tells the cursor column"""
        _, pos = self.__editor.cursorPosition
        return pos

    def getEncoding(self):
        """Tells the content encoding"""
        if self.__editor.explicitUserEncoding:
            return self.__editor.explicitUserEncoding
        return self.__editor.encoding

    def getShortName(self):
        """Tells the display name"""
        return self.__shortName

    def setShortName(self, name):
        """Sets the display name"""
        self.__shortName = name

    def isDiskFileModified(self):
        """Return True if the loaded file is modified"""
        if not os.path.isabs(self.__fileName):
            return False
        if not os.path.exists(self.__fileName):
            return True
        path = os.path.realpath(self.__fileName)
        return self.__diskModTime != os.path.getmtime(path) or \
               self.__diskSize != os.path.getsize(path)

    def doesFileExist(self):
        """Returns True if the loaded file still exists"""
        return os.path.exists(self.__fileName)

    def setReloadDialogShown(self, value=True):
        """Memorizes if the reloading dialogue has already been displayed"""
        self.__reloadDlgShown = value

    def getReloadDialogShown(self):
        """Tells if the reload dialog has already been shown"""
        return self.__reloadDlgShown and \
            not self.__outsideChangesBar.isVisible()

    def updateModificationTime(self, fileName):
        """Updates the modification time"""
        path = os.path.realpath(fileName)
        self.__diskModTime = os.path.getmtime(path)
        self.__diskSize = os.path.getsize(path)

    def setDebugMode(self, debugOn, disableEditing):
        """Called to switch debug/development"""
        self.__debugMode = debugOn
        self.__editor.setDebugMode(debugOn, disableEditing)

        if debugOn:
            if disableEditing:
                # Undo/redo
                self.__undoButton.setEnabled(False)
                self.__redoButton.setEnabled(False)

                # Spaces/tabs/line
                self.removeTrailingSpacesButton.setEnabled(False)
                self.expandTabsButton.setEnabled(False)
        else:
            # Undo/redo
            self.__undoButton.setEnabled(
                self.__editor.document().isUndoAvailable())
            self.__redoButton.setEnabled(
                self.__editor.document().isRedoAvailable())

            # Spaces/tabs
            self.removeTrailingSpacesButton.setEnabled(True)
            self.expandTabsButton.setEnabled(True)

        # Run/debug buttons
        self.__updateRunDebugButtons()

    def isLineBreakable(self,
                        line=None,
                        enforceRecalc=False,
                        enforceSure=False):
        """True if a breakpoint could be placed on the current line"""
        return self.__editor.isLineBreakable()

    def getVCSStatus(self):
        """Provides the VCS status"""
        return self.__vcsStatus

    def setVCSStatus(self, newStatus):
        """Sets the new VCS status"""
        self.__vcsStatus = newStatus

    # Floating renderer support
    def popRenderingWidgets(self):
        """Pops the rendering widgets"""
        self.__renderLayout.removeWidget(self.__flowUI)
        self.__renderLayout.removeWidget(self.__mdView)
        self.__renderWidget.setVisible(False)
        return [self.__flowUI, self.__mdView]

    def pushRenderingWidgets(self, widgets):
        """Returns back the rendering widgets"""
        for widget in widgets:
            self.__renderLayout.addWidget(widget)
        self.__languageChanged()  # Sets the widget visibility
Example #27
0
    def __createLayout(self, bpointsModel):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__breakpointLabel = HeaderFitLabel(self)
        self.__breakpointLabel.setText('Breakpoints')
        self.__breakpointLabel.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Fixed)
        self.__breakpointLabel.setMinimumWidth(10)

        self.headerToolbar = QToolBar(self)
        self.headerToolbar.setIconSize(QSize(18, 18))
        self.headerToolbar.setContentsMargins(1, 1, 1, 1)
        self.headerToolbar.addWidget(self.__breakpointLabel)

        self.bpointsList = BreakPointView(self, bpointsModel)

        self.__editButton = QAction(
            getIcon('bpprops.png'), "Edit breakpoint properties", self)
        self.__editButton.triggered.connect(self.__onEdit)
        self.__editButton.setEnabled(False)

        self.__jumpToCodeButton = QAction(
            getIcon('gotoline.png'), "Jump to the code", self)
        self.__jumpToCodeButton.triggered.connect(self.__onJumpToCode)
        self.__jumpToCodeButton.setEnabled(False)

        self.__enableButton = QAction(
            getIcon('bpenable.png'), "Enable selected breakpoint", self)
        self.__enableButton.triggered.connect(self.__onEnableDisable)
        self.__enableButton.setEnabled(False)

        self.__disableButton = QAction(
            getIcon('bpdisable.png'), "Disable selected breakpoint", self)
        self.__disableButton.triggered.connect(self.__onEnableDisable)
        self.__disableButton.setEnabled(False)

        self.__enableAllButton = QAction(
            getIcon('bpenableall.png'), "Enable all the breakpoint", self)
        self.__enableAllButton.triggered.connect(self.__onEnableAll)
        self.__enableAllButton.setEnabled(False)

        self.__disableAllButton = QAction(
            getIcon('bpdisableall.png'), "Disable all the breakpoint", self)
        self.__disableAllButton.triggered.connect(self.__onDisableAll)
        self.__disableAllButton.setEnabled(False)

        self.__delButton = QAction(
            getIcon('delitem.png'), "Delete selected breakpoint", self)
        self.__delButton.triggered.connect(self.__onDel)
        self.__delButton.setEnabled(False)

        self.__delAllButton = QAction(
            getIcon('bpdelall.png'), "Delete all the breakpoint", self)
        self.__delAllButton.triggered.connect(self.__onDelAll)
        self.__delAllButton.setEnabled(False)


        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__editButton)
        self.toolbar.addAction(self.__jumpToCodeButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addAction(self.__enableButton)
        self.toolbar.addAction(self.__enableAllButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addAction(self.__disableButton)
        self.toolbar.addAction(self.__disableAllButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addWidget(ToolBarExpandingSpacer(self.toolbar))
        self.toolbar.addAction(self.__delButton)
        self.toolbar.addWidget(ToolBarHSpacer(self.toolbar, 5))
        self.toolbar.addAction(self.__delAllButton)

        verticalLayout.addWidget(self.headerToolbar)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.bpointsList)
Example #28
0
    def __createLayout(self, bpointsModel):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.headerFrame = QFrame()
        self.headerFrame.setObjectName('bpheader')
        self.headerFrame.setStyleSheet('QFrame#bpheader {' +
                                       getLabelStyle(self) + '}')
        self.headerFrame.setFixedHeight(HEADER_HEIGHT)

        self.__breakpointLabel = QLabel("Breakpoints")

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__breakpointLabel)
        self.headerFrame.setLayout(headerLayout)

        self.bpointsList = BreakPointView(self, bpointsModel)

        self.__editButton = QAction(getIcon('bpprops.png'),
                                    "Edit breakpoint properties", self)
        self.__editButton.triggered.connect(self.__onEdit)
        self.__editButton.setEnabled(False)

        self.__jumpToCodeButton = QAction(getIcon('gotoline.png'),
                                          "Jump to the code", self)
        self.__jumpToCodeButton.triggered.connect(self.__onJumpToCode)
        self.__jumpToCodeButton.setEnabled(False)

        self.__enableButton = QAction(getIcon('bpenable.png'),
                                      "Enable selected breakpoint", self)
        self.__enableButton.triggered.connect(self.__onEnableDisable)
        self.__enableButton.setEnabled(False)

        self.__disableButton = QAction(getIcon('bpdisable.png'),
                                       "Disable selected breakpoint", self)
        self.__disableButton.triggered.connect(self.__onEnableDisable)
        self.__disableButton.setEnabled(False)

        self.__enableAllButton = QAction(getIcon('bpenableall.png'),
                                         "Enable all the breakpoint", self)
        self.__enableAllButton.triggered.connect(self.__onEnableAll)
        self.__enableAllButton.setEnabled(False)

        self.__disableAllButton = QAction(getIcon('bpdisableall.png'),
                                          "Disable all the breakpoint", self)
        self.__disableAllButton.triggered.connect(self.__onDisableAll)
        self.__disableAllButton.setEnabled(False)

        self.__delButton = QAction(getIcon('delitem.png'),
                                   "Delete selected breakpoint", self)
        self.__delButton.triggered.connect(self.__onDel)
        self.__delButton.setEnabled(False)

        self.__delAllButton = QAction(getIcon('bpdelall.png'),
                                      "Delete all the breakpoint", self)
        self.__delAllButton.triggered.connect(self.__onDelAll)
        self.__delAllButton.setEnabled(False)

        # Toolbar
        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addAction(self.__editButton)
        self.toolbar.addAction(self.__jumpToCodeButton)
        fixedSpacer2 = QWidget()
        fixedSpacer2.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer2)
        self.toolbar.addAction(self.__enableButton)
        self.toolbar.addAction(self.__enableAllButton)
        fixedSpacer3 = QWidget()
        fixedSpacer3.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer3)
        self.toolbar.addAction(self.__disableButton)
        self.toolbar.addAction(self.__disableAllButton)
        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        fixedSpacer4 = QWidget()
        fixedSpacer4.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer4)
        self.toolbar.addWidget(expandingSpacer)
        self.toolbar.addAction(self.__delButton)
        fixedSpacer5 = QWidget()
        fixedSpacer5.setFixedWidth(5)
        self.toolbar.addWidget(fixedSpacer5)
        self.toolbar.addAction(self.__delAllButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.bpointsList)
    def __createLayout(self):
        """Creates the toolbar and layout"""
        # Buttons
        printButton = QAction(getIcon('printer.png'), 'Print', self)
        printButton.triggered.connect(self.__onPrint)
        printButton.setEnabled(False)
        printButton.setVisible(False)

        printPreviewButton = QAction(getIcon('printpreview.png'),
                                     'Print preview', self)
        printPreviewButton.triggered.connect(self.__onPrintPreview)
        printPreviewButton.setEnabled(False)
        printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # The toolbar
        toolbar = QToolBar(self)
        toolbar.setOrientation(Qt.Vertical)
        toolbar.setMovable(False)
        toolbar.setAllowedAreas(Qt.RightToolBarArea)
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFixedWidth(28)
        toolbar.setContentsMargins(0, 0, 0, 0)

        toolbar.addAction(printPreviewButton)
        toolbar.addAction(printButton)
        toolbar.addWidget(spacer)

        self.__importsBar = ImportListWidget(self.__viewer)
        self.__importsBar.hide()

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.setSpacing(0)
        hLayout.addWidget(self.__viewer)
        hLayout.addWidget(toolbar)

        self.setLayout(hLayout)