示例#1
0
    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)
示例#2
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(450, 20)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)

        # Note label
        noteLabel = QLabel(
            "<b>Note</b>: the analysis is "
            "suggestive and not precise. "
            "Use the results with caution.\n", self)
        verticalLayout.addWidget(noteLabel)

        # Info label
        self.__infoLabel = QLabel(self)
        verticalLayout.addWidget(self.__infoLabel)

        # Found label
        self.__foundLabel = QLabel(self)
        verticalLayout.addWidget(self.__foundLabel)

        # Buttons
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Close)
        verticalLayout.addWidget(buttonBox)

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

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

        # Top level layout
        layout = QVBoxLayout(self)

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

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

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

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

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

        varValueValue.setFocus()
示例#4
0
class PathElement:

    """Single path element"""

    def __init__(self, parent=None):
        self.icon = QLabel()
        self.icon.setPixmap(getPixmap('nbsep.png'))
        self.combo = NavBarComboBox(parent)
示例#5
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

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

        self.__stackLabel = QLabel("Stack")

        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 frames 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.__stackLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.__framesList = QTreeWidget(self)
        self.__framesList.setSortingEnabled(False)
        # I might not need that because of two reasons:
        # - the window has no focus
        # - the window has custom current indicator
        # self.__framesList.setAlternatingRowColors(True)
        self.__framesList.setRootIsDecorated(False)
        self.__framesList.setItemsExpandable(False)
        self.__framesList.setUniformRowHeights(True)
        self.__framesList.setSelectionMode(QAbstractItemView.NoSelection)
        self.__framesList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.__framesList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__framesList.setFocusPolicy(Qt.NoFocus)
        self.__framesList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.__framesList.itemClicked.connect(self.__onFrameClicked)
        self.__framesList.itemDoubleClicked.connect(
            self.__onFrameDoubleClicked)
        self.__framesList.customContextMenuRequested.connect(
            self.__showContextMenu)

        self.__framesList.setHeaderLabels(
            ["", "File:line", "Function", "Arguments", "Full path"])

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.__framesList)
示例#6
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)

        self.__titleLabel = QLabel()
        self.__titleLabel.setAutoFillBackground(True)
        self.__titleLabel.setFrameShape(QFrame.StyledPanel)
        self.__titleLabel.setStyleSheet('padding: 2px')
        verticalLayout.addWidget(self.__titleLabel)
示例#7
0
    def __createLayout(self):
        """Creates the tooltip layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)

        self.info = QLabel()
        self.info.setAutoFillBackground(True)
        self.info.setFont(getZoomedMonoFont())
        self.info.setFrameShape(QFrame.StyledPanel)
        self.info.setStyleSheet('padding: 4px')
        verticalLayout.addWidget(self.info)

        self.location = QLabel()
示例#8
0
    def __createLayout(self):
        """Creates the widget layout"""
        totalCalls = self.__stats.total_calls
        # The calls were not induced via recursion
        totalPrimitiveCalls = self.__stats.prim_calls
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + \
              self.__params['arguments'] + "<br/>" \
              "<b>Run at:</b> " + self.__reportTime + "<br/>" + \
              str(totalCalls) + " function calls (" + \
              str(totalPrimitiveCalls) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel(txt)
        summary.setToolTip(txt)
        summary.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        summary.setStyleSheet('QLabel {' + getLabelStyle(self) + '}')

        self.__scene = QGraphicsScene()
        self.__viewer = DiagramWidget()
        self.__viewer.sigEscapePressed.connect(self.__onESC)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)
        vLayout.addWidget(summary)
        vLayout.addWidget(self.__viewer)

        self.setLayout(vLayout)
示例#9
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(450, 20)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)
        self.__infoLabel = QLabel("Retrieving log of '" + self.__path + "'...")
        verticalLayout.addWidget(self.__infoLabel)

        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Close)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)
示例#10
0
    def __createLayout(self, paths, ignoredPaths):
        """Creates the dialog layout"""
        self.resize(640, 420)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Paths to commit part
        vboxLayout.addWidget(QLabel("Paths (total: " +
                             str(len(paths)) + ")"))

        self.__pathView = QTreeWidget()
        self.__pathView.setAlternatingRowColors(True)
        self.__pathView.setRootIsDecorated(False)
        self.__pathView.setItemsExpandable(False)
        self.__pathView.setSortingEnabled(True)
        self.__pathView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__pathView.setUniformRowHeights(True)

        self.__pathHeader = QTreeWidgetItem(["", "Path", "Status", "Message"])
        self.__pathView.setHeaderItem(self.__pathHeader)
        self.__pathView.header().setSortIndicator(1, Qt.AscendingOrder)
        vboxLayout.addWidget(self.__pathView)

        # Paths to ignore part
        vboxLayout.addWidget(QLabel("Ignored paths (total: " +
                             str(len(ignoredPaths)) + ")"))

        self.__ignoredPathView = QTreeWidget()
        self.__ignoredPathView.setAlternatingRowColors(True)
        self.__ignoredPathView.setRootIsDecorated(False)
        self.__ignoredPathView.setItemsExpandable(False)
        self.__ignoredPathView.setSortingEnabled(True)
        self.__ignoredPathView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__ignoredPathView.setUniformRowHeights(True)

        pathToIgnoreHeader = QTreeWidgetItem(["Path", "Status"])
        self.__ignoredPathView.setHeaderItem(pathToIgnoreHeader)
        self.__ignoredPathView.header().setSortIndicator(0, Qt.AscendingOrder)
        vboxLayout.addWidget(self.__ignoredPathView)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
        buttonBox.accepted.connect(self.accept)
        vboxLayout.addWidget(buttonBox)
示例#11
0
    def __createLayout(self, pathsToAdd):
        """Creates the dialog layout"""

        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        # Paths to add part
        vboxLayout.addWidget(
            QLabel("Paths to add (total: " + str(len(pathsToAdd)) + ")"))

        self.__pathToAddView = QTreeWidget()
        self.__configTable(self.__pathToAddView)

        self.__pathToAddHeader = QTreeWidgetItem(["", "Path"])
        self.__pathToAddView.setHeaderItem(self.__pathToAddHeader)
        self.__pathToAddView.header().setSortIndicator(PATH_COL,
                                                       Qt.AscendingOrder)
        self.__pathToAddView.itemChanged.connect(self.__onAddPathChanged)
        vboxLayout.addWidget(self.__pathToAddView)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.__OKButton = buttonBox.button(QDialogButtonBox.Ok)
        self.__OKButton.setText("Add")
        buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
        buttonBox.accepted.connect(self.userAccept)
        buttonBox.rejected.connect(self.close)
        vboxLayout.addWidget(buttonBox)
    def __createLayout(self, labelText):
        """Creates the dialog layout"""
        self.resize(600, 250)
        self.setSizeGripEnabled(True)

        # Top level layout
        layout = QVBoxLayout(self)

        layout.addWidget(QLabel(labelText))
        self.__newCaption = QTextEdit()
        self.__newCaption.setFont(getZoomedMonoFont())
        self.__newCaption.setAcceptRichText(False)
        layout.addWidget(self.__newCaption)

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

        self.__newCaption.setFocus()
示例#13
0
 def draw(self, label):
     """Draws the indicator as members tell. label is QLabel"""
     label.setPalette(QLabel().palette())
     if self.isPixmap():
         label.setAutoFillBackground(False)
         label.setFrameStyle(QLabel().frameStyle())
         label.setPixmap(self.pixmap)
     else:
         label.setFrameStyle(QFrame.StyledPanel)
         label.setAutoFillBackground(True)
         palette = label.palette()
         if self.backgroundColor is not None:
             palette.setColor(QPalette.Background, self.backgroundColor)
         if self.foregroundColor is not None:
             palette.setColor(QPalette.Foreground, self.foregroundColor)
         label.setPalette(palette)
         label.setText(self.text)
示例#14
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.setMinimumWidth(300)
        self.setMinimumHeight(250)
        self.resize(400, 300)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(5, 5, 5, 5)
        gridLayout = QGridLayout()

        bgLabel = QLabel('Select background color:', self)
        gridLayout.addWidget(bgLabel, 0, 0, 1, 1)
        self.__bgColorButton = ColorButton('', self)
        gridLayout.addWidget(self.__bgColorButton, 0, 1, 1, 1)

        fgLabel = QLabel('Select foreground color:', self)
        gridLayout.addWidget(fgLabel, 1, 0, 1, 1)
        self.__fgColorButton = ColorButton('', self)
        gridLayout.addWidget(self.__fgColorButton, 1, 1, 1, 1)

        borderLabel = QLabel('Select border color (*):', self)
        gridLayout.addWidget(borderLabel, 2, 0, 1, 1)
        self.__borderColorButton = ColorButton('', self)
        gridLayout.addWidget(self.__borderColorButton, 2, 1, 1, 1)

        verticalLayout.addLayout(gridLayout)
        verticalLayout.addWidget(
            QLabel('(*): docstrings use it only when shown as badges'))

        # Sample area
        self.__scene = QGraphicsScene()
        self.__view = QGraphicsView()
        self.__view.setScene(self.__scene)
        verticalLayout.addWidget(self.__view)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                     | QDialogButtonBox.Ok)
        verticalLayout.addWidget(buttonBox)

        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
示例#15
0
    def __createLayout(self):
        """Creates the layout"""
        self.__layout = QHBoxLayout(self)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        # Create info icon
        self.__infoIcon = QLabel(self)
        self.__infoIcon.setPixmap(getPixmap('cfunknown.png'))
        self.__layout.addWidget(self.__infoIcon)

        self.__warningsIcon = QLabel(self)
        self.__warningsIcon.setPixmap(getPixmap('cfwarning.png'))
        self.__layout.addWidget(self.__warningsIcon)

        self.clearWarnings()

        # Create the path label
        self.__pathLabel = HeaderFitLabel(self)
        self.__pathLabel.setTextFormat(Qt.PlainText)
        self.__pathLabel.setAlignment(Qt.AlignLeft)
        self.__pathLabel.setWordWrap(False)
        self.__pathLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__pathLabel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.__pathLabel.setMinimumWidth(40)
        self.__layout.addWidget(self.__pathLabel)

        self.__spacer = ToolBarExpandingSpacer(self)
        self.__spacer.setMinimumWidth(0)
        self.__layout.addWidget(self.__spacer)

        # Create the selection label
        self.__selectionLabel = HeaderLabel('', None, self)
        self.__selectionLabel.setTextFormat(Qt.PlainText)
        self.__selectionLabel.setAlignment(Qt.AlignCenter)
        self.__selectionLabel.setWordWrap(False)
        self.__selectionLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__selectionLabel.setSizePolicy(QSizePolicy.Fixed,
                                            QSizePolicy.Fixed)
        self.__selectionLabel.setMinimumWidth(40)
        self.__layout.addWidget(self.__selectionLabel)
        self.setSelectionLabel(0, None)
示例#16
0
    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)
示例#17
0
    def __createLayout(self):
        """Creates the layout"""
        self.setFixedHeight(24)
        self.__layout = QHBoxLayout(self)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        # Set the background color

        # Create info icon
        self.__infoIcon = QLabel()
        self.__layout.addWidget(self.__infoIcon)

        self.__globalScopeCombo = NavBarComboBox(self)
        self.__globalScopeCombo.jumpToLine.connect(self.__onJumpToLine)
        self.__layout.addWidget(self.__globalScopeCombo)

        self.__spacer = QWidget()
        self.__spacer.setSizePolicy(QSizePolicy.Expanding,
                                    QSizePolicy.Expanding)
        self.__layout.addWidget(self.__spacer)
示例#18
0
    def __createLayout(self):
        """Creates the layout"""
        self.setFixedHeight(24)
        self.__layout = QHBoxLayout(self)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        # Create info icon
        self.__infoIcon = QLabel()
        self.__infoIcon.setPixmap(getPixmap('cfunknown.png'))
        self.__layout.addWidget(self.__infoIcon)

        self.__warningsIcon = QLabel()
        self.__warningsIcon.setPixmap(getPixmap('cfwarning.png'))
        self.__layout.addWidget(self.__warningsIcon)

        self.clearWarnings()

        self.__spacer = QWidget()
        self.__spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.__spacer.setMinimumWidth(0)
        self.__layout.addWidget(self.__spacer)
示例#19
0
def getLabelStyle(owner):
    """Creates a label stylesheet for the given owner widget"""
    modelLabel = QLabel(owner)
    bgColor = modelLabel.palette().color(modelLabel.backgroundRole())
    del modelLabel

    red = bgColor.red()
    green = bgColor.green()
    blue = bgColor.blue()
    delta = 60

    borderColor = QColor(max(red - delta, 0), max(green - delta, 0),
                         max(blue - delta, 0))
    bgColor = QColor(min(red + delta, 255), min(green + delta, 255),
                     min(blue + delta, 255))

    props = [
        'border-radius: 3px', 'padding: 4px',
        'background-color: ' + colorAsString(bgColor, True),
        'border: 1px solid ' + colorAsString(borderColor, True)
    ]
    return '; '.join(props)
示例#20
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(450, 150)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)
        gridLayout = QGridLayout()

        # Link
        gridLayout.addWidget(QLabel('Link', self), 0, 0, 1, 1)
        self.linkEdit = QLineEdit(self)
        self.linkEdit.setClearButtonEnabled(True)
        self.linkEdit.setToolTip(
            'A link to a file or to an external web resource')
        gridLayout.addWidget(self.linkEdit, 0, 1, 1, 1)
        self.linkEdit.textChanged.connect(self.__validate)
        self.fileButton = QPushButton(self)
        self.fileButton.setText('...')
        self.fileButton.setToolTip('Select an existing or non existing file')
        gridLayout.addWidget(self.fileButton, 0, 2, 1, 1)
        self.fileButton.clicked.connect(self.__onSelectPath)
        self.createCheckBox = QCheckBox(
            'Create a markdown file if does not exist', self)
        self.createCheckBox.setChecked(False)
        gridLayout.addWidget(self.createCheckBox, 1, 1, 1, 1)
        self.createCheckBox.stateChanged.connect(self.__validate)

        # Anchor
        gridLayout.addWidget(QLabel('Anchor', self), 2, 0, 1, 1)
        self.anchorEdit = QLineEdit(self)
        self.anchorEdit.setClearButtonEnabled(True)
        gridLayout.addWidget(self.anchorEdit, 2, 1, 1, 1)
        self.anchorEdit.textChanged.connect(self.__validate)

        # Title
        titleLabel = QLabel('Title', self)
        titleLabel.setAlignment(Qt.AlignTop)
        gridLayout.addWidget(titleLabel, 3, 0, 1, 1)
        self.titleEdit = QTextEdit()
        self.titleEdit.setTabChangesFocus(True)
        self.titleEdit.setAcceptRichText(False)
        self.titleEdit.setFont(getZoomedMonoFont())
        self.titleEdit.setToolTip(
            'If provided then will be displayed in the rectangle')
        gridLayout.addWidget(self.titleEdit, 3, 1, 1, 1)

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

        verticalLayout.addLayout(gridLayout)
        verticalLayout.addWidget(buttonBox)

        self.linkEdit.setFocus()
示例#21
0
    def __createLayout(self):
        """Creates the layout"""
        self.setFixedHeight(24)
        self.__layout = QHBoxLayout(self)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        # Create info icon
        self.__infoIcon = QLabel(self)
        self.__infoIcon.setPixmap(getPixmap('cfunknown.png'))
        self.__layout.addWidget(self.__infoIcon)

        self.__warningsIcon = QLabel(self)
        self.__warningsIcon.setPixmap(getPixmap('cfwarning.png'))
        self.__layout.addWidget(self.__warningsIcon)

        self.clearWarnings()

        labelStylesheet = 'QLabel {' + getLabelStyle(self.__infoIcon) + '}'

        # Create the path label
        self.__pathLabel = QLabel(self)
        self.__pathLabel.setStyleSheet(labelStylesheet)
        self.__pathLabel.setTextFormat(Qt.PlainText)
        self.__pathLabel.setAlignment(Qt.AlignLeft)
        self.__pathLabel.setWordWrap(False)
        self.__pathLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__pathLabel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.__layout.addWidget(self.__pathLabel)

        self.__spacer = QWidget()
        self.__spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.__spacer.setMinimumWidth(0)
        self.__layout.addWidget(self.__spacer)

        # Create the selection label
        self.__selectionLabel = QLabel(self)
        self.__selectionLabel.setStyleSheet(labelStylesheet)
        self.__selectionLabel.setTextFormat(Qt.PlainText)
        self.__selectionLabel.setAlignment(Qt.AlignCenter)
        self.__selectionLabel.setWordWrap(False)
        self.__selectionLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__selectionLabel.setSizePolicy(QSizePolicy.Fixed,
                                            QSizePolicy.Fixed)
        self.__selectionLabel.setMinimumWidth(40)
        self.__layout.addWidget(self.__selectionLabel)
        self.setSelectionLabel(0, None)
示例#22
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(450, 20)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)

        # Info label
        self.infoLabel = QLabel(self)
        verticalLayout.addWidget(self.infoLabel)

        # Progress bar
        self.progressBar = QProgressBar(self)
        self.progressBar.setValue(0)
        self.progressBar.setOrientation(Qt.Horizontal)
        verticalLayout.addWidget(self.progressBar)

        # Buttons
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Close)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)
示例#23
0
    def __createLayout(self, bpoint):
        """Creates the dialog layout"""
        self.resize(400, 150)
        self.setSizeGripEnabled(True)

        # Top level layout
        layout = QVBoxLayout(self)

        gridLayout = QGridLayout()
        fileLabel = QLabel("File name:")
        gridLayout.addWidget(fileLabel, 0, 0)
        fileValue = QLabel(bpoint.getAbsoluteFileName())
        gridLayout.addWidget(fileValue, 0, 1)
        lineLabel = QLabel("Line:")
        gridLayout.addWidget(lineLabel, 1, 0)
        lineValue = QLabel(str(bpoint.getLineNumber()))
        gridLayout.addWidget(lineValue, 1, 1)
        conditionLabel = QLabel("Condition:")
        gridLayout.addWidget(conditionLabel, 2, 0)
        self.__conditionValue = CDMComboBox(True)
        self.__conditionValue.lineEdit().setText(bpoint.getCondition())
        gridLayout.addWidget(self.__conditionValue, 2, 1)
        ignoreLabel = QLabel("Ignore count:")
        gridLayout.addWidget(ignoreLabel, 3, 0)
        self.__ignoreValue = QSpinBox()
        self.__ignoreValue.setMinimum(0)
        self.__ignoreValue.setValue(bpoint.getIgnoreCount())
        gridLayout.addWidget(self.__ignoreValue, 3, 1)
        layout.addLayout(gridLayout)

        # Checkboxes part
        self.__tempCheckbox = QCheckBox("&Temporary")
        self.__tempCheckbox.setChecked(bpoint.isTemporary())
        layout.addWidget(self.__tempCheckbox)
        self.__enabled = QCheckBox("&Enabled")
        self.__enabled.setChecked(bpoint.isEnabled())
        layout.addWidget(self.__enabled)

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

        self.__conditionValue.setFocus()
示例#24
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(400, 80)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        hboxLayout = QHBoxLayout()
        hboxLayout.addWidget(QLabel("Status update interval, sec."))
        self.__intervalEdit = QLineEdit()
        self.__intervalEdit.setValidator(QIntValidator(1, 3600, self))
        self.__intervalEdit.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        hboxLayout.addWidget(self.__intervalEdit)

        # Buttons at the bottom
        self.__buttonBox = QDialogButtonBox(self)
        self.__buttonBox.setOrientation(Qt.Horizontal)
        self.__buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                            | QDialogButtonBox.Cancel)
        self.__buttonBox.accepted.connect(self.userAccept)
        self.__buttonBox.rejected.connect(self.close)

        vboxLayout.addLayout(hboxLayout)
        vboxLayout.addWidget(self.__buttonBox)
示例#25
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)
示例#26
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()
示例#27
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)

        # Buttons
        saveAsMenu = QMenu(self)
        saveAsSVGAct = saveAsMenu.addAction(getIcon('filesvg.png'),
                                            'Save as SVG...')
        saveAsSVGAct.triggered.connect(self.onSaveAsSVG)

        saveAsPDFAct = saveAsMenu.addAction(getIcon('filepdf.png'),
                                            'Save as PDF...')
        saveAsPDFAct.triggered.connect(self.onSaveAsPDF)
        saveAsPNGAct = saveAsMenu.addAction(getIcon('filepixmap.png'),
                                            'Save as PNG...')
        saveAsPNGAct.triggered.connect(self.onSaveAsPNG)
        saveAsMenu.addSeparator()
        saveAsCopyToClipboardAct = saveAsMenu.addAction(
            getIcon('copymenu.png'), 'Copy to clipboard')
        saveAsCopyToClipboardAct.triggered.connect(self.copyToClipboard)

        self.__saveAsButton = QToolButton(self)
        self.__saveAsButton.setIcon(getIcon('saveasmenu.png'))
        self.__saveAsButton.setToolTip('Save as')
        self.__saveAsButton.setPopupMode(QToolButton.InstantPopup)
        self.__saveAsButton.setMenu(saveAsMenu)
        self.__saveAsButton.setFocusPolicy(Qt.NoFocus)

        self.__levelUpButton = QToolButton(self)
        self.__levelUpButton.setFocusPolicy(Qt.NoFocus)
        self.__levelUpButton.setIcon(getIcon('levelup.png'))
        self.__levelUpButton.setToolTip('Smart zoom level up (Shift+wheel)')
        self.__levelUpButton.clicked.connect(self.onSmartZoomLevelUp)
        self.__levelIndicator = QLabel('<b>0</b>', self)
        self.__levelIndicator.setAlignment(Qt.AlignCenter)
        self.__levelDownButton = QToolButton(self)
        self.__levelDownButton.setFocusPolicy(Qt.NoFocus)
        self.__levelDownButton.setIcon(getIcon('leveldown.png'))
        self.__levelDownButton.setToolTip('Smart zoom level down (Shift+wheel)')
        self.__levelDownButton.clicked.connect(self.onSmartZoomLevelDown)

        fixedSpacer = QWidget()
        fixedSpacer.setFixedHeight(10)

        self.__hideDocstrings = QToolButton(self)
        self.__hideDocstrings.setCheckable(True)
        self.__hideDocstrings.setIcon(getIcon('hidedocstrings.png'))
        self.__hideDocstrings.setToolTip('Show/hide docstrings')
        self.__hideDocstrings.setFocusPolicy(Qt.NoFocus)
        self.__hideDocstrings.setChecked(Settings()['hidedocstrings'])
        self.__hideDocstrings.clicked.connect(self.__onHideDocstrings)
        self.__hideComments = QToolButton(self)
        self.__hideComments.setCheckable(True)
        self.__hideComments.setIcon(getIcon('hidecomments.png'))
        self.__hideComments.setToolTip('Show/hide comments')
        self.__hideComments.setFocusPolicy(Qt.NoFocus)
        self.__hideComments.setChecked(Settings()['hidecomments'])
        self.__hideComments.clicked.connect(self.__onHideComments)
        self.__hideExcepts = QToolButton(self)
        self.__hideExcepts.setCheckable(True)
        self.__hideExcepts.setIcon(getIcon('hideexcepts.png'))
        self.__hideExcepts.setToolTip('Show/hide except blocks')
        self.__hideExcepts.setFocusPolicy(Qt.NoFocus)
        self.__hideExcepts.setChecked(Settings()['hideexcepts'])
        self.__hideExcepts.clicked.connect(self.__onHideExcepts)

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

        self.__toolbar.addWidget(self.__saveAsButton)
        self.__toolbar.addWidget(spacer)
        self.__toolbar.addWidget(self.__levelUpButton)
        self.__toolbar.addWidget(self.__levelIndicator)
        self.__toolbar.addWidget(self.__levelDownButton)
        self.__toolbar.addWidget(fixedSpacer)
        self.__toolbar.addWidget(self.__hideDocstrings)
        self.__toolbar.addWidget(self.__hideComments)
        self.__toolbar.addWidget(self.__hideExcepts)
        return self.__toolbar
示例#28
0
class FlowUIWidget(QWidget):

    """The widget which goes along with the text editor"""

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

        # It is always not visible at the beginning because there is no
        # editor content at the start
        self.setVisible(False)

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

        self.cflowSettings = getCflowSettings(self)
        self.__displayProps = (self.cflowSettings.hidedocstrings,
                               self.cflowSettings.hidecomments,
                               self.cflowSettings.hideexcepts,
                               Settings()['smartZoom'])

        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.__navBar = None
        self.__cf = None
        self.__canvas = None
        self.__validGroups = []
        self.__allGroupId = set()

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

        vLayout.addWidget(self.__createNavigationBar())
        vLayout.addWidget(self.__createStackedViews())

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

        self.updateSettings()

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

        Settings().sigHideDocstringsChanged.connect(
            self.__onHideDocstringsChanged)
        Settings().sigHideCommentsChanged.connect(self.__onHideCommentsChanged)
        Settings().sigHideExceptsChanged.connect(self.__onHideExceptsChanged)
        Settings().sigSmartZoomChanged.connect(self.__onSmartZoomChanged)

        self.setSmartZoomLevel(Settings()['smartZoom'])

    def getParentWidget(self):
        return self.__parentWidget

    def view(self):
        """Provides a reference to the current view"""
        return self.smartViews.currentWidget()

    def scene(self):
        """Provides a reference to the current scene"""
        return self.view().scene

    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)

        # Buttons
        saveAsMenu = QMenu(self)
        saveAsSVGAct = saveAsMenu.addAction(getIcon('filesvg.png'),
                                            'Save as SVG...')
        saveAsSVGAct.triggered.connect(self.onSaveAsSVG)

        saveAsPDFAct = saveAsMenu.addAction(getIcon('filepdf.png'),
                                            'Save as PDF...')
        saveAsPDFAct.triggered.connect(self.onSaveAsPDF)
        saveAsPNGAct = saveAsMenu.addAction(getIcon('filepixmap.png'),
                                            'Save as PNG...')
        saveAsPNGAct.triggered.connect(self.onSaveAsPNG)
        saveAsMenu.addSeparator()
        saveAsCopyToClipboardAct = saveAsMenu.addAction(
            getIcon('copymenu.png'), 'Copy to clipboard')
        saveAsCopyToClipboardAct.triggered.connect(self.copyToClipboard)

        self.__saveAsButton = QToolButton(self)
        self.__saveAsButton.setIcon(getIcon('saveasmenu.png'))
        self.__saveAsButton.setToolTip('Save as')
        self.__saveAsButton.setPopupMode(QToolButton.InstantPopup)
        self.__saveAsButton.setMenu(saveAsMenu)
        self.__saveAsButton.setFocusPolicy(Qt.NoFocus)

        self.__levelUpButton = QToolButton(self)
        self.__levelUpButton.setFocusPolicy(Qt.NoFocus)
        self.__levelUpButton.setIcon(getIcon('levelup.png'))
        self.__levelUpButton.setToolTip('Smart zoom level up (Shift+wheel)')
        self.__levelUpButton.clicked.connect(self.onSmartZoomLevelUp)
        self.__levelIndicator = QLabel('<b>0</b>', self)
        self.__levelIndicator.setAlignment(Qt.AlignCenter)
        self.__levelDownButton = QToolButton(self)
        self.__levelDownButton.setFocusPolicy(Qt.NoFocus)
        self.__levelDownButton.setIcon(getIcon('leveldown.png'))
        self.__levelDownButton.setToolTip('Smart zoom level down (Shift+wheel)')
        self.__levelDownButton.clicked.connect(self.onSmartZoomLevelDown)

        fixedSpacer = QWidget()
        fixedSpacer.setFixedHeight(10)

        self.__hideDocstrings = QToolButton(self)
        self.__hideDocstrings.setCheckable(True)
        self.__hideDocstrings.setIcon(getIcon('hidedocstrings.png'))
        self.__hideDocstrings.setToolTip('Show/hide docstrings')
        self.__hideDocstrings.setFocusPolicy(Qt.NoFocus)
        self.__hideDocstrings.setChecked(Settings()['hidedocstrings'])
        self.__hideDocstrings.clicked.connect(self.__onHideDocstrings)
        self.__hideComments = QToolButton(self)
        self.__hideComments.setCheckable(True)
        self.__hideComments.setIcon(getIcon('hidecomments.png'))
        self.__hideComments.setToolTip('Show/hide comments')
        self.__hideComments.setFocusPolicy(Qt.NoFocus)
        self.__hideComments.setChecked(Settings()['hidecomments'])
        self.__hideComments.clicked.connect(self.__onHideComments)
        self.__hideExcepts = QToolButton(self)
        self.__hideExcepts.setCheckable(True)
        self.__hideExcepts.setIcon(getIcon('hideexcepts.png'))
        self.__hideExcepts.setToolTip('Show/hide except blocks')
        self.__hideExcepts.setFocusPolicy(Qt.NoFocus)
        self.__hideExcepts.setChecked(Settings()['hideexcepts'])
        self.__hideExcepts.clicked.connect(self.__onHideExcepts)

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

        self.__toolbar.addWidget(self.__saveAsButton)
        self.__toolbar.addWidget(spacer)
        self.__toolbar.addWidget(self.__levelUpButton)
        self.__toolbar.addWidget(self.__levelIndicator)
        self.__toolbar.addWidget(self.__levelDownButton)
        self.__toolbar.addWidget(fixedSpacer)
        self.__toolbar.addWidget(self.__hideDocstrings)
        self.__toolbar.addWidget(self.__hideComments)
        self.__toolbar.addWidget(self.__hideExcepts)
        return self.__toolbar

    def __createNavigationBar(self):
        """Creates the navigation bar"""
        self.__navBar = ControlFlowNavigationBar(self)
        return self.__navBar

    def __createStackedViews(self):
        """Creates the graphics view"""
        self.smartViews = QStackedWidget(self)
        self.smartViews.setContentsMargins(0, 0, 0, 0)

        self.smartViews.addWidget(CFGraphicsView(self.__navBar, self))
        self.smartViews.addWidget(CFGraphicsView(self.__navBar, self))
        return self.smartViews

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

        start = timer()
        cf = getControlFlowFromMemory(self.__editor.text)
        end = timer()
        if cf.errors:
            self.__navBar.updateInfoIcon(self.__navBar.STATE_BROKEN_UTD)
            errors = []
            for err in cf.errors:
                if err[0] == -1 and err[1] == -1:
                    errors.append(err[2])
                elif err[1] == -1:
                    errors.append('[' + str(err[0]) + ':] ' + err[2])
                elif err[0] == -1:
                    errors.append('[:' + str(err[1]) + '] ' + err[2])
                else:
                    errors.append('[' + str(err[0]) + ':' +
                                  str(err[1]) + '] ' + err[2])
            self.__navBar.setErrors(errors)
            return

        self.__cf = cf
        if self.isDebugMode():
            logging.info('Parsed file: %s', formatFlow(str(self.__cf)))
            logging.info('Parse timing: %f', end - start)

        # Collect warnings (parser + CML warnings) and valid groups
        self.__validGroups = []
        self.__allGroupId = set()
        allWarnings = self.__cf.warnings + \
                      CMLVersion.validateCMLComments(self.__cf,
                                                     self.__validGroups,
                                                     self.__allGroupId)

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

        if allWarnings:
            warnings = []
            for warn in allWarnings:
                if warn[0] == -1 and warn[1] == -1:
                    warnings.append(warn[2])
                elif warn[1] == -1:
                    warnings.append('[' + str(warn[0]) + ':] ' + warn[2])
                elif warn[0] == -1:
                    warnings.append('[:' + str(warn[1]) + '] ' + warn[2])
                else:
                    warnings.append('[' + str(warn[0]) + ':' +
                                    str(warn[1]) + '] ' + warn[2])
            self.__navBar.setWarnings(warnings)
        else:
            self.__navBar.clearWarnings()

        self.redrawScene()

    def __cleanupCanvas(self):
        """Cleans up the canvas"""
        if self.__canvas is not None:
            self.__canvas.cleanup()
            self.__canvas = None
        for item in self.scene().items():
            item.cleanup()
        self.scene().clear()

    def redrawScene(self):
        """Redraws the scene"""
        smartZoomLevel = Settings()['smartZoom']
        self.cflowSettings = getCflowSettings(self)
        if self.dirty():
            self.__displayProps = (self.cflowSettings.hidedocstrings,
                                   self.cflowSettings.hidecomments,
                                   self.cflowSettings.hideexcepts,
                                   smartZoomLevel)
        self.cflowSettings.itemID = 0
        self.cflowSettings = tweakSmartSettings(self.cflowSettings,
                                                smartZoomLevel)

        try:
            fileName = self.__parentWidget.getFileName()
            if not fileName:
                fileName = self.__parentWidget.getShortName()
            collapsedGroups = getCollapsedGroups(fileName)

            # Top level canvas has no adress and no parent canvas
            self.__cleanupCanvas()
            self.__canvas = VirtualCanvas(self.cflowSettings, None, None,
                                          self.__validGroups, collapsedGroups,
                                          None)
            lStart = timer()
            self.__canvas.layoutModule(self.__cf)
            lEnd = timer()
            self.__canvas.setEditor(self.__editor)
            width, height = self.__canvas.render()
            rEnd = timer()
            self.scene().setSceneRect(0, 0, width, height)
            self.__canvas.draw(self.scene(), 0, 0)
            dEnd = timer()
            if self.isDebugMode():
                logging.info('Redrawing is done. Size: %d x %d', width, height)
                logging.info('Layout timing: %f', lEnd - lStart)
                logging.info('Render timing: %f', rEnd - lEnd)
                logging.info('Draw timing: %f', dEnd - rEnd)
        except Exception as exc:
            logging.error(str(exc))
            raise

    def onFlowZoomChanged(self):
        """Triggered when a flow zoom is changed"""
        if self.__cf:
            selection = self.scene().serializeSelection()
            firstOnScreen = self.scene().getFirstLogicalItem()
            self.cflowSettings.onFlowZoomChanged()
            self.redrawScene()
            self.updateNavigationToolbar('')
            self.scene().restoreSelectionByID(selection)
            self.__restoreScroll(firstOnScreen)

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

        if not isPythonMime(newFileType):
            self.__disconnectEditorSignals()
            self.__updateTimer.stop()
            self.__cleanupCanvas()
            self.__cf = None
            self.__validGroups = []
            self.setVisible(False)
            self.__navBar.updateInfoIcon(self.__navBar.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
        _, _, _, cflowHPos, cflowVPos = getFilePosition(fileName)
        self.setScrollbarPositions(cflowHPos, cflowVPos)

    def terminate(self):
        """Called when a tab is closed"""
        if self.__updateTimer.isActive():
            self.__updateTimer.stop()
        self.__updateTimer.deleteLater()

        self.__disconnectEditorSignals()

        self.__mainWindow = GlobalData().mainWindow
        editorsManager = self.__mainWindow.editorsManagerWidget.editorsManager
        editorsManager.sigFileTypeChanged.disconnect(self.__onFileTypeChanged)

        Settings().sigHideDocstringsChanged.disconnect(
            self.__onHideDocstringsChanged)
        Settings().sigHideCommentsChanged.disconnect(self.__onHideCommentsChanged)
        Settings().sigHideExceptsChanged.disconnect(self.__onHideExceptsChanged)
        Settings().sigSmartZoomChanged.disconnect(self.__onSmartZoomChanged)

        # Helps GC to collect more
        self.__cleanupCanvas()
        for index in range(self.smartViews.count()):
            self.smartViews.widget(index).terminate()
            self.smartViews.widget(index).deleteLater()

        self.smartViews.deleteLater()
        self.__navBar.deleteLater()
        self.__cf = None

        self.__saveAsButton.menu().deleteLater()
        self.__saveAsButton.deleteLater()

        self.__levelUpButton.clicked.disconnect(self.onSmartZoomLevelUp)
        self.__levelUpButton.deleteLater()

        self.__levelDownButton.clicked.disconnect(self.onSmartZoomLevelDown)
        self.__levelDownButton.deleteLater()

        self.__hideDocstrings.clicked.disconnect(self.__onHideDocstrings)
        self.__hideDocstrings.deleteLater()

        self.__hideComments.clicked.disconnect(self.__onHideComments)
        self.__hideComments.deleteLater()

        self.__hideExcepts.clicked.disconnect(self.__onHideExcepts)
        self.__hideExcepts.deleteLater()

        self.__toolbar.deleteLater()

        self.__editor = None
        self.__parentWidget = None
        self.cflowSettings = None
        self.__displayProps = 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.__navBar.getCurrentState() in [self.__navBar.STATE_OK_UTD,
                                               self.__navBar.STATE_OK_CHN,
                                               self.__navBar.STATE_UNKNOWN]:
            self.__navBar.updateInfoIcon(self.__navBar.STATE_OK_CHN)
        else:
            self.__navBar.updateInfoIcon(self.__navBar.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 generateNewGroupId(self):
        """Generates a new group ID (string)"""
        # It can also consider the current set of the groups: valid + invalid
        # and generate an integer id which is shorter
        for vacantGroupId in range(1000):
            groupId = str(vacantGroupId)
            if not groupId in self.__allGroupId:
                return groupId
        # Last resort
        return str(uuid.uuid1())

    def updateNavigationToolbar(self, text):
        """Updates the toolbar text"""
        if self.__needPathUpdate:
            self.__navBar.setPath(text)

    def updateSettings(self):
        """Updates settings"""
        self.__needPathUpdate = Settings()['showCFNavigationBar']
        self.__navBar.setPathVisible(self.__needPathUpdate)
        self.__navBar.setPath('')

    def highlightAtAbsPos(self, absPos, line, pos):
        """Scrolls the view to the item closest to absPos and selects it.

        line and pos are 1-based
        """
        item, _ = self.scene().getNearestItem(absPos, line, pos)
        if item:
            GlobalData().mainWindow.setFocusToFloatingRenderer()
            self.scene().clearSelection()
            item.setSelected(True)
            self.view().scrollTo(item)
            self.setFocus()

    def setFocus(self):
        """Sets the focus"""
        self.view().setFocus()

    @staticmethod
    def __getDefaultSaveDir():
        """Provides the default directory to save files to"""
        project = GlobalData().project
        if project.isLoaded():
            return project.getProjectDir()
        return QDir.currentPath()

    def __selectFile(self, extension):
        """Picks a file of a certain extension"""
        dialog = QFileDialog(self, 'Save flowchart as')
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setLabelText(QFileDialog.Accept, "Save")
        dialog.setNameFilter(extension.upper() + " files (*." +
                             extension.lower() + ")")
        urls = []
        for dname in QDir.drives():
            urls.append(QUrl.fromLocalFile(dname.absoluteFilePath()))
        urls.append(QUrl.fromLocalFile(QDir.homePath()))
        project = GlobalData().project
        if project.isLoaded():
            urls.append(QUrl.fromLocalFile(project.getProjectDir()))
        dialog.setSidebarUrls(urls)

        suggestedFName = self.__parentWidget.getFileName()
        if '.' in suggestedFName:
            dotIndex = suggestedFName.rindex('.')
            suggestedFName = suggestedFName[:dotIndex]

        dialog.setDirectory(self.__getDefaultSaveDir())
        dialog.selectFile(suggestedFName + "." + extension.lower())
        dialog.setOption(QFileDialog.DontConfirmOverwrite, False)
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        if dialog.exec_() != QDialog.Accepted:
            return None

        fileNames = dialog.selectedFiles()
        fileName = os.path.abspath(str(fileNames[0]))
        if os.path.isdir(fileName):
            logging.error("A file must be selected")
            return None

        if "." not in fileName:
            fileName += "." + extension.lower()

        # Check permissions to write into the file or to a directory
        if os.path.exists(fileName):
            # Check write permissions for the file
            if not os.access(fileName, os.W_OK):
                logging.error("There is no write permissions for " + fileName)
                return None
        else:
            # Check write permissions to the directory
            dirName = os.path.dirname(fileName)
            if not os.access(dirName, os.W_OK):
                logging.error("There is no write permissions for the "
                              "directory " + dirName)
                return None

        if os.path.exists(fileName):
            res = QMessageBox.warning(
                self, "Save flowchart as",
                "<p>The file <b>" + fileName + "</b> already exists.</p>",
                QMessageBox.StandardButtons(QMessageBox.Abort |
                                            QMessageBox.Save),
                QMessageBox.Abort)
            if res == QMessageBox.Abort or res == QMessageBox.Cancel:
                return None

        # All prerequisites are checked, return a file name
        return fileName

    def onSaveAsSVG(self):
        """Triggered on the 'Save as SVG' button"""
        fileName = self.__selectFile("svg")
        if fileName is None:
            return False

        try:
            self.__saveAsSVG(fileName)
        except Exception as excpt:
            logging.error(str(excpt))
            return False
        return True

    def __saveAsSVG(self, fileName):
        """Saves the flowchart as an SVG file"""
        generator = QSvgGenerator()
        generator.setFileName(fileName)
        generator.setSize(QSize(self.scene().width(), self.scene().height()))
        painter = QPainter(generator)
        self.scene().render(painter)
        painter.end()

    def onSaveAsPDF(self):
        """Triggered on the 'Save as PDF' button"""
        fileName = self.__selectFile("pdf")
        if fileName is None:
            return False

        try:
            self.__saveAsPDF(fileName)
        except Exception as excpt:
            logging.error(str(excpt))
            return False
        return True

    def __saveAsPDF(self, fileName):
        """Saves the flowchart as an PDF file"""
        printer = QPrinter()
        printer.setOutputFormat(QPrinter.PdfFormat)
        printer.setPaperSize(QSizeF(self.scene().width(),
                                    self.scene().height()), QPrinter.Point)
        printer.setFullPage(True)
        printer.setOutputFileName(fileName)

        painter = QPainter(printer)
        self.scene().render(painter)
        painter.end()

    def onSaveAsPNG(self):
        """Triggered on the 'Save as PNG' button"""
        fileName = self.__selectFile("png")
        if fileName is None:
            return False

        try:
            self.__saveAsPNG(fileName)
        except Exception as excpt:
            logging.error(str(excpt))
            return False
        return True

    def __getPNG(self):
        """Renders the scene as PNG"""
        image = QImage(self.scene().width(), self.scene().height(),
                       QImage.Format_ARGB32_Premultiplied)
        painter = QPainter(image)
        # It seems that the better results are without antialiasing
        # painter.setRenderHint( QPainter.Antialiasing )
        self.scene().render(painter)
        painter.end()
        return image

    def __saveAsPNG(self, fileName):
        """Saves the flowchart as an PNG file"""
        image = self.__getPNG()
        image.save(fileName, "PNG")

    def copyToClipboard(self):
        """Copies the rendered scene to the clipboard as an image"""
        image = self.__getPNG()
        clip = QApplication.clipboard()
        clip.setImage(image)

    def getScrollbarPositions(self):
        """Provides the scrollbar positions"""
        hScrollBar = self.view().horizontalScrollBar()
        vScrollBar = self.view().verticalScrollBar()
        return hScrollBar.value(), vScrollBar.value()

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

    def __onHideDocstrings(self):
        """Triggered when a hide docstring button is pressed"""
        Settings()['hidedocstrings'] = not Settings()['hidedocstrings']

    def __onHideDocstringsChanged(self):
        """Signalled by settings"""
        selection = self.scene().serializeSelection()
        firstOnScreen = self.scene().getFirstLogicalItem()
        settings = Settings()
        self.__hideDocstrings.setChecked(settings['hidedocstrings'])
        if self.__checkNeedRedraw():
            self.scene().restoreSelectionByID(selection)
            self.__restoreScroll(firstOnScreen)

    def __onHideComments(self):
        """Triggered when a hide comments button is pressed"""
        Settings()['hidecomments'] = not Settings()['hidecomments']

    def __onHideCommentsChanged(self):
        """Signalled by settings"""
        selection = self.scene().serializeSelection()
        firstOnScreen = self.scene().getFirstLogicalItem()
        settings = Settings()
        self.__hideComments.setChecked(settings['hidecomments'])
        if self.__checkNeedRedraw():
            self.scene().restoreSelectionByID(selection)
            self.__restoreScroll(firstOnScreen)

    def __onHideExcepts(self):
        """Triggered when a hide except blocks button is pressed"""
        Settings()['hideexcepts'] = not Settings()['hideexcepts']

    def __onHideExceptsChanged(self):
        """Signalled by settings"""
        selection = self.scene().serializeSelection()
        firstOnScreen = self.scene().getFirstLogicalItem()
        settings = Settings()
        self.__hideExcepts.setChecked(settings['hideexcepts'])
        if self.__checkNeedRedraw():
            self.scene().restoreSelectionByTooltip(selection)
            self.__restoreScroll(firstOnScreen)

    def __checkNeedRedraw(self):
        """Redraws the scene if necessary when a display setting is changed"""
        editorsManager = self.__mainWindow.editorsManagerWidget.editorsManager
        if self.__parentWidget == editorsManager.currentWidget():
            self.updateNavigationToolbar('')
            self.process()
            return True
        return False

    def dirty(self):
        """True if some other tab has switched display settings"""
        settings = Settings()
        return self.__displayProps[0] != settings['hidedocstrings'] or \
            self.__displayProps[1] != settings['hidecomments'] or \
            self.__displayProps[2] != settings['hideexcepts'] or \
            self.__displayProps[3] != settings['smartZoom']

    def onSmartZoomLevelUp(self):
        """Triggered when an upper smart zoom level was requested"""
        Settings().onSmartZoomIn()

    def onSmartZoomLevelDown(self):
        """Triggered when an lower smart zoom level was requested"""
        Settings().onSmartZoomOut()

    def setSmartZoomLevel(self, smartZoomLevel):
        """Sets the new smart zoom level"""
        maxSmartZoom = Settings().MAX_SMART_ZOOM
        if smartZoomLevel < 0 or smartZoomLevel > maxSmartZoom:
            return

        self.__levelIndicator.setText('<b>' + str(smartZoomLevel) + '</b>')
        self.__levelIndicator.setToolTip(
            getSmartZoomDescription(smartZoomLevel))
        self.__levelUpButton.setEnabled(smartZoomLevel < maxSmartZoom)
        self.__levelDownButton.setEnabled(smartZoomLevel > 0)
        self.smartViews.setCurrentIndex(smartZoomLevel)

    def __onSmartZoomChanged(self):
        """Triggered when a smart zoom changed"""
        selection = self.scene().serializeSelection()
        firstOnScreen = self.scene().getFirstLogicalItem()
        self.setSmartZoomLevel(Settings()['smartZoom'])
        if self.__checkNeedRedraw():
            self.scene().restoreSelectionByTooltip(selection)
            self.__restoreScroll(firstOnScreen)

    def __restoreScroll(self, toItem):
        """Restores the view scrolling to the best possible position"""
        if toItem:
            lineRange = toItem.getLineRange()
            absPosRange = toItem.getAbsPosRange()
            item, _ = self.scene().getNearestItem(absPosRange[0],
                                                  lineRange[0], 0)
            if item:
                self.view().scrollTo(item, True)
                self.view().horizontalScrollBar().setValue(0)

    def validateCollapsedGroups(self, fileName):
        """Checks that there are no collapsed groups which are invalid"""
        if self.__navBar.getCurrentState() != self.__navBar.STATE_OK_UTD:
            return

        collapsedGroups = getCollapsedGroups(fileName)
        if collapsedGroups:
            toBeDeleted = []
            for groupId in collapsedGroups:
                for validId, start, end in self.__validGroups:
                    del start
                    del end
                    if validId == groupId:
                        break
                else:
                    toBeDeleted.append(groupId)

            if toBeDeleted:
                for groupId in toBeDeleted:
                    collapsedGroups.remove(groupId)
                setCollapsedGroups(fileName, collapsedGroups)
        else:
            setCollapsedGroups(fileName, [])

    def getDocItemByAnchor(self, anchor):
        """Provides the graphics item for the given anchor if so"""
        return self.scene().getDocItemByAnchor(anchor)

    @staticmethod
    def isDebugMode():
        """True if it is a debug mode"""
        return GlobalData().skin['debug']
示例#29
0
class ControlFlowNavigationBar(QFrame):
    """Navigation bar at the top of the flow UI widget"""

    STATE_OK_UTD = 0  # Parsed OK, control flow up to date
    STATE_OK_CHN = 1  # Parsed OK, control flow changed
    STATE_BROKEN_UTD = 2  # Parsed with errors, control flow up to date
    STATE_BROKEN_CHN = 3  # Parsed with errors, control flow changed
    STATE_UNKNOWN = 4

    def __init__(self, parent):
        QFrame.__init__(self, parent)
        self.__infoIcon = None
        self.__warningsIcon = None
        self.__layout = None
        self.__pathLabel = None
        self.__createLayout()
        self.__currentIconState = self.STATE_UNKNOWN

    def __createLayout(self):
        """Creates the layout"""
        self.__layout = QHBoxLayout(self)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        # Create info icon
        self.__infoIcon = QLabel(self)
        self.__infoIcon.setPixmap(getPixmap('cfunknown.png'))
        self.__layout.addWidget(self.__infoIcon)

        self.__warningsIcon = QLabel(self)
        self.__warningsIcon.setPixmap(getPixmap('cfwarning.png'))
        self.__layout.addWidget(self.__warningsIcon)

        self.clearWarnings()

        # Create the path label
        self.__pathLabel = HeaderFitLabel(self)
        self.__pathLabel.setTextFormat(Qt.PlainText)
        self.__pathLabel.setAlignment(Qt.AlignLeft)
        self.__pathLabel.setWordWrap(False)
        self.__pathLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__pathLabel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Fixed)
        self.__pathLabel.setMinimumWidth(40)
        self.__layout.addWidget(self.__pathLabel)

        self.__spacer = ToolBarExpandingSpacer(self)
        self.__spacer.setMinimumWidth(0)
        self.__layout.addWidget(self.__spacer)

        # Create the selection label
        self.__selectionLabel = HeaderLabel('', None, self)
        self.__selectionLabel.setTextFormat(Qt.PlainText)
        self.__selectionLabel.setAlignment(Qt.AlignCenter)
        self.__selectionLabel.setWordWrap(False)
        self.__selectionLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__selectionLabel.setSizePolicy(QSizePolicy.Fixed,
                                            QSizePolicy.Fixed)
        self.__selectionLabel.setMinimumWidth(40)
        self.__layout.addWidget(self.__selectionLabel)
        self.setSelectionLabel(0, None)

    def clearWarnings(self):
        """Clears the warnings"""
        self.__warningsIcon.setVisible(False)
        self.__warningsIcon.setToolTip("")

    def setWarnings(self, warnings):
        """Sets the warnings"""
        self.__warningsIcon.setToolTip('Control flow parser warnings:\n' +
                                       '\n'.join(warnings))
        self.__warningsIcon.setVisible(True)

    def clearErrors(self):
        """Clears all the errors"""
        self.__infoIcon.setToolTip('')

    def setErrors(self, errors):
        """Sets the errors"""
        self.__infoIcon.setToolTip('Control flow parser errors:\n' +
                                   '\n'.join(errors))

    def updateInfoIcon(self, state):
        """Updates the information icon"""
        if state == self.__currentIconState:
            return

        if state == self.STATE_OK_UTD:
            self.__infoIcon.setPixmap(getPixmap('cfokutd.png'))
            self.__infoIcon.setToolTip("Control flow is up to date")
            self.__currentIconState = self.STATE_OK_UTD
        elif state == self.STATE_OK_CHN:
            self.__infoIcon.setPixmap(getPixmap('cfokchn.png'))
            self.__infoIcon.setToolTip("Control flow is not up to date; "
                                       "will be updated on idle")
            self.__currentIconState = self.STATE_OK_CHN
        elif state == self.STATE_BROKEN_UTD:
            self.__infoIcon.setPixmap(getPixmap('cfbrokenutd.png'))
            self.__infoIcon.setToolTip("Control flow might be invalid "
                                       "due to invalid python code")
            self.__currentIconState = self.STATE_BROKEN_UTD
        elif state == self.STATE_BROKEN_CHN:
            self.__infoIcon.setPixmap(getPixmap('cfbrokenchn.png'))
            self.__infoIcon.setToolTip("Control flow might be invalid; "
                                       "will be updated on idle")
            self.__currentIconState = self.STATE_BROKEN_CHN
        else:
            # STATE_UNKNOWN
            self.__infoIcon.setPixmap(getPixmap('cfunknown.png'))
            self.__infoIcon.setToolTip("Control flow state is unknown")
            self.__currentIconState = self.STATE_UNKNOWN

    def getCurrentState(self):
        """Provides the current state"""
        return self.__currentIconState

    def setPath(self, txt):
        """Sets the path label content"""
        self.__pathLabel.setText(txt)

    def setPathVisible(self, switchOn):
        """Sets the path visible"""
        self.__pathLabel.setVisible(switchOn)
        self.__spacer.setVisible(not switchOn)

    def setSelectionLabel(self, text, tooltip):
        """Sets selection label"""
        self.__selectionLabel.setText(str(text))
        if tooltip:
            self.__selectionLabel.setToolTip("Selected items:\n" +
                                             str(tooltip))
        else:
            self.__selectionLabel.setToolTip("Number of selected items")

    def resizeEvent(self, event):
        """Editor has resized"""
        QFrame.resizeEvent(self, event)
示例#30
0
class NotUsedAnalysisProgress(QDialog):
    """Progress of the not used analysis"""
    def __init__(self, path, newSearch=True):
        QDialog.__init__(self, GlobalData().mainWindow)

        path = os.path.abspath(path)
        if not os.path.exists(path):
            raise Exception('Dead code analysis path must exist. '
                            'The provide path "' + path + '" does not.')

        self.__path = path

        self.__newSearch = newSearch
        self.candidates = None
        self.__cancelRequest = False
        self.__inProgress = False

        self.__infoLabel = None
        self.__foundLabel = None
        self.__found = 0  # Number of found

        self.__createLayout()
        title = 'Dead code analysis for '
        if os.path.isdir(path):
            project = GlobalData().project
            if project.isLoaded() and project.getProjectDir() == path:
                title += 'all project files'
            else:
                title += 'dir ' + os.path.basename(os.path.normpath(path))
        else:
            title += os.path.basename(path)

        if not self.__newSearch:
            title += ' (do again)'

        self.setWindowTitle(title)
        self.__updateFoundLabel()

    def exec_(self):
        """Executes the dialog"""
        QTimer.singleShot(1, self.__process)
        QDialog.exec_(self)

    def keyPressEvent(self, event):
        """Processes the ESC key specifically"""
        if event.key() == Qt.Key_Escape:
            self.__onClose()
        else:
            QDialog.keyPressEvent(self, event)

    def __updateFoundLabel(self):
        """Updates the found label"""
        text = "Found: " + str(self.__found) + " candidate"
        if self.__found != 1:
            text += "s"
        self.__foundLabel.setText(text)

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

        verticalLayout = QVBoxLayout(self)

        # Note label
        noteLabel = QLabel(
            "<b>Note</b>: the analysis is "
            "suggestive and not precise. "
            "Use the results with caution.\n", self)
        verticalLayout.addWidget(noteLabel)

        # Info label
        self.__infoLabel = QLabel(self)
        verticalLayout.addWidget(self.__infoLabel)

        # Found label
        self.__foundLabel = QLabel(self)
        verticalLayout.addWidget(self.__foundLabel)

        # Buttons
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Close)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)

    def __onClose(self):
        """triggered when the close button is clicked"""
        self.__cancelRequest = True
        if not self.__inProgress:
            self.close()

    def __run(self):
        """Runs vulture"""
        errTmp = tempfile.mkstemp()
        errStream = os.fdopen(errTmp[0])
        process = Popen(['vulture', self.__path],
                        stdin=PIPE,
                        stdout=PIPE,
                        stderr=errStream)
        process.stdin.close()
        processStdout = process.stdout.read()
        process.stdout.close()
        errStream.seek(0)
        err = errStream.read()
        errStream.close()
        process.wait()
        try:
            os.unlink(errTmp[1])
        except:
            pass
        return processStdout.decode(DEFAULT_ENCODING), err.strip()

    def __process(self):
        """Analysis process"""
        self.__inProgress = True
        mainWindow = GlobalData().mainWindow

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        # return code gives really nothing. So the error in running the utility
        # is detected by the stderr content.
        # Also, there could be a mix of messages for a project. Some files
        # could have syntax errors - there will be messages on stderr. The
        # other files are fine so there will be messages on stdout
        stdout, stderr = self.__run()
        self.candidates = []
        for line in stdout.splitlines():
            line = line.strip()
            if line:
                # Line is like file.py:2: unused variable 'a' (60% confidence)
                try:
                    startIndex = line.find(':')
                    if startIndex < 0:
                        continue
                    endIndex = line.find(':', startIndex + 1)
                    if endIndex < 0:
                        continue
                    fileName = line[:startIndex]
                    startIndex = line.find(':')
                    if startIndex < 0:
                        continue
                    endIndex = line.find(':', startIndex + 1)
                    if endIndex < 0:
                        continue
                    fileName = os.path.abspath(line[:startIndex])
                    lineno = int(line[startIndex + 1:endIndex])
                    message = line[endIndex + 1:].strip()
                except:
                    continue

                index = getSearchItemIndex(self.candidates, fileName)
                if index < 0:
                    widget = mainWindow.getWidgetForFileName(fileName)
                    if widget is None:
                        uuid = ''
                    else:
                        uuid = widget.getUUID()
                    newItem = ItemToSearchIn(fileName, uuid)
                    self.candidates.append(newItem)
                    index = len(self.candidates) - 1
                self.candidates[index].addMatch('', lineno, message)

                self.__found += 1
                self.__updateFoundLabel()
                QApplication.processEvents()

        if self.__newSearch:
            # Do the action only for the new search.
            # Redo action will handle the results on its own
            if self.__found == 0:
                if stderr:
                    logging.error('Error running vulture for ' + self.__path +
                                  ':\n' + stderr)
                else:
                    logging.info('No unused candidates found')
            else:
                mainWindow.displayFindInFiles(VultureSearchProvider.getName(),
                                              self.candidates,
                                              {'path': self.__path})

        QApplication.restoreOverrideCursor()
        self.__infoLabel.setText('Done')
        self.__inProgress = False

        self.accept()