예제 #1
0
    def showContextMenu(self, point):
        scipos = self.edit.SendScintilla(Qsci.QsciScintilla.SCI_POSITIONFROMPOINT, point.x(), point.y())
        point = self.edit.mapToGlobal(point)
        exp = self.getWordOrSelectionFromPosition(scipos)
        # self.edit.lineIndexFromPosition(..) returns tupel. first of tupel is line
        self.lastContexMenuLine = int(self.edit.lineIndexFromPosition(scipos)[0])

        self.expToWatch = exp

        listOfTracepoints = self.tracepointController.getTracepointsFromModel()

        self.subPopupMenu = QtGui.QMenu(self.edit)
        self.subPopupMenu.setTitle("Add variable " + exp + " to...")

        for tp in listOfTracepoints:
            # dynamic actions, not in actiony.py Action class
            self.action = ActionEx(self.expToWatch, self)
            QObject.connect(self.action, SIGNAL("triggered(PyQt_PyObject)"), tp.addVar)
            self.action.setText(str(tp.name))
            self.action.setIcon(QIcon(QPixmap(":/icons/images/insert.png")))
            self.action.setIconVisibleInMenu(True)
            self.subPopupMenu.addAction(self.action)

        self.popupMenu = QtGui.QMenu(self.edit)
        # add watch and toggle breakpoint to menu
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.AddWatch])
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.ToggleTrace])
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.AddVarToDataGraph])
        # add separator and self.subPopupMenu
        self.popupMenu.addSeparator()
        self.popupMenu.addMenu(self.subPopupMenu)
        self.popupMenu.popup(point)
예제 #2
0
class OpenedFileView(QObject):
    MARGIN_NUMBERS, MARGIN_MARKER_BP, MARGIN_MARKER_TP, MARGIN_MARKER_EXEC, MARGIN_MARKER_EXEC_SIGNAL, MARGIN_MARKER_STACK = range(6)

    def __init__(self, distributedObjects, filename):
        QObject.__init__(self)
        filename = str(filename)
        self.distributedObjects = distributedObjects
        self.debugController = self.distributedObjects.debugController
        self.breakpointController = self.distributedObjects.breakpointController
        self.tracepointController = self.distributedObjects.tracepointController
        self.signalProxy = self.distributedObjects.signalProxy
        self.filename = filename
        self.lastContexMenuLine = 0
        self.markerBp = QPixmap(":/markers/bp.png")
        self.markerTp = QPixmap(":/markers/tp.png")
        self.markerExec = QPixmap(":/markers/exec_pos.png")
        self.markerExecSignal = QPixmap(":/markers/exec_pos_signal.png")
        self.shown = False
        self.expToWatch = False

        self.tab = QtGui.QWidget()
        self.gridLayout = QtGui.QGridLayout(self.tab)
        self.gridLayout.setMargin(0)
        self.edit = Qsci.QsciScintilla(self.tab)
        self.font = QFont("DejaVu Sans Mono", 10)
        self.font.setStyleHint(QFont.TypeWriter)
        self.lexer = Qsci.QsciLexerCPP()
        self.lexer.setFont(self.font)
        self.edit.setToolTip("")
        self.edit.setWhatsThis("")
        self.edit.setTabWidth(4)
        self.edit.setLexer(self.lexer)
        self.edit.setWhitespaceVisibility(Qsci.QsciScintilla.WsVisible)
        self.edit.setIndentationGuides(True)
        self.edit.setMarginLineNumbers(self.MARGIN_NUMBERS, True)
        # set sensitivity
        self.edit.setMarginSensitivity(self.MARGIN_NUMBERS, True)
        self.edit.setMarginSensitivity(self.MARGIN_MARKER_BP, True)
        self.edit.setMarginSensitivity(self.MARGIN_MARKER_TP, True)
        # define symbol
        self.edit.markerDefine(self.markerBp, self.MARGIN_MARKER_BP)
        self.edit.markerDefine(self.markerTp, self.MARGIN_MARKER_TP)
        self.edit.markerDefine(self.markerExec, self.MARGIN_MARKER_EXEC)
        self.edit.markerDefine(self.markerExecSignal, self.MARGIN_MARKER_EXEC_SIGNAL)
        self.edit.markerDefine(Qsci.QsciScintilla.Background, self.MARGIN_MARKER_STACK)
        # define width and mask to show margin
        self.edit.setMarginWidth(self.MARGIN_MARKER_BP, 10)
        self.edit.setMarginMarkerMask(self.MARGIN_MARKER_BP, 1 << self.MARGIN_MARKER_BP)
        self.edit.setMarginWidth(self.MARGIN_MARKER_TP, 10)
        self.edit.setMarginMarkerMask(self.MARGIN_MARKER_TP, 1 << self.MARGIN_MARKER_TP)
        self.edit.setMarginWidth(self.MARGIN_MARKER_EXEC, 10)
        self.edit.setMarginMarkerMask(self.MARGIN_MARKER_EXEC, 1 << self.MARGIN_MARKER_EXEC | 1 << self.MARGIN_MARKER_EXEC_SIGNAL)
        self.edit.setMarginWidth(self.MARGIN_MARKER_STACK, 0)
        self.edit.setMarkerBackgroundColor(QColor(Qt.yellow), self.MARGIN_MARKER_STACK)
        self.edit.setMarginMarkerMask(self.MARGIN_MARKER_STACK, 1 << self.MARGIN_MARKER_STACK)
        # ...
        self.edit.setReadOnly(False)
        self.gridLayout.addWidget(self.edit, 0, 0, 1, 1)

        self.breakpoints = []

        if not (QtCore.QFile.exists(filename)):
            logging.error("could not open file", filename)
        self.file_ = QtCore.QFile(filename)
        self.file_.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text)
        self.edit.read(self.file_)
        self.file_.close()

        self.changed = False
        QObject.connect(self.edit, SIGNAL("modificationChanged(bool)"), self.__setFileModified)

        self.setMarginWidthByLineNumbers()
        self.edit.SendScintilla(Qsci.QsciScintilla.SCI_SETMOUSEDWELLTIME, 500)

        # override scintillas context menu with our own
        self.edit.SendScintilla(Qsci.QsciScintilla.SCI_USEPOPUP, 0)
        self.edit.setContextMenuPolicy(Qt.CustomContextMenu)
        QObject.connect(self.edit, SIGNAL('customContextMenuRequested(QPoint)'), self.showContextMenu)

        QObject.connect(self.edit, SIGNAL("marginClicked(int,int,Qt::KeyboardModifiers)"), self.marginClicked)
        QObject.connect(self.edit, SIGNAL("SCN_DOUBLECLICK(int, int, int)"), self.editDoubleClicked)
        QObject.connect(self.edit, SIGNAL("SCN_DWELLSTART(int, int, int)"), self.dwellStart)
        QObject.connect(self.edit, SIGNAL("SCN_DWELLEND(int, int, int)"), self.dwellEnd)

        # initially, read all breakpoints and tracepoints from the model
        self.getBreakpointsFromModel()
        self.getTracepointsFromModel()

        self.connect(self.breakpointController.model(), SIGNAL('rowsInserted(QModelIndex, int, int)'), self.getBreakpointsFromModel)
        self.connect(self.breakpointController.model(), SIGNAL('rowsRemoved(QModelIndex, int, int)'), self.getBreakpointsFromModel)
        self.connect(self.tracepointController.model(), SIGNAL('rowsInserted(QModelIndex, int, int)'), self.getTracepointsFromModel)
        self.connect(self.tracepointController.model(), SIGNAL('rowsRemoved(QModelIndex, int, int)'), self.getTracepointsFromModel)

        self.connect(self.distributedObjects.actions.actions[Actions.AddWatch], SIGNAL('triggered()'), self.addWatch)
        self.connect(self.distributedObjects.actions.actions[Actions.ToggleTrace], SIGNAL('triggered()'), self.toggleTracepoint)
        self.connect(self.distributedObjects.actions.actions[Actions.AddVarToDataGraph], SIGNAL('triggered()'), self.AddVarToDataGraph)

    def saveFile(self):
        ''' Save source file '''
        if (QtCore.QFile.exists(self.filename)):
            f = open(self.filename, 'w')
            f.write(self.edit.text())
            f.close()
            self.file_.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text)
            self.edit.read(self.file_)
            self.file_.close()
            self.__setFileModified(False)

            logging.warning("Source file %s modified. Recompile executable for correct debugging.", self.filename)

    def __setFileModified(self, modified):
        ''' Method called whenever current file is marked as modified '''
        self.distributedObjects.signalProxy.emitFileModified(self.filename, modified)

    def dwellStart(self, pos, x, y):
        if self.edit.frameGeometry().contains(x, y):
            name = self.getWordOrSelectionFromPosition(pos)
            val = self.debugController.evaluateExpression(name.strip())
            if val != None:
                name = cgi.escape(name)
                val = cgi.escape(val)
                QToolTip.showText(self.edit.mapToGlobal(QtCore.QPoint(x, y)), "<b>" + name + "</b> = " + val, self.edit, QtCore.QRect())

    def dwellEnd(self, position, x, y):
        QToolTip.showText(self.edit.mapToGlobal(QtCore.QPoint(x, y)), "", self.edit, QtCore.QRect())

    def showContextMenu(self, point):
        scipos = self.edit.SendScintilla(Qsci.QsciScintilla.SCI_POSITIONFROMPOINT, point.x(), point.y())
        point = self.edit.mapToGlobal(point)
        exp = self.getWordOrSelectionFromPosition(scipos)
        # self.edit.lineIndexFromPosition(..) returns tupel. first of tupel is line
        self.lastContexMenuLine = int(self.edit.lineIndexFromPosition(scipos)[0])

        self.expToWatch = exp

        listOfTracepoints = self.tracepointController.getTracepointsFromModel()

        self.subPopupMenu = QtGui.QMenu(self.edit)
        self.subPopupMenu.setTitle("Add variable " + exp + " to...")

        for tp in listOfTracepoints:
            # dynamic actions, not in actiony.py Action class
            self.action = ActionEx(self.expToWatch, self)
            QObject.connect(self.action, SIGNAL("triggered(PyQt_PyObject)"), tp.addVar)
            self.action.setText(str(tp.name))
            self.action.setIcon(QIcon(QPixmap(":/icons/images/insert.png")))
            self.action.setIconVisibleInMenu(True)
            self.subPopupMenu.addAction(self.action)

        self.popupMenu = QtGui.QMenu(self.edit)
        # add watch and toggle breakpoint to menu
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.AddWatch])
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.ToggleTrace])
        self.popupMenu.addAction(self.distributedObjects.actions.actions[Actions.AddVarToDataGraph])
        # add separator and self.subPopupMenu
        self.popupMenu.addSeparator()
        self.popupMenu.addMenu(self.subPopupMenu)
        self.popupMenu.popup(point)

    def addWatch(self, watch=None):
        if watch:
            self.signalProxy.addWatch(watch)
        elif self.expToWatch:
            self.signalProxy.addWatch(self.expToWatch)

    def AddVarToDataGraph(self, watch=None):
        if watch:
            self.distributedObjects.datagraphController.addWatch(watch)
        elif self.expToWatch:
            self.distributedObjects.datagraphController.addWatch(self.expToWatch)

    def addWatchFloating(self, watch=None):
        if watch:
            self.signalProxy.addVarFloating(watch)
        elif self.expToWatch:
            self.signalProxy.addVarFloating(self.expToWatch)

    def isPositionInsideSelection(self, position):
        lf, cf, lt, ct = self.edit.getSelection()
        pl, pc = self.edit.lineIndexFromPosition(position)

        if lf < pl and pl < lt:
            return True
        elif lf == pl and pl < lt:
            return True if cf <= pc else False
        elif lf < pl and pl == lt:
            return True if pc <= ct else False
        elif lf == pl and pl == lt:
            return True if (cf <= pc and pc <= ct) else False
        else:
            return False

    def getWordOrSelectionFromPosition(self, position):
        if self.isPositionInsideSelection(position):
            return str(self.edit.selectedText())
        else:
            return self.getWordFromPosition(position)

    def getWordFromPosition(self, position):
        line, col = self.edit.lineIndexFromPosition(position)
        s = str(self.edit.text(line))
        start = col
        end = col

        r = re.compile(r'[\w\d_]')
        while start >= 0:
            if not r.match(s[start]):
                break
            start -= 1
        start += 1
        while end < len(s):
            if not r.match(s[end]):
                break
            end += 1
        return s[start:end]

    def editDoubleClicked(self, position, line, modifiers):
        w = self.getWordFromPosition(position)
        self.addWatch(str(w))

    def showExecutionPosition(self, line):
        self.edit.markerAdd(line, self.MARGIN_MARKER_EXEC)
        self.showLine(line)

    def showSignalPosition(self, line):
        self.edit.markerAdd(line, self.MARGIN_MARKER_EXEC_SIGNAL)
        self.showLine(line)

    def showLine(self, line):
        self.edit.setCursorPosition(line, 1)
        self.edit.ensureLineVisible(line)

    def clearExecutionPositionMarkers(self):
        self.edit.markerDeleteAll(self.MARGIN_MARKER_EXEC)

    def setMarginWidthByLineNumbers(self):
        self.edit.setMarginWidth(0, ceil(log(self.edit.lines(), 10)) * 10 + 5)

    def marginClicked(self, margin, line, state):
        # if breakpoint should be toggled
        if margin == self.MARGIN_NUMBERS or margin == self.MARGIN_MARKER_BP:
            self.toggleBreakpointWithLine(line)
        elif margin == self.MARGIN_MARKER_TP:
            self.toggleTracepointWithLine(line)

    def toggleBreakpointWithLine(self, line):
        self.breakpointController.toggleBreakpoint(self.filename, line + 1)

    def toggleTracepointWithLine(self, line):
        self.tracepointController.toggleTracepoint(self.filename, line + 1)

    def toggleTracepoint(self):
        self.toggleTracepointWithLine(self.lastContexMenuLine)

    def getBreakpointsFromModel(self, parent=None, start=None, end=None):
        """Get breakpoints from model."""
        # TODO: don't reload all breakpoints, just the one referenced by parent/start/end
        self.edit.markerDeleteAll(self.MARGIN_MARKER_BP)
        for bp in self.breakpointController.getBreakpointsFromModel():
            if bp.fullname == self.filename:
                self.edit.markerAdd(int(bp.line) - 1, self.MARGIN_MARKER_BP)

    def getTracepointsFromModel(self):
        """Get tracepoints from model."""
        self.edit.markerDeleteAll(self.MARGIN_MARKER_TP)
        for tp in self.tracepointController.getTracepointsFromModel():
            if tp.fullname == self.filename:
                self.edit.markerAdd(int(tp.line) - 1, self.MARGIN_MARKER_TP)