Esempio n. 1
0
    def __init__(self):
        QPushButton.__init__(self, getIcon('pluginsettings.png'), "")
        self.setFixedSize(24, 24)
        self.setFocusPolicy(Qt.NoFocus)

        self.index = -1
        self.clicked.connect(self.onClick)
Esempio n. 2
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()
Esempio n. 3
0
    def __init__(self):
        QPushButton.__init__(self, getIcon(pluginHomeDir + 'svnmenudiff.png'),
                             "")
        self.setFixedSize(24, 24)
        self.setFocusPolicy(Qt.NoFocus)

        self.path = ""
        self.status = None
        self.clicked.connect(self.onClick)
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.__headerLabel = HeaderFitLabel(self)
        self.__headerLabel.setText('Variables')
        self.__headerLabel.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Fixed)
        self.__headerLabel.setMinimumWidth(10)

        self.__filterMenu = QMenu(self)
        self.__showAllAct = self.__filterMenu.addAction('Show all variables')
        self.__showAllAct.setData('showall')
        self.__filterMenu.addSeparator()
        self.__filters = []
        for title, settingName, _ in VARIABLE_FILTERS:
            action = self.__filterMenu.addAction(title)
            action.setCheckable(True)
            action.setData(settingName)
            self.__filters.append(action)
        self.__filterMenu.aboutToShow.connect(self.__filterMenuAboutToShow)
        self.__filterMenu.triggered.connect(self.__filterMenuTriggered)

        self.__filterButton = QToolButton(self)
        self.__filterButton.setIcon(getIcon('dbgvarflt.png'))
        self.__filterButton.setToolTip('Variable filter')
        self.__filterButton.setPopupMode(QToolButton.InstantPopup)
        self.__filterButton.setMenu(self.__filterMenu)
        self.__filterButton.setFocusPolicy(Qt.NoFocus)
        self.__filterButton.setFixedSize(self.__headerLabel.height(),
                                         self.__headerLabel.height())

        self.__execStatement = CDMComboBox(True)
        self.__execStatement.setSizePolicy(QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)
        self.__execStatement.lineEdit().setToolTip("Execute statement")
        self.__execStatement.setFixedHeight(26)
        self.__execStatement.editTextChanged.connect(
            self.__execStatementChanged)
        self.__execStatement.enterClicked.connect(self.__onEnterInExec)
        self.__execButton = QPushButton("Exec")
        self.__execButton.setEnabled(False)
        self.__execButton.setFixedHeight(26)
        self.__execButton.clicked.connect(self.__onExec)

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

        execLayout = QGridLayout()
        execLayout.setContentsMargins(1, 1, 1, 1)
        execLayout.setSpacing(1)
        execLayout.addWidget(self.__execStatement, 0, 0)
        execLayout.addWidget(self.__execButton, 0, 1)

        verticalLayout.addWidget(self.headerToolbar)
        verticalLayout.addWidget(self.__browser)
        verticalLayout.addLayout(execLayout)
class VariablesViewer(QWidget):
    """Implements the variables viewer for a debugger"""

    # First group of filters
    FilterGlobalAndLocal = 0
    FilterGlobalOnly = 1
    FilterLocalOnly = 2

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

        self.__debugger = debugger
        self.__browser = VariablesBrowser(debugger, self)
        self.__createLayout()

        self.setTabOrder(self.__browser, self.__execStatement)
        self.setTabOrder(self.__execStatement, self.__execButton)

        self.__updateFilter()

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

        self.__headerLabel = HeaderFitLabel(self)
        self.__headerLabel.setText('Variables')
        self.__headerLabel.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Fixed)
        self.__headerLabel.setMinimumWidth(10)

        self.__filterMenu = QMenu(self)
        self.__showAllAct = self.__filterMenu.addAction('Show all variables')
        self.__showAllAct.setData('showall')
        self.__filterMenu.addSeparator()
        self.__filters = []
        for title, settingName, _ in VARIABLE_FILTERS:
            action = self.__filterMenu.addAction(title)
            action.setCheckable(True)
            action.setData(settingName)
            self.__filters.append(action)
        self.__filterMenu.aboutToShow.connect(self.__filterMenuAboutToShow)
        self.__filterMenu.triggered.connect(self.__filterMenuTriggered)

        self.__filterButton = QToolButton(self)
        self.__filterButton.setIcon(getIcon('dbgvarflt.png'))
        self.__filterButton.setToolTip('Variable filter')
        self.__filterButton.setPopupMode(QToolButton.InstantPopup)
        self.__filterButton.setMenu(self.__filterMenu)
        self.__filterButton.setFocusPolicy(Qt.NoFocus)
        self.__filterButton.setFixedSize(self.__headerLabel.height(),
                                         self.__headerLabel.height())

        self.__execStatement = CDMComboBox(True)
        self.__execStatement.setSizePolicy(QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)
        self.__execStatement.lineEdit().setToolTip("Execute statement")
        self.__execStatement.setFixedHeight(26)
        self.__execStatement.editTextChanged.connect(
            self.__execStatementChanged)
        self.__execStatement.enterClicked.connect(self.__onEnterInExec)
        self.__execButton = QPushButton("Exec")
        self.__execButton.setEnabled(False)
        self.__execButton.setFixedHeight(26)
        self.__execButton.clicked.connect(self.__onExec)

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

        execLayout = QGridLayout()
        execLayout.setContentsMargins(1, 1, 1, 1)
        execLayout.setSpacing(1)
        execLayout.addWidget(self.__execStatement, 0, 0)
        execLayout.addWidget(self.__execButton, 0, 1)

        verticalLayout.addWidget(self.headerToolbar)
        verticalLayout.addWidget(self.__browser)
        verticalLayout.addLayout(execLayout)

    def __filterMenuAboutToShow(self):
        """Debug variable filter menu is about to show"""
        for flt in self.__filters:
            flt.setChecked(Settings()[flt.data()])

    def __filterMenuTriggered(self, act):
        """A filter has been changed"""
        name = act.data()
        if name == 'showall':
            for _, settingName, _ in VARIABLE_FILTERS:
                Settings()[settingName] = True
        else:
            Settings()[name] = not Settings()[name]
        self.__updateFilter()

    def updateVariables(self, areGlobals, frameNumber, variables):
        """Triggered when a new set of variables is received"""
        self.__browser.showVariables(areGlobals, variables, frameNumber)
        self.__updateHeaderLabel()

    def updateVariable(self, areGlobals, variables):
        """Triggered when a new variable has been received"""
        self.__browser.showVariable(areGlobals, variables)
        self.__updateHeaderLabel()

    def __updateHeaderLabel(self):
        """Updates the header text"""
        shown, total = self.__browser.getShownAndTotalCounts()
        if shown == 0 and total == 0:
            self.__headerLabel.setText("Variables")
        else:
            self.__headerLabel.setText("Variables (" + str(shown) + " of " +
                                       str(total) + ")")

    def __updateFilter(self):
        """Updates the current filter"""
        self.__browser.filterChanged()
        self.__updateHeaderLabel()

    def clear(self):
        """Clears the content"""
        self.__browser.clear()
        self.__updateHeaderLabel()

    def clearAll(self):
        """Clears everything including the history"""
        self.clear()
        self.__execStatement.lineEdit().setText("")
        self.__execStatement.clear()

    def __execStatementChanged(self, text):
        """Triggered when a exec statement is changed"""
        text = str(text).strip()
        self.__execButton.setEnabled(text != "")

    def __onEnterInExec(self):
        """Enter/return clicked in exec"""
        self.__onExec()

    def __onExec(self):
        """Triggered when the Exec button is clicked"""
        text = self.__execStatement.currentText().strip()
        if text != "":
            currentFrame = GlobalData().mainWindow.getCurrentFrameNumber()
            self.__debugger.remoteExecuteStatement(text, currentFrame)
            self.__debugger.remoteClientVariables(1, currentFrame)  # globals
            self.__debugger.remoteClientVariables(0, currentFrame)  # locals

    def switchControl(self, isInIDE):
        """Switches the UI depending where the control flow is"""
        self.__browser.setEnabled(isInIDE)
        self.__filterButton.setEnabled(isInIDE)

        self.__execStatement.setEnabled(isInIDE)
        if isInIDE:
            text = self.__execStatement.currentText().strip()
            self.__execButton.setEnabled(text != "")
        else:
            self.__execButton.setEnabled(False)
Esempio n. 6
0
    def __createLayout(self):
        """Creates the widget layout"""
        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

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

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

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

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

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

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

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

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

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

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

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

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

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

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

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)
Esempio n. 7
0
class IgnoredExceptionsViewer(QWidget):
    """Implements the client exceptions viewer for a debugger"""
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

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

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

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

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

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

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

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

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

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

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

            Settings()['showIgnoredExcViewer'] = True

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

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

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

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

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

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

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

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

        self.__addButton.setEnabled(True)

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

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

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

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

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

        text = self.__currentItem.text(0)

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

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

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

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

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

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

        self.__headerLabel = QLabel("Variables")

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

        self.__filterMenu = QMenu(self)
        self.__showAllAct = self.__filterMenu.addAction('Show all variables')
        self.__showAllAct.setData('showall')
        self.__filterMenu.addSeparator()
        self.__filters = []
        for title, settingName, _ in VARIABLE_FILTERS:
            action = self.__filterMenu.addAction(title)
            action.setCheckable(True)
            action.setData(settingName)
            self.__filters.append(action)
        self.__filterMenu.aboutToShow.connect(self.__filterMenuAboutToShow)
        self.__filterMenu.triggered.connect(self.__filterMenuTriggered)

        self.__filterButton = QToolButton(self)
        self.__filterButton.setIcon(getIcon('dbgvarflt.png'))
        self.__filterButton.setToolTip('Variable filter')
        self.__filterButton.setPopupMode(QToolButton.InstantPopup)
        self.__filterButton.setMenu(self.__filterMenu)
        self.__filterButton.setFocusPolicy(Qt.NoFocus)
        self.__filterButton.setFixedSize(HEADER_BUTTON, HEADER_BUTTON)

        self.__execStatement = CDMComboBox(True)
        self.__execStatement.setSizePolicy(QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)
        self.__execStatement.lineEdit().setToolTip("Execute statement")
        self.__execStatement.setFixedHeight(26)
        self.__execStatement.editTextChanged.connect(
            self.__execStatementChanged)
        self.__execStatement.enterClicked.connect(self.__onEnterInExec)
        self.__execButton = QPushButton("Exec")
        self.__execButton.setEnabled(False)
        self.__execButton.setFixedHeight(26)
        self.__execButton.clicked.connect(self.__onExec)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.setSpacing(0)
        headerLayout.addSpacing(3)
        headerLayout.addWidget(self.__headerLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__filterButton)
        headerFrame.setLayout(headerLayout)

        execLayout = QGridLayout()
        execLayout.setContentsMargins(1, 1, 1, 1)
        execLayout.setSpacing(1)
        execLayout.addWidget(self.__execStatement, 0, 0)
        execLayout.addWidget(self.__execButton, 0, 1)

        verticalLayout.addWidget(headerFrame)
        verticalLayout.addWidget(self.__browser)
        verticalLayout.addLayout(execLayout)
Esempio n. 9
0
class FindInFilesDialog(QDialog):

    """find in files dialog implementation"""

    IN_PROJECT = 0
    IN_DIRECTORY = 1
    IN_OPEN_FILES = 2

    def __init__(self, where=None, what=None, dirPath=None, params=None):
        QDialog.__init__(self, GlobalData().mainWindow)

        # If parans is not None it means it is a repeated search

        mainWindow = GlobalData().mainWindow
        self.editorsManager = mainWindow.editorsManagerWidget.editorsManager

        self.__cancelRequest = False
        self.__inProgress = False
        self.searchRegexp = None
        self.searchResults = []

        # Avoid pylint complains
        self.findCombo = None
        self.caseCheckBox = None
        self.wordCheckBox = None
        self.regexpCheckBox = None
        self.projectRButton = None
        self.openFilesRButton = None
        self.dirRButton = None
        self.dirEditCombo = None
        self.dirSelectButton = None
        self.filterCombo = None
        self.fileLabel = None
        self.progressBar = None
        self.findButton = None

        self.__createLayout()

        self.__maxEntries = Settings()['maxSearchEntries']

        if params is None:
            self.__newSearch = True
            self.setWindowTitle("Find in files")

            # Restore the combo box values
            # [ {'term': ., 'dir': ., 'filters': .,
            #    'cbCase': ., 'cbWord': ., 'cbRegexp': .,
            #    'rbProject': ., 'rbOpen': ., 'rbDir': .}, ... ]
            self.__history = getFindInFilesHistory()
            self.__populateHistory()
            self.findCombo.setEditText('')
            self.dirEditCombo.setEditText('')
            self.filterCombo.setEditText('')

            if where == self.IN_PROJECT:
                self.setSearchInProject(what)
            elif where == self.IN_DIRECTORY:
                self.setSearchInDirectory(what, dirPath)
            else:
                self.setSearchInOpenFiles(what)
        else:
            self.__newSearch = False
            self.setWindowTitle("Find in files: search again")
            self.__populateSearchAgain(params)

    def exec_(self):
        """Execute the dialog"""
        if not self.__newSearch:
            QTimer.singleShot(1, self.__process)
        QDialog.exec_(self)

    def __serialize(self):
        """Serializes the current search parameters"""
        termText = self.findCombo.currentText()
        filtText = self.__normalizeFilters(self.filterCombo.currentText())
        dirText = ''
        if self.dirRButton.isChecked():
            dirText = self.dirEditCombo.currentText().strip()

        return {'term': termText,
                'dir': dirText,
                'filters': filtText,
                'cbCase': self.caseCheckBox.isChecked(),
                'cbWord': self.wordCheckBox.isChecked(),
                'cbRegexp': self.regexpCheckBox.isChecked(),
                'rbProject': self.projectRButton.isChecked(),
                'rbOpen': self.openFilesRButton.isChecked(),
                'rbDir': self.dirRButton.isChecked()}

    def __deserialize(self, item):
        """Deserializes the history item"""
        self.findCombo.setEditText(item['term'])
        self.dirEditCombo.setEditText(item['dir'])
        self.filterCombo.setEditText(item['filters'])
        self.caseCheckBox.setChecked(item['cbCase'])
        self.wordCheckBox.setChecked(item['cbWord'])
        self.regexpCheckBox.setChecked(item['cbRegexp'])

        self.projectRButton.setChecked(item['rbProject'])
        self.openFilesRButton.setChecked(item['rbOpen'])
        self.dirRButton.setChecked(item['rbDir'])

        self.dirEditCombo.setEnabled(item['rbDir'])
        self.dirSelectButton.setEnabled(item['rbDir'])

    def __populateHistory(self):
        """Populates the search history in the combo boxes"""
        # No need to react to the change of the current index
        self.findCombo.currentIndexChanged[int].disconnect(
            self.__whatIndexChanged)
        index = 0
        for props in self.__history:
            self.findCombo.addItem(props['term'], index)
            directory = props['dir']
            if directory:
                self.dirEditCombo.addItem(directory)
            filt = props['filters']
            if filt:
                self.filterCombo.addItem(filt)
            index += 1
        # Restore the handler
        self.findCombo.currentIndexChanged[int].connect(
            self.__whatIndexChanged)

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

        verticalLayout = QVBoxLayout(self)
        gridLayout = QGridLayout()

        # Combo box for the text to search
        findLabel = QLabel(self)
        findLabel.setText("Find text:")
        self.findCombo = QComboBox(self)
        self.__tuneCombo(self.findCombo)
        self.findCombo.lineEdit().setToolTip(
            "Regular expression to search for")
        self.findCombo.editTextChanged.connect(self.__someTextChanged)
        self.findCombo.currentIndexChanged[int].connect(
            self.__whatIndexChanged)

        gridLayout.addWidget(findLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.findCombo, 0, 1, 1, 1)
        verticalLayout.addLayout(gridLayout)

        # Check boxes
        horizontalCBLayout = QHBoxLayout()
        self.caseCheckBox = QCheckBox(self)
        self.caseCheckBox.setText("Match &case")
        horizontalCBLayout.addWidget(self.caseCheckBox)
        self.wordCheckBox = QCheckBox(self)
        self.wordCheckBox.setText("Match whole &word")
        horizontalCBLayout.addWidget(self.wordCheckBox)
        self.regexpCheckBox = QCheckBox(self)
        self.regexpCheckBox.setText("Regular &expression")
        horizontalCBLayout.addWidget(self.regexpCheckBox)

        verticalLayout.addLayout(horizontalCBLayout)

        # Files groupbox
        filesGroupbox = QGroupBox(self)
        filesGroupbox.setTitle("Find in")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            filesGroupbox.sizePolicy().hasHeightForWidth())
        filesGroupbox.setSizePolicy(sizePolicy)

        gridLayoutFG = QGridLayout(filesGroupbox)
        self.projectRButton = QRadioButton(filesGroupbox)
        self.projectRButton.setText("&Project")
        gridLayoutFG.addWidget(self.projectRButton, 0, 0)
        self.projectRButton.clicked.connect(self.__projectClicked)

        self.openFilesRButton = QRadioButton(filesGroupbox)
        self.openFilesRButton.setText("&Opened files only")
        gridLayoutFG.addWidget(self.openFilesRButton, 1, 0)
        self.openFilesRButton.clicked.connect(self.__openFilesOnlyClicked)

        self.dirRButton = QRadioButton(filesGroupbox)
        self.dirRButton.setText("&Directory tree")
        gridLayoutFG.addWidget(self.dirRButton, 2, 0)
        self.dirRButton.clicked.connect(self.__dirClicked)

        self.dirEditCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.dirEditCombo)
        self.dirEditCombo.lineEdit().setToolTip("Directory to search in")
        gridLayoutFG.addWidget(self.dirEditCombo, 2, 1)
        self.dirEditCombo.editTextChanged.connect(self.__someTextChanged)

        self.dirSelectButton = QPushButton(filesGroupbox)
        self.dirSelectButton.setText("...")
        gridLayoutFG.addWidget(self.dirSelectButton, 2, 2)
        self.dirSelectButton.clicked.connect(self.__selectDirClicked)

        filterLabel = QLabel(filesGroupbox)
        filterLabel.setText("Files filter:")
        gridLayoutFG.addWidget(filterLabel, 3, 0)
        self.filterCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.filterCombo)
        self.filterCombo.lineEdit().setToolTip("File names regular expression")
        gridLayoutFG.addWidget(self.filterCombo, 3, 1)
        self.filterCombo.editTextChanged.connect(self.__someTextChanged)

        verticalLayout.addWidget(filesGroupbox)

        # File label
        self.fileLabel = FitPathLabel(parent=self)
        self.fileLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        verticalLayout.addWidget(self.fileLabel)

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

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.findButton = buttonBox.addButton("Find",
                                              QDialogButtonBox.AcceptRole)
        self.findButton.setDefault(True)
        self.findButton.clicked.connect(self.__process)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)

    @staticmethod
    def __tuneCombo(comboBox):
        """Sets the common settings for a combo box"""
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            comboBox.sizePolicy().hasHeightForWidth())
        comboBox.setSizePolicy(sizePolicy)
        comboBox.setEditable(True)
        comboBox.setInsertPolicy(QComboBox.InsertAtTop)
        comboBox.setCompleter(None)
        comboBox.setDuplicatesEnabled(False)

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

    def __historyIndexByWhat(self, what):
        """Provides the history index by 'what' value"""
        if what:
            for index in range(self.findCombo.count()):
                if self.findCombo.itemText(index) == what:
                    return index, self.findCombo.itemData(index)
        return None, None

    @staticmethod
    def __indexByText(combo, text):
        """Provides the text entry index"""
        index = 0
        for index in range(combo.count()):
            if combo.itemText(index) == text:
                return index
            index += 1
        return -1

    def setSearchInProject(self, what=None):
        """Set search ready for the whole project"""
        if not GlobalData().project.isLoaded():
            # No project loaded, fallback to opened files
            self.setSearchInOpenFiles(what)
            return

        # Select the project radio button
        self.projectRButton.setEnabled(True)
        self.projectRButton.setChecked(True)
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)

        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled(len(openedFiles) != 0)

        if what:
            # Pick up the history values if so
            comboIndex, historyIndex = self.__historyIndexByWhat(what)
            if historyIndex is not None:
                self.__deserialize(self.__history[historyIndex])
                self.findCombo.setCurrentIndex(comboIndex)
            else:
                self.findCombo.setCurrentText(what)
            self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()

    def setSearchInOpenFiles(self, what=None):
        """Sets search ready for the opened files"""
        openedFiles = self.editorsManager.getTextEditors()
        if not openedFiles:
            # No opened files, fallback to search in dir
            self.setSearchInDirectory(what, None)
            return

        # Select the radio buttons
        self.projectRButton.setEnabled(GlobalData().project.isLoaded())
        self.openFilesRButton.setEnabled(True)
        self.openFilesRButton.setChecked(True)
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)

        if what:
            # Pick up the history values if so
            comboIndex, historyIndex = self.__historyIndexByWhat(what)
            if historyIndex is not None:
                self.__deserialize(self.__history[historyIndex])
                self.findCombo.setCurrentIndex(comboIndex)
            else:
                self.findCombo.setCurrentText(what)
            self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()

    def setSearchInDirectory(self, what=None, dirPath=None):
        """Sets search ready for the given directory"""
        # Select radio buttons
        self.projectRButton.setEnabled(GlobalData().project.isLoaded())
        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled(len(openedFiles) != 0)
        self.dirRButton.setEnabled(True)
        self.dirRButton.setChecked(True)
        self.dirEditCombo.setEnabled(True)
        self.dirSelectButton.setEnabled(True)

        if what:
            # Pick up the history values if so
            comboIndex, historyIndex = self.__historyIndexByWhat(what)
            if historyIndex is not None:
                self.__deserialize(self.__history[historyIndex])
                self.findCombo.setCurrentIndex(comboIndex)
            else:
                self.findCombo.setCurrentText(what)
            self.findCombo.lineEdit().selectAll()

        if dirPath:
            self.dirEditCombo.setEditText(dirPath)

        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()

    def getParameters(self):
        """Provides a dictionary with the search parameters"""
        parameters = {'term': self.findCombo.currentText(),
                      'case': self.caseCheckBox.isChecked(),
                      'whole': self.wordCheckBox.isChecked(),
                      'regexp': self.regexpCheckBox.isChecked()}
        if self.projectRButton.isChecked():
            parameters['in-project'] = True
            parameters['in-opened'] = False
            parameters['in-dir'] = ''
        elif self.openFilesRButton.isChecked():
            parameters['in-project'] = False
            parameters['in-opened'] = True
            parameters['in-dir'] = ''
        else:
            parameters['in-project'] = False
            parameters['in-opened'] = False
            parameters['in-dir'] = realpath(
                self.dirEditCombo.currentText().strip())
        parameters['file-filter'] = self.filterCombo.currentText().strip()

        return parameters

    def __populateSearchAgain(self, params):
        """Populates the search parameters to do the same search"""
        self.findCombo.setEditText(params['term'])
        self.findCombo.setEnabled(False)
        self.caseCheckBox.setChecked(params['case'])
        self.caseCheckBox.setEnabled(False)
        self.wordCheckBox.setChecked(params['whole'])
        self.wordCheckBox.setEnabled(False)
        self.regexpCheckBox.setChecked(params['regexp'])
        self.regexpCheckBox.setEnabled(False)

        if params['in-project']:
            self.projectRButton.setChecked(True)
        elif params['in-opened']:
            self.openFilesRButton.setChecked(True)
        else:
            self.dirRButton.setChecked(True)

        self.projectRButton.setEnabled(False)
        self.openFilesRButton.setEnabled(False)
        self.dirRButton.setEnabled(False)

        self.dirEditCombo.setEditText(params['in-dir'])
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)

        self.filterCombo.setEditText(params['file-filter'])
        self.filterCombo.setEnabled(False)

    @staticmethod
    def __normalizeFilters(text):
        """Normalizes the filters string"""
        normParts = []
        for part in text.strip().split(';'):
            part = part.strip()
            if part:
                normParts.append(part)
        return '; '.join(normParts)

    def __testSearchability(self):
        """Tests the searchability and sets the Find button status"""
        startTime = time.time()
        if self.findCombo.currentText().strip() == "":
            self.findButton.setEnabled(False)
            self.findButton.setToolTip("No text to search")
            return

        if self.dirRButton.isChecked():
            dirname = self.dirEditCombo.currentText().strip()
            if dirname == "":
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("No directory path")
                return
            if not isdir(dirname):
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("Path is not a directory")
                return

        # Now we need to match file names if there is a filter
        filtersText = self.filterCombo.currentText().strip()
        if filtersText == "":
            self.findButton.setEnabled(True)
            self.findButton.setToolTip("Find in files")
            return

        # Need to check the files match
        try:
            filters = self.__compileFilters()
        except:
            self.findButton.setEnabled(False)
            self.findButton.setToolTip("Incorrect files "
                                       "filter regular expression")
            return

        matched = False
        tooLong = False
        if self.projectRButton.isChecked():
            # Whole project
            for fname in GlobalData().project.filesList:
                if fname.endswith(sep):
                    continue
                matched = self.__filterMatch(filters, fname)
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        elif self.openFilesRButton.isChecked():
            # Opened files
            openedFiles = self.editorsManager.getTextEditors()
            for record in openedFiles:
                matched = self.__filterMatch(filters, record[1])
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        else:
            # Search in the dir
            if not dirname.endswith(sep):
                dirname += sep
            matched, tooLong = self.__matchInDir(dirname, filters, startTime)

        if matched:
            self.findButton.setEnabled(True)
            self.findButton.setToolTip("Find in files")
        else:
            if tooLong:
                self.findButton.setEnabled(True)
                self.findButton.setToolTip("Find in files")
            else:
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("No files matched to search in")

    @staticmethod
    def __matchInDir(path, filters, startTime):
        """Provides the 'match' and 'too long' statuses"""
        matched = False
        tooLong = False
        for item in listdir(path):
            if time.time() - startTime > 0.1:
                tooLong = True
                return matched, tooLong
            if isdir(path + item):
                dname = path + item + sep
                matched, tooLong = FindInFilesDialog.__matchInDir(dname,
                                                                  filters,
                                                                  startTime)
                if matched or tooLong:
                    return matched, tooLong
                continue
            if FindInFilesDialog.__filterMatch(filters, path + item):
                matched = True
                return matched, tooLong
        return matched, tooLong

    def __projectClicked(self):
        """project radio button clicked"""
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)
        self.__testSearchability()

    def __openFilesOnlyClicked(self):
        """open files only radio button clicked"""
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)
        self.__testSearchability()

    def __dirClicked(self):
        """dir radio button clicked"""
        self.dirEditCombo.setEnabled(True)
        self.dirSelectButton.setEnabled(True)
        self.dirEditCombo.setFocus()
        self.__testSearchability()

    def __someTextChanged(self, text):
        """Text to search, filter or dir name has been changed"""
        del text    # unused argument
        self.__testSearchability()

    def __whatIndexChanged(self, index):
        """Index in history has changed"""
        if index != -1:
            historyIndex = self.findCombo.itemData(index)
            if historyIndex is not None:
                self.__deserialize(self.__history[historyIndex])
        self.__testSearchability()

    def __selectDirClicked(self):
        """The user selects a directory"""
        options = QFileDialog.Options()
        options |= QFileDialog.ShowDirsOnly | QFileDialog.DontUseNativeDialog
        dirName = QFileDialog.getExistingDirectory(
            self, 'Select directory to search in',
            self.dirEditCombo.currentText(), options)

        if dirName:
            self.dirEditCombo.setEditText(normpath(dirName))
        self.__testSearchability()

    @staticmethod
    def __filterMatch(filters, fname):
        """True if the file should be taken into consideration"""
        if filters:
            for filt in filters:
                if filt.match(fname):
                    return True
            return False
        return True

    def __projectFiles(self, filters):
        """Project files list respecting the mask"""
        mainWindow = GlobalData().mainWindow
        files = []
        for fname in GlobalData().project.filesList:
            if fname.endswith(sep):
                continue
            if self.__filterMatch(filters, fname):
                widget = mainWindow.getWidgetForFileName(fname)
                if widget is None:
                    # Do not check for broken symlinks
                    if isFileSearchable(fname, False):
                        files.append(ItemToSearchIn(fname, ""))
                else:
                    if widget.getType() in \
                                [MainWindowTabWidgetBase.PlainTextEditor]:
                        files.append(ItemToSearchIn(fname,
                                                    widget.getUUID()))
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
        return files

    def __openedFiles(self, filters):
        """Currently opened editor buffers"""
        files = []
        openedFiles = self.editorsManager.getTextEditors()
        for record in openedFiles:
            uuid = record[0]
            fname = record[1]
            if self.__filterMatch(filters, fname):
                files.append(ItemToSearchIn(fname, uuid))
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
        return files

    def __dirFiles(self, path, filters, files):
        """Files recursively for the dir"""
        for item in listdir(path):
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
            if isdir(path + item):
                if item in ['.svn', '.cvs', '.git', '.hg']:
                    # It does not make sense to search in revision control dirs
                    continue
                anotherDir, isLoop = resolveLink(path + item)
                if not isLoop:
                    self.__dirFiles(anotherDir + sep,
                                    filters, files)
                continue
            if not isfile(path + item):
                continue
            realItem, isLoop = resolveLink(path + item)
            if isLoop:
                continue
            if self.__filterMatch(filters, realItem):
                found = False
                for itm in files:
                    if itm.fileName == realItem:
                        found = True
                        break
                if not found:
                    mainWindow = GlobalData().mainWindow
                    widget = mainWindow.getWidgetForFileName(realItem)
                    if widget is None:
                        if isFileSearchable(realItem):
                            files.append(ItemToSearchIn(realItem, ""))
                    else:
                        if widget.getType() in \
                                    [MainWindowTabWidgetBase.PlainTextEditor]:
                            files.append(ItemToSearchIn(realItem,
                                                        widget.getUUID()))

    def __compileFilters(self):
        """Compiles the filters"""
        filtersText = self.filterCombo.currentText().strip()
        filtersRe = []
        if filtersText != "":
            for filt in filtersText.split(';'):
                filtersRe.append(re.compile(filt.strip(), re.IGNORECASE))
        return filtersRe

    def __buildFilesList(self):
        """Builds the list of files to search in"""
        filtersRe = self.__compileFilters()

        if self.projectRButton.isChecked():
            return self.__projectFiles(filtersRe)

        if self.openFilesRButton.isChecked():
            return self.__openedFiles(filtersRe)

        dirname = realpath(self.dirEditCombo.currentText().strip())
        files = []
        self.__dirFiles(dirname + sep, filtersRe, files)
        return files

    def __updateHistory(self):
        """Updates history if needed"""
        if not self.__newSearch:
            return

        # Add entries to the combo box if required
        historyItem = self.__serialize()
        _, historyIndex = self.__historyIndexByWhat(
            self.findCombo.currentText())
        if historyIndex is not None:
            self.__history[historyIndex] = historyItem
        else:
            historyIndex = 0
            self.__history.insert(0, historyItem)
            if len(self.__history) > self.__maxEntries:
                self.__history = self.__history[:self.__maxEntries]

        self.findCombo.clear()
        self.filterCombo.clear()
        self.dirEditCombo.clear()
        self.__populateHistory()

        self.findCombo.setCurrentIndex(historyIndex)
        self.findCombo.setCurrentText(historyItem['term'])

        fltValue = historyItem['filters']
        if fltValue:
            index = self.__indexByText(self.filterCombo, fltValue)
            self.filterCombo.setCurrentIndex(index)
        self.filterCombo.setCurrentText(fltValue)

        dirValue = historyItem['dir']
        if dirValue:
            index = self.__indexByText(self.dirEditCombo, dirValue)
            self.dirEditCombo.setCurrentIndex(index)
        self.dirEditCombo.setCurrentText(dirValue)

        # Save the combo values for further usage
        setFindInFilesHistory(self.__history)

    def __process(self):
        """Search process"""
        self.__updateHistory()

        self.__inProgress = True
        numberOfMatches = 0
        self.searchResults = []
        self.searchRegexp = None

        # Form the regexp to search
        regexpText = self.findCombo.currentText()
        if not self.regexpCheckBox.isChecked():
            regexpText = re.escape(regexpText)
        if self.wordCheckBox.isChecked():
            regexpText = "\\b%s\\b" % regexpText
        flags = re.UNICODE
        if not self.caseCheckBox.isChecked():
            flags |= re.IGNORECASE

        try:
            self.searchRegexp = re.compile(regexpText, flags)
        except Exception as exc:
            logging.error("Invalid search expression: %s", str(exc))
            self.close()
            return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.fileLabel.setPath('Building list of files to search in...')
        QApplication.processEvents()
        try:
            files = self.__buildFilesList()
        except Exception as exc:
            QApplication.restoreOverrideCursor()
            if 'Cancel request' not in str(exc):
                logging.error(str(exc))
            self.close()
            return
        QApplication.restoreOverrideCursor()
        QApplication.processEvents()

        if not files:
            self.fileLabel.setPath('No files to search in')
            return

        self.progressBar.setRange(0, len(files))

        index = 1
        for item in files:

            if self.__cancelRequest:
                self.__inProgress = False
                self.close()
                return

            self.fileLabel.setPath('Matches: ' + str(numberOfMatches) +
                                   ' Processing: ' + item.fileName)

            item.search(self.searchRegexp)
            found = len(item.matches)
            if found > 0:
                numberOfMatches += found
                self.searchResults.append(item)

            self.progressBar.setValue(index)
            index += 1

            QApplication.processEvents()

        if numberOfMatches > 0 or self.__newSearch == False:
            # If it is redo then close the dialog anyway
            self.close()
        else:
            msg = 'No matches in ' + str(len(files)) + ' file'
            if len(files) > 1:
                msg += 's'
            self.fileLabel.setPath(msg)
            self.__inProgress = False
Esempio n. 10
0
    def __createLayout(self):
        """Creates the dialog layout"""
        self.resize(600, 300)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)
        gridLayout = QGridLayout()

        # Combo box for the text to search
        findLabel = QLabel(self)
        findLabel.setText("Find text:")
        self.findCombo = QComboBox(self)
        self.__tuneCombo(self.findCombo)
        self.findCombo.lineEdit().setToolTip(
            "Regular expression to search for")
        self.findCombo.editTextChanged.connect(self.__someTextChanged)
        self.findCombo.currentIndexChanged[int].connect(
            self.__whatIndexChanged)

        gridLayout.addWidget(findLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.findCombo, 0, 1, 1, 1)
        verticalLayout.addLayout(gridLayout)

        # Check boxes
        horizontalCBLayout = QHBoxLayout()
        self.caseCheckBox = QCheckBox(self)
        self.caseCheckBox.setText("Match &case")
        horizontalCBLayout.addWidget(self.caseCheckBox)
        self.wordCheckBox = QCheckBox(self)
        self.wordCheckBox.setText("Match whole &word")
        horizontalCBLayout.addWidget(self.wordCheckBox)
        self.regexpCheckBox = QCheckBox(self)
        self.regexpCheckBox.setText("Regular &expression")
        horizontalCBLayout.addWidget(self.regexpCheckBox)

        verticalLayout.addLayout(horizontalCBLayout)

        # Files groupbox
        filesGroupbox = QGroupBox(self)
        filesGroupbox.setTitle("Find in")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            filesGroupbox.sizePolicy().hasHeightForWidth())
        filesGroupbox.setSizePolicy(sizePolicy)

        gridLayoutFG = QGridLayout(filesGroupbox)
        self.projectRButton = QRadioButton(filesGroupbox)
        self.projectRButton.setText("&Project")
        gridLayoutFG.addWidget(self.projectRButton, 0, 0)
        self.projectRButton.clicked.connect(self.__projectClicked)

        self.openFilesRButton = QRadioButton(filesGroupbox)
        self.openFilesRButton.setText("&Opened files only")
        gridLayoutFG.addWidget(self.openFilesRButton, 1, 0)
        self.openFilesRButton.clicked.connect(self.__openFilesOnlyClicked)

        self.dirRButton = QRadioButton(filesGroupbox)
        self.dirRButton.setText("&Directory tree")
        gridLayoutFG.addWidget(self.dirRButton, 2, 0)
        self.dirRButton.clicked.connect(self.__dirClicked)

        self.dirEditCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.dirEditCombo)
        self.dirEditCombo.lineEdit().setToolTip("Directory to search in")
        gridLayoutFG.addWidget(self.dirEditCombo, 2, 1)
        self.dirEditCombo.editTextChanged.connect(self.__someTextChanged)

        self.dirSelectButton = QPushButton(filesGroupbox)
        self.dirSelectButton.setText("...")
        gridLayoutFG.addWidget(self.dirSelectButton, 2, 2)
        self.dirSelectButton.clicked.connect(self.__selectDirClicked)

        filterLabel = QLabel(filesGroupbox)
        filterLabel.setText("Files filter:")
        gridLayoutFG.addWidget(filterLabel, 3, 0)
        self.filterCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.filterCombo)
        self.filterCombo.lineEdit().setToolTip("File names regular expression")
        gridLayoutFG.addWidget(self.filterCombo, 3, 1)
        self.filterCombo.editTextChanged.connect(self.__someTextChanged)

        verticalLayout.addWidget(filesGroupbox)

        # File label
        self.fileLabel = FitPathLabel(parent=self)
        self.fileLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        verticalLayout.addWidget(self.fileLabel)

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

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.findButton = buttonBox.addButton("Find",
                                              QDialogButtonBox.AcceptRole)
        self.findButton.setDefault(True)
        self.findButton.clicked.connect(self.__process)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)
Esempio n. 11
0
class DocLinkAnchorDialog(QDialog):
    """Replace text input dialog"""
    def __init__(self, windowTitle, cmlDocComment, fileName, parent):
        QDialog.__init__(self, parent)

        # Name of a file from which the doc link is created/edited
        self.__fileName = fileName
        self.setWindowTitle(windowTitle + ' documentation link and/or anchor')

        self.__createLayout()
        self.__invalidInputColor = GlobalData().skin['invalidInputPaper']
        self.__validInputColor = self.linkEdit.palette().color(
            self.linkEdit.backgroundRole())

        if cmlDocComment is not None:
            self.__populate(cmlDocComment)

    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.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()

    def setTitle(self, txt):
        """Sets the title text to be edited"""
        self.titleEdit.setPlainText(txt)

    def title(self):
        """Provides the new title text"""
        return self.titleEdit.toPlainText()

    def needToCreate(self):
        return self.createCheckBox.isEnabled(
        ) and self.createCheckBox.isChecked()

    def __populate(self, cmlDocComment):
        """Populates the fields from the comment"""
        if cmlDocComment.link:
            self.linkEdit.setText(cmlDocComment.link)
        if cmlDocComment.anchor:
            self.anchorEdit.setText(cmlDocComment.anchor)
        if cmlDocComment.title:
            self.setTitle(cmlDocComment.getTitle())

    def __onSelectPath(self):
        """Select file or directory"""
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        selectedPath = QFileDialog.getOpenFileName(self,
                                                   'Select documentation file',
                                                   self.linkEdit.text(),
                                                   options=options)
        if isinstance(selectedPath, tuple):
            selectedPath = selectedPath[0]
        if selectedPath:
            self.linkEdit.setText(os.path.normpath(selectedPath))

    def __setLinkValid(self):
        """Sets the link edit valid"""
        self.linkEdit.setToolTip(
            'A link to a file or to an external web resource')
        setLineEditBackground(self.linkEdit, self.__validInputColor,
                              self.__validInputColor)

    def __setLinkInvalid(self, msg):
        """Sets the link edit invalid"""
        self.linkEdit.setToolTip(msg)
        setLineEditBackground(self.linkEdit, self.__invalidInputColor,
                              self.__invalidInputColor)

    def __validateLink(self):
        """Validates the link field content"""
        txt = self.linkEdit.text().strip()
        if txt == '' or txt.startswith('http://') or txt.startswith(
                'https://'):
            self.__setLinkValid()
            self.createCheckBox.setEnabled(False)
            return True

        if txt.endswith(os.path.sep):
            self.__setLinkInvalid('A link must be a file, not a directory')
            return False

        # Not a link; it is supposed to be a file or a creatable file
        # However the invalid values will also be acceptable
        self.createCheckBox.setEnabled(True)
        fromFile = None
        if self.__fileName:
            if os.path.isabs(self.__fileName):
                fromFile = self.__fileName
        fName, anchor, errMsg = preResolveLinkPath(
            txt, fromFile, self.createCheckBox.isChecked())
        del anchor

        if fName:
            self.__setLinkValid()
            return True

        self.__setLinkInvalid(errMsg)
        return not self.createCheckBox.isChecked()

    def __setAnchorValid(self):
        """Sets the anchor edit valid"""
        self.anchorEdit.setToolTip(
            'Anchor may not contain neither spaces nor tabs')
        setLineEditBackground(self.anchorEdit, self.__invalidInputColor,
                              self.__validInputColor)

    def __setAnchorInvalid(self):
        """Sets the anchor edit invalid"""
        self.anchorEdit.setToolTip(
            'Anchor is used to refer to it from the other files')
        setLineEditBackground(self.anchorEdit, self.__validInputColor,
                              self.__validInputColor)

    def __validateAnchor(self):
        """Validates the anchor field"""
        txt = self.anchorEdit.text().strip()
        if ' ' in txt or '\t' in txt:
            self.__setAnchorValid()
            return False
        self.__setAnchorInvalid()
        return True

    def __validate(self, _=None):
        """Validates the input fields and sets the OK button enable"""
        self.__OKButton.setToolTip('')
        valid = self.__validateAnchor() and self.__validateLink()
        if valid:
            if not self.linkEdit.text().strip() and not self.anchorEdit.text(
            ).strip():
                valid = False
                self.__OKButton.setToolTip(
                    'At least one of the items: link or anchor must be provided'
                )

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

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

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

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

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

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

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

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

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

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

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

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