class PathElement: """Single path element""" def __init__(self, parent=None): self.icon = QLabel() self.icon.setPixmap(getPixmap('nbsep.png')) self.combo = NavBarComboBox(parent)
def __createLayout(self): """Creates the dialog layout""" self.resize(320, 120) self.setSizeGripEnabled(True) pluginVersion = getPluginVersionAndPath(self.__pluginHomeDir) pylintVersion, pylintPath = getPylintVersionAndPath() vboxLayout = QVBoxLayout(self) hboxLayout = QHBoxLayout() iconLabel = QLabel() iconLabel.setPixmap(QPixmap(self.__pluginHomeDir + 'pylint.png')) iconLabel.setScaledContents(True) iconLabel.setFixedSize(48, 48) hboxLayout.addWidget(iconLabel) titleLabel = QLabel('<b>Codimension pylint plugin</b>') titleLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) titleLabel.setFixedHeight(48) titleLabel.setAlignment(Qt.AlignCenter) infoLabel = QLabel('<hr><br>More info:' '<ul>' '<li>Plugin<br>' 'Version: ' + pluginVersion + '<br>' 'Location: ' + self.__pluginHomeDir + '</li>' '<li>Pylint<br>' 'Version: ' + pylintVersion + '<br>' + 'Location: ' + pylintPath + '</li>' '</ul><br>') hboxLayout.addWidget(titleLabel) vboxLayout.addLayout(hboxLayout) vboxLayout.addWidget(infoLabel) self.__buttonBox = QDialogButtonBox(self) self.__buttonBox.setOrientation(Qt.Horizontal) self.__buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__buttonBox.accepted.connect(self.close) self.__buttonBox.rejected.connect(self.close) vboxLayout.addWidget(self.__buttonBox)
def __createLayout(self): """Creates the dialog layout""" self.resize(640, 420) self.setSizeGripEnabled(True) vboxLayout = QVBoxLayout(self) hboxLayout = QHBoxLayout() iconLabel = QLabel() logoPath = os.path.dirname(os.path.abspath(__file__)) + \ os.path.sep + "svn-logo.png" iconLabel.setPixmap(QPixmap(logoPath)) iconLabel.setScaledContents(True) iconLabel.setFixedSize(48, 48) hboxLayout.addWidget(iconLabel) titleLabel = QLabel("Codimension SVN plugin settings") titleLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) titleLabel.setFixedHeight(48) titleLabel.setAlignment(Qt.AlignCenter) hboxLayout.addWidget(titleLabel) vboxLayout.addLayout(hboxLayout) self.__tabWidget = QTabWidget(self) self.__tabWidget.setFocusPolicy(Qt.NoFocus) ideWide = self.__createIDEWide() self.__tabWidget.addTab(ideWide, "IDE Wide") projectSpecific = self.__createProjectSpecific() self.__tabWidget.addTab(projectSpecific, "Project Specific") version = self.__createVersionWidget() self.__tabWidget.addTab(version, "Versions") vboxLayout.addWidget(self.__tabWidget) # 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.addWidget(self.__buttonBox)
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)
class MDTopBar(QFrame): """MD widget top bar at the top""" STATE_OK_UTD = 0 # Parsed OK, MD up to date STATE_OK_CHN = 1 # Parsed OK, MD changed STATE_BROKEN_UTD = 2 # Parsed with errors, MD up to date STATE_BROKEN_CHN = 3 # Parsed with errors, MD changed STATE_UNKNOWN = 4 def __init__(self, parent): QFrame.__init__(self, parent) self.__infoIcon = None self.__warningsIcon = None self.__layout = None self.__createLayout() self.__currentIconState = self.STATE_UNKNOWN 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) def clearWarnings(self): """Clears the warnings""" self.__warningsIcon.setVisible(False) self.__warningsIcon.setToolTip("") def setWarnings(self, warnings): """Sets the warnings""" self.__warningsIcon.setToolTip('Markdown 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('Markdown 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("Markdown render 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("Markdown render 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("Markdown render 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("Markdown render 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("Markdown render state is unknown") self.__currentIconState = self.STATE_UNKNOWN def getCurrentState(self): """Provides the current state""" return self.__currentIconState def resizeEvent(self, event): """Editor has resized""" QFrame.resizeEvent(self, event)
def __createLayout(self, action, title, files): """Creates the dialog layout""" self.resize(400, 300) self.setSizeGripEnabled(True) # Top level layout layout = QVBoxLayout(self) # Pixmap and the message topLayout = QHBoxLayout() pixmap = QLabel() pixmap.setPixmap(getPixmap('warning.png')) topLayout.addWidget(pixmap) hSpacer = QWidget() hSpacer.setFixedSize(15, 15) topLayout.addWidget(hSpacer) message = QLabel("All the project files must be " "saved before start debugging") message.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) message.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) message.setWordWrap(True) topLayout.addWidget(message) layout.addLayout(topLayout) vSpacer = QWidget() vSpacer.setFixedSize(15, 15) layout.addWidget(vSpacer) layout.addWidget(QLabel(title + ":")) filesList = QTreeWidget() filesList.setRootIsDecorated(False) filesList.setAlternatingRowColors(True) filesList.setUniformRowHeights(True) filesList.setItemsExpandable(False) filesList.setItemDelegate(NoOutlineHeightDelegate(4)) filesList.setSelectionMode(QAbstractItemView.NoSelection) filesList.setHeaderHidden(True) for item in files: fileName = item[0] fileItem = QTreeWidgetItem([fileName]) fileType, icon, _ = getFileProperties(fileName) fileItem.setIcon(0, icon) if isPythonMime(fileType): info = GlobalData().briefModinfoCache.get(fileName) fileItem.setToolTip( 0, info.docstring.text if info.docstring else '') filesList.addTopLevelItem(fileItem) layout.addWidget(filesList) # Buttons at the bottom buttonBox = QDialogButtonBox() buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Cancel) continueButton = buttonBox.addButton(action, QDialogButtonBox.ActionRole) continueButton.setDefault(True) layout.addWidget(buttonBox) continueButton.clicked.connect(self.accept) buttonBox.rejected.connect(self.close) continueButton.setFocus()
class NavigationBar(QFrame): """Navigation bar at the top of the editor (python only)""" STATE_OK_UTD = 0 # Parsed OK, context up to date STATE_OK_CHN = 1 # Parsed OK, context changed STATE_BROKEN_UTD = 2 # Parsed with errors, context up to date STATE_BROKEN_CHN = 3 # Parsed with errors, context changed STATE_UNKNOWN = 4 def __init__(self, editor, parent): QFrame.__init__(self, parent) self.__editor = editor self.__parentWidget = parent # It is always not visible at the beginning because there is no # editor content at the start self.setVisible(False) # There is no parser info used to display values self.__currentInfo = None self.__currentIconState = self.STATE_UNKNOWN self.__connected = False # List of PathElement starting after the global scope self.__path = [] self.__createLayout() # Create the update timer self.__updateTimer = QTimer(self) self.__updateTimer.setSingleShot(True) self.__updateTimer.timeout.connect(self.updateBar) # Connect to the change file type signal mainWindow = GlobalData().mainWindow editorsManager = mainWindow.editorsManagerWidget.editorsManager editorsManager.sigFileTypeChanged.connect(self.__onFileTypeChanged) def getEditor(self): """Provides the editor""" return self.__editor 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 __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) def __updateInfoIcon(self, state): """Updates the information icon""" if state != self.__currentIconState: if state == self.STATE_OK_UTD: self.__infoIcon.setPixmap(getPixmap('nbokutd.png')) self.__infoIcon.setToolTip("Context is up to date") self.__currentIconState = self.STATE_OK_UTD elif state == self.STATE_OK_CHN: self.__infoIcon.setPixmap(getPixmap('nbokchn.png')) self.__infoIcon.setToolTip("Context 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('nbbrokenutd.png')) self.__infoIcon.setToolTip("Context might be invalid " "due to invalid python code") self.__currentIconState = self.STATE_BROKEN_UTD else: # STATE_BROKEN_CHN self.__infoIcon.setPixmap(getPixmap('nbbrokenchn.png')) self.__infoIcon.setToolTip("Context might be invalid; " "will be updated on idle") self.__currentIconState = self.STATE_BROKEN_CHN def resizeEvent(self, event): """Editor has resized""" QFrame.resizeEvent(self, event) # Arguments: fileName, uuid, newFileType def __onFileTypeChanged(self, _, uuid, newFileType): """Triggered when a buffer content type has changed""" if self.__parentWidget.getUUID() != uuid: return if isPythonMime(newFileType) and Settings()['showNavigationBar']: # Update the bar and show it self.setVisible(True) self.updateBar() else: self.__disconnectEditorSignals() self.__updateTimer.stop() self.__currentInfo = None self.setVisible(False) self.__currentIconState = self.STATE_UNKNOWN def updateSettings(self): """Called when navigation bar settings have been updated""" textMime = self.__parentWidget.getMime() if Settings()['showNavigationBar'] and isPythonMime(textMime): self.setVisible(True) self.updateBar() else: self.__disconnectEditorSignals() self.__updateTimer.stop() self.__currentInfo = None self.setVisible(False) def updateBar(self): """Triggered when the timer is fired""" self.__updateTimer.stop() # just in case if not isPythonMime(self.__parentWidget.getMime()): return if not self.__connected: self.__connectEditorSignals() # Parse the buffer content self.__currentInfo = getBriefModuleInfoFromMemory(self.__editor.text) # Decide what icon to use if self.__currentInfo.isOK: self.__updateInfoIcon(self.STATE_OK_UTD) else: self.__updateInfoIcon(self.STATE_BROKEN_UTD) # Calc the cursor context context = getContext(self.__editor, self.__currentInfo, True, False) # Display the context self.__populateGlobalScope() if context.length == 0: self.__globalScopeCombo.setCurrentIndex(-1) else: index = self.__globalScopeCombo.findData( context.levels[0][0].line) self.__globalScopeCombo.setCurrentIndex(index) usedFromStore = 0 index = 1 while index < context.length: if len(self.__path) < index: newPathItem = PathElement(self) self.__path.append(newPathItem) self.__layout.addWidget(newPathItem.icon) self.__layout.addWidget(newPathItem.combo) combo = newPathItem.combo combo.pathIndex = len(self.__path) - 1 combo.jumpToLine.connect(self.__onJumpToLine) else: self.__path[index - 1].icon.setVisible(True) self.__path[index - 1].combo.setVisible(True) combo = self.__path[index - 1].combo combo.clear() # Populate the combo box self.__populateClassesAndFunctions(context.levels[index - 1][0], combo) combo.setCurrentIndex(combo.findData(context.levels[index][0].line)) index += 1 usedFromStore += 1 # it might need to have one more level with nothing selected if context.length > 0: if len(context.levels[context.length - 1][0].functions) > 0 or \ len(context.levels[context.length - 1][0].classes) > 0: # Need to add a combo if len(self.__path) <= usedFromStore: newPathItem = PathElement(self) self.__path.append(newPathItem) self.__layout.addWidget(newPathItem.icon) self.__layout.addWidget(newPathItem.combo) combo = newPathItem.combo combo.pathIndex = len(self.__path) - 1 combo.jumpToLine.connect(self.__onJumpToLine) else: self.__path[index - 1].icon.setVisible(True) self.__path[index - 1].combo.setVisible(True) combo = self.__path[index - 1].combo combo.clear() self.__populateClassesAndFunctions( context.levels[context.length - 1][0], combo) combo.setCurrentIndex(-1) usedFromStore += 1 # Hide extra components if so index = usedFromStore while index < len(self.__path): self.__path[index].icon.setVisible(False) self.__path[index].combo.setVisible(False) index += 1 # Make sure the spacer is the last item self.__layout.removeWidget(self.__spacer) self.__layout.addWidget(self.__spacer) def __populateGlobalScope(self): """Repopulates the global scope combo box""" self.__globalScopeCombo.clear() self.__populateClassesAndFunctions(self.__currentInfo, self.__globalScopeCombo) if not Settings()['navbarglobalsimports']: return if len(self.__currentInfo.globals) == 0 and \ len(self.__currentInfo.imports) == 0: return if self.__globalScopeCombo.count() != 0: self.__globalScopeCombo.insertSeparator( self.__globalScopeCombo.count()) for glob in self.__currentInfo.globals: self.__globalScopeCombo.addItem(getIcon('globalvar.png'), glob.name, glob.line) for imp in self.__currentInfo.imports: self.__globalScopeCombo.addItem(getIcon('imports.png'), imp.name, imp.line) @staticmethod def __populateClassesAndFunctions(infoObj, combo): """Populates the combo with classes and functions from the infoObj""" for klass in infoObj.classes: combo.addItem(getIcon('class.png'), klass.name, klass.line) for func in infoObj.functions: if func.isPrivate(): icon = getIcon('method_private.png') elif func.isProtected(): icon = getIcon('method_protected.png') else: icon = getIcon('method.png') combo.addItem(icon, func.name, func.line) def __cursorPositionChanged(self): """Cursor position changed""" self.__onNeedUpdate() def __onBufferChanged(self): """Buffer changed""" self.__onNeedUpdate() def __onNeedUpdate(self): """Triggered to update status icon and to restart the timer""" self.__updateTimer.stop() if self.__currentInfo.isOK: self.__updateInfoIcon(self.STATE_OK_CHN) else: self.__updateInfoIcon(self.STATE_BROKEN_CHN) self.__updateTimer.start(IDLE_TIMEOUT) def __onJumpToLine(self, line): """Triggered when it needs to jump to a line""" self.__editor.gotoLine(line, 0) self.__editor.setFocus() def setFocusToLastCombo(self): """Activates the last combo""" if self.__currentInfo is None: return for index in range(len(self.__path) - 1, -1, -1): if self.__path[index].combo.isVisible(): self.__path[index].combo.setFocus() self.__path[index].combo.showPopup() return self.__globalScopeCombo.setFocus() self.__globalScopeCombo.showPopup() def activateCombo(self, currentCombo, newIndex): """Triggered when a neighbour combo should be activated""" if newIndex == -1: if len(self.__path) > 0: if self.__path[0].combo.isVisible(): currentCombo.hidePopup() self.__globalScopeCombo.setFocus() self.__globalScopeCombo.showPopup() return if newIndex >= len(self.__path): # This is the most right one return if self.__path[newIndex].combo.isVisible(): currentCombo.hidePopup() self.__path[newIndex].combo.setFocus() self.__path[newIndex].combo.showPopup()