def clear(self): """ Deletes all items in the TreeView """ #logging.debug(__name__ + ": clear") self._itemDict = {} self._firstItem = None QTreeWidget.clear(self)
def mousePressEvent(self, event): index = self.indexAt(event.pos()) if index.isValid(): item = self.itemAt(event.pos()) if event.button() == Qt.RightButton: self.copyMenu.popup(QCursor.pos()) QTreeWidget.mousePressEvent(self, event)
def __init__(self, state_index=list()): QTreeWidget.__init__(self) self.header().setHidden(True) self.setSelectionMode(QTreeWidget.SingleSelection) self.setAnimated(True) self._actualProject = None #self._projects -> key: [Item, folderStructure] self._projects = {} self._loading_items = {} self._thread_execution = {} self.__enableCloseNotification = True self._fileWatcher = NinjaFileSystemWatcher self._refresh_projects_queue = [] self._timer_running = False self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.header().setResizeMode(0, QHeaderView.ResizeToContents) self.header().setStretchLastSection(False) self.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self, SIGNAL( "customContextMenuRequested(const QPoint &)"), self._menu_context_tree) self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self._open_file) self.connect(self._fileWatcher, SIGNAL("fileChanged(int, QString)"), self._refresh_project_by_path) self.itemExpanded.connect(self._item_expanded) self.itemCollapsed.connect(self._item_collapsed) self.mute_signals = False self.state_index = list() self._folding_menu = FoldingContextMenu(self)
def songKeyPressEvent(self, event): if event.matches(QKeySequence.Delete): self.__removeSong() elif event.key() == Qt.Key_Escape: self.songList.setCurrentRow(-1) else: QTreeWidget.keyPressEvent(self.songList, event)
def __init__( self, debugger, parent = None ): QTreeWidget.__init__( self, parent ) self.setRootIsDecorated( True ) self.setAlternatingRowColors( True ) self.setUniformRowHeights( True ) self.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.setSelectionBehavior( QAbstractItemView.SelectRows ) self.setHeaderLabels( [ "Name", "Value", "Type" ] ) header = self.header() header.setSortIndicator( 0, Qt.AscendingOrder ) header.setSortIndicatorShown( True ) header.setClickable( True ) header.setStretchLastSection( True ) self.itemExpanded.connect( self.__expandItemSignal ) self.itemCollapsed.connect( self.collapseItem ) self.resortEnabled = True self.openItems = [] self.framenr = 0 self.__debugger = debugger # Ugly filtering support self.__hideMCFFilter = False self.__scopeFilter = 0 # Global and local self.__filterIsSet = False self.__textFilters = [] self.__textFiltersCount = 0 self.setSortingEnabled( True ) return
def mousePressEvent(self, mouseEvent): QTreeWidget.mousePressEvent(self, mouseEvent) # http://doc.qt.nokia.com/4.7-snapshot/dnd.html if mouseEvent.button() != Qt.LeftButton: return if self._selectedExperiment(): self.dragStartPosition = mouseEvent.pos()
def keyPressEvent(self, event): """ Обрабатываем нажатия на кнопки вверх и вниз так, чтобы перескакивать на следующую запись мимо категорий. Запрещаем использование кнопок вправо и влево """ ourEvent = (event.key() == Qt.Key_Down or event.key() == Qt.Key_Up or event.key() == Qt.Key_Left or event.key() == Qt.Key_Right) if not ourEvent: QTreeWidget.keyPressEvent(self, event) return curItem = self.currentItem() if event.key() == Qt.Key_Down: nextItem = self._getNextNonCategoryItem(curItem) if nextItem: self.setCurrentItem(nextItem) elif event.key() == Qt.Key_Up: nextItem = self._getPreviousNonCategoryItem(curItem) if nextItem: self.setCurrentItem(nextItem) elif self.topLevelItemCount() > 0: # Дошли до верха списка и нужно прокрутить до самого верха self.scrollToItem(self.topLevelItem(0))
def __init__(self, parent): QTreeWidget.__init__(self, parent) self.name = "Modules" self.tm = TaskManager() self.loader = loader.loader() self.setupUi(self) self.initTreeModule()
def __init__(self): QTreeWidget.__init__(self) self.header().setHidden(True) self.setSelectionMode(QTreeWidget.SingleSelection) self.setAnimated(True) self._actualProject = None #self._projects -> key: [Item, folderStructure] self._projects = {} self.__enableCloseNotification = True self._fileWatcher = QFileSystemWatcher() self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.header().setResizeMode(0, QHeaderView.ResizeToContents) self.header().setStretchLastSection(False) self.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self, SIGNAL( "customContextMenuRequested(const QPoint &)"), self._menu_context_tree) self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self._open_file) self.connect(self._fileWatcher, SIGNAL("directoryChanged(QString)"), self._refresh_project_by_path)
def __init__( self, parent ): QTreeWidget.__init__( self, parent ) self.pyQGisApp = parent self.canvas = None self.layers = self.getLayerSet() self.bMousePressedFlag = False self.itemBeingMoved = None # QTreeWidget properties self.setSortingEnabled( False ) self.setDragEnabled( False ) self.setAutoScroll( False ) #self.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel ) self.setHeaderHidden( True ) self.setRootIsDecorated( True ) self.setContextMenuPolicy( Qt.CustomContextMenu ) self.connect( self, SIGNAL( "customContextMenuRequested(QPoint)" ), self.showMenu ) self.connect( QgsMapLayerRegistry.instance(), SIGNAL("layerWasAdded(QgsMapLayer *)"), self.addLayerToLegend ) self.connect( QgsMapLayerRegistry.instance(), SIGNAL( "removedAll()" ), self.removeAll ) self.connect( self, SIGNAL( "itemChanged(QTreeWidgetItem *,int)" ), self.updateLayerStatus ) self.connect( self, SIGNAL( "currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)" ), self.currentItemChanged )
def __init__(self): QTreeWidget.__init__(self) self.header().setHidden(True) self.setSelectionMode(self.SingleSelection) self.setAnimated(True) self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.header().setResizeMode(0, QHeaderView.ResizeToContents) self.header().setStretchLastSection(False) self.actualSymbols = ('', {}) self.docstrings = {} self.collapsedItems = {} self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self._go_to_definition) self.connect(self, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self._go_to_definition) self.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self, SIGNAL("customContextMenuRequested(const QPoint &)"), self._menu_context_tree) self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"), self._item_collapsed) self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"), self._item_expanded) IDE.register_service('symbols_explorer', self) ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self)
def keyHandler(self, event): if not self.edit_mode \ and event.key() == Qt.Key_Delete: self.deleteEvent() event.accept() return QTreeWidget.keyPressEvent(self.container, event)
def __init__( self, parent = None ): QTreeWidget.__init__( self, parent ) self.setRootIsDecorated( False ) self.setItemsExpandable( False ) self.setSortingEnabled( True ) self.__headerItem = QTreeWidgetItem( [ "", "File name", "Line", "Description" ] ) self.__headerItem.setIcon( 0, PixmapCache().getIcon("todocompleted.png") ) self.setHeaderItem( self.__headerItem ) self.header().setSortIndicator( 1, Qt.AscendingOrder ) self.__resizeColumns() self.todoItems = [] self.setContextMenuPolicy( Qt.CustomContextMenu ) self.connect( self, SIGNAL( "customContextMenuRequested(const QPoint &)" ), self.__showContextMenu ) self.connect( self, SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ), self.__todoItemActivated ) return
def __init__(self, parent=None, TreeFileName=DefaultTreeFileName): QTreeWidget.__init__(self, parent) self.parent = parent self.setGeometry(0,0, self.parent.width(), self.parent.height()) self.setColumnCount(2) self.setColumnWidth(0,270) #self.header().setStretchLastSection(False) #self.resizeColumnToContents(1) headerTitles = QStringList() headerTitles.append(QString("Parameter")) headerTitles.append(QString("Value")) self.setHeaderLabels(headerTitles) self.setEditTriggers(QTreeWidget.DoubleClicked|QTreeWidget.EditKeyPressed) self.rootItems = [] self.currentItemChanged.connect(self.visit) self.itemDoubleClicked.connect(self.edit_) self.editing = None self.expandAll() self.ScenarioName = '' self.NodeDescriptions = dict() # textual parameter descriptions self.ParamScenario = dict() # name of corresponding scenario for parameters self.changed = False self.ApplicationPath = '' self.TreeFileName = TreeFileName self.RunCfgFileName = DefaultCfgFileName self.load() self.parent.setWindowTitle(self.NodeValue('Title').replace('_',' ') + ' ' + DefaultTtitle)
def __init__(self, controller, parent = None): ''' Constructor - calls parent class constructor ''' QTreeWidget.__init__(self, parent) if parent!=None: self.parentController = parent
def __init__(self,parent = None): QTreeWidget.__init__(self,parent) self.setColumnCount(1) self.setHeaderLabel("Explorer") self.projects = [] self.header().setStretchLastSection(False) self.header().setResizeMode(QHeaderView.ResizeToContents)
def __init__(self,parent = None): QTreeWidget.__init__(self,parent) self.setColumnCount(1) self.header().close() self.header().setStretchLastSection(False) self.header().setResizeMode(QHeaderView.ResizeToContents) self.mainClass = None
def scrollTo( self, index, hint = QAbstractItemView.EnsureVisible ): """ Disables horizontal scrolling when a row is clicked. Found here: http://qt-project.org/faq/answer/how_can_i_disable_autoscroll_when_selecting_a_partially_displayed_column_in """ oldValue = self.horizontalScrollBar().value() QTreeWidget.scrollTo( self, index, hint ) self.horizontalScrollBar().setValue( oldValue ) return
def __init__(self, hide_parent_element = False): """Constructor.""" QTreeWidget.__init__(self) self._content_provider = None self._label_providers = {} # index table to lookup treeview items associated with model objects. self.__indextable = [] self._hide_parent = hide_parent_element
def clear( self ): " Resets everything " self.resortEnabled = True self.openItems = [] self.framenr = 0 QTreeWidget.clear( self ) return
def __init__(self): QTreeWidget.__init__(self) self.setHeaderLabels((self.tr('Description'), self.tr('Shortcut'))) #columns width self.setColumnWidth(0, 175) self.header().setStretchLastSection(True) self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder)
def keyPressEvent( self, event ): " Handles the key press events " if event.key() == Qt.Key_Escape: self.escapePressed.emit() event.accept() else: QTreeWidget.keyPressEvent( self, event ) return
def __init__(self): QTreeWidget.__init__(self) self.setHeaderLabels((self.tr('File'), self.tr('Line'))) self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.header().setResizeMode(0, QHeaderView.ResizeToContents) self.header().setResizeMode(1, QHeaderView.ResizeToContents) self.header().setStretchLastSection(False) self.sortByColumn(0, Qt.AscendingOrder)
def __init__(self, parent): QTreeWidget.__init__(self, parent) self.setItemsExpandable(True) self.setColumnCount(1) self.connect(self, SIGNAL('itemActivated(QTreeWidgetItem*,int)'), self.activated) # Setup context menu self.menu = QMenu(self) self.common_actions = self.setup_common_actions()
def leaveEvent(self, event): " Triggered when the cursor leaves the find results tree " global inside inside = False QApplication.processEvents() hideSearchTooltip() QTreeWidget.leaveEvent(self, event) return
def __init__(self): QTreeWidget.__init__(self) self.setHeaderLabels((translations.TR_PROJECT_DESCRIPTION, translations.TR_SHORTCUT)) #columns width self.setColumnWidth(0, 175) self.header().setStretchLastSection(True) self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder)
def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) else: QTreeWidget.changeEvent(self, event)
def keyPressEvent(self, e): ## if e.key() in [Qt.Key_Escape]: ## self.parent.close() if e.key() in [Qt.Key_F2, Qt.Key_Space]: if self.editing is not None: #print "Error: already editing an item" pass else: self.edit_(self.currentItem(),0) QTreeWidget.keyPressEvent(self,e)
def __init__(self, parent=None): QTreeWidget.__init__(self, parent) self.setWindowTitle('TreeWidget Context Menu') self.header().setHidden(True) self.setGeometry(320, 320, 320, 320) for index in '12345': parent = QTreeWidgetItem(self, ['Parent %s' % index]) for item in 'ABCDE': QTreeWidgetItem(parent, ['Child %s%s' % (index, item)]) parent.setExpanded(True)
def __init__(self, parent=None): QTreeWidget.__init__(self, parent) self.singleOverlaySelection = True self.header().close() self.setSortingEnabled(True) self.installEventFilter(self) self.spacePressed.connect(self.spacePressedTreewidget) self.itemChanged.connect(self.treeItemChanged)
class NetworkArgs(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Network arguments dialog """ def __init__(self, dataArgs, parent=None): """ Dialog to fill arguments for the network probe @param dataArgs: @type dataArgs: @param parent: @type parent: """ super(NetworkArgs, self).__init__(parent) self.dataArgs = dataArgs self.createDialog() self.createConnections() self.loadDefaultData() def createDialog(self): """ Create qt dialog """ mainLayout = QHBoxLayout() paramLayout = QHBoxLayout() paramLayout.addWidget(QLabel("Interface:")) self.intComboBox = QComboBox() self.intComboBox.setEditable(1) self.intComboBox.addItems( ['any', 'eth0', 'eth1', 'eth2', 'eth3', 'eth4', 'lo0']) paramLayout.addWidget(self.intComboBox) paramLayout.addWidget(QLabel("Filter:")) self.filterEdit = QLineEdit() paramLayout.addWidget(self.filterEdit) dataLayout = QVBoxLayout() self.labelHelp = QLabel( "Network interface to dump:\nIf the interface name does not exist in the list\nplease to edit the combox list to change it." ) self.listBox = QTreeWidget(self) self.listBox.setIndentation(0) self.labels = [self.tr("Interface"), self.tr("Filter")] self.listBox.setHeaderLabels(self.labels) dataLayout.addWidget(self.labelHelp) dataLayout.addLayout(paramLayout) dataLayout.addWidget(self.listBox) buttonLayout = QVBoxLayout() self.addButton = QPushButton("Add", self) self.delButton = QPushButton("Remove", self) self.delButton.setEnabled(False) self.editButton = QPushButton("Edit", self) self.editButton.setEnabled(False) self.clearButton = QPushButton("Clear", self) self.okButton = QPushButton("Ok", self) self.cancelButton = QPushButton("Cancel", self) buttonLayout.addWidget(self.addButton) buttonLayout.addWidget(self.delButton) buttonLayout.addWidget(self.editButton) buttonLayout.addWidget(self.clearButton) buttonLayout.addWidget(self.okButton) buttonLayout.addWidget(self.cancelButton) mainLayout.addLayout(dataLayout) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("Network Probe > Arguments") def createConnections(self): """ Create qt connections """ self.okButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject) self.addButton.clicked.connect(self.addItem) self.delButton.clicked.connect(self.delItem) self.editButton.clicked.connect(self.editItem) self.clearButton.clicked.connect(self.clearList) self.listBox.itemClicked.connect(self.onItemSelected) def clearList(self): """ Clear the list """ self.listBox.clear() def onItemSelected(self, itm, row): """ Called when an item is selected """ self.delButton.setEnabled(True) self.editButton.setEnabled(True) def editItem(self): """ Edit item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # retrieve value to put it in the line edit and then remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) eth = selectedItem.dataNet['interface'] flt = selectedItem.dataNet['filter'] self.filterEdit.setText(flt) self.intComboBox.setEditText(eth) model.removeRow(qIndex.row()) def delItem(self): """ Delete item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) model.removeRow(qIndex.row()) def addItem(self): """ Add item """ eth = self.intComboBox.currentText() if eth != '': flt = self.filterEdit.text() tpl = {'interface': str(eth), 'filter': str(flt)} newParam = NetItem(data=tpl, parent=self.listBox) self.listBox.resizeColumnToContents(0) def loadDefaultData(self): """ Load the default data """ try: if len(self.dataArgs) == 0: return datObj = eval(str(self.dataArgs)) if 'interfaces' in datObj: for eth in datObj['interfaces']: newParam = NetItem(data=eth, parent=self.listBox) except Exception as e: self.error("unable to load the default data: %s" % e) def getArgs(self): """ Returns arguments Example list of files: {'interfaces': [ {'interface':'any', 'filter':''} ] } """ listEth = [] # iterate all items in a QListWidget root = self.listBox.invisibleRootItem() child_count = root.childCount() for i in xrange(child_count): itm = root.child(i) listEth.append(eval(str(itm.dataNet))) ret = {'interfaces': listEth} if len(listEth) == 0: ret = '' return str(ret)
class XConsoleEdit(XLoggerWidget): __designer_icon__ = projexui.resources.find('img/ui/console.png') def __init__(self, parent): super(XConsoleEdit, self).__init__(parent) self.setLogger(logging.getLogger()) # create custom properties self._completerTree = None self._commandStack = [] self._highlighter = XConsoleHighlighter(self.document()) # set properties font = QFont('Courier New') font.setPointSize(9) self.setFont(font) self.setReadOnly(False) self.waitForInput() metrics = QFontMetrics(font) self.setTabStopWidth(4 * metrics.width(' ')) # create connections XStream.stdout().messageWritten.connect(self.information) XStream.stderr().messageWritten.connect(self.error) def __del__(self): XStream.stdout().messageWritten.disconnect(self.information) XStream.stderr().messageWritten.disconnect(self.error) def acceptCompletion(self): """ Accepts the current completion and inserts the code into the edit. :return <bool> accepted """ tree = self._completerTree if not tree: return False tree.hide() item = tree.currentItem() if not item: return False # clear the previously typed code for the block cursor = self.textCursor() text = cursor.block().text() col = cursor.columnNumber() end = col while col: col -= 1 if text[col] == '.': col += 1 break # insert the current text cursor.setPosition(cursor.position() - (end - col), cursor.KeepAnchor) cursor.removeSelectedText() self.insertPlainText(item.text(0)) return True def applyCommand(self): """ Applies the current line of code as an interactive python command. """ # grab the command from the current line block = self.textCursor().block().text() match = INPUT_EXPR.match(projex.text.toUtf8(block)) # if there is no command, then wait for the input if not match: self.waitForInput() return self.executeCommand(match.group(2).rstrip(), match.group(1).strip()) def cancelCompletion(self): """ Cancels the current completion. """ if (self._completerTree): self._completerTree.hide() def clear(self): """ Clears the current text and starts a new input line. """ super(XConsoleEdit, self).clear() self.waitForInput() def closeEvent(self, event): """ Disconnects from the stderr/stdout on close. :param event | <QCloseEvent> """ if (self.clearOnClose()): XStream.stdout().messageWritten.disconnect(self.information) XStream.stderr().messageWritten.disconnect(self.error) super(XConsoleEdit, self).closeEvent(event) def completerTree(self): """ Returns the completion tree for this instance. :return <QTreeWidget> """ if (not self._completerTree): self._completerTree = QTreeWidget(self) self._completerTree.setWindowFlags(Qt.Popup) self._completerTree.setAlternatingRowColors(True) self._completerTree.installEventFilter(self) self._completerTree.itemClicked.connect(self.acceptCompletion) self._completerTree.setRootIsDecorated(False) self._completerTree.header().hide() return self._completerTree def eventFilter(self, obj, event): """ Filters particular events for a given QObject through this class. \ Will use this to intercept events to the completer tree widget while \ filtering. :param obj | <QObject> event | <QEvent> :return <bool> consumed """ if (not obj == self._completerTree): return False if (event.type() != event.KeyPress): return False if (event.key() == Qt.Key_Escape): QToolTip.hideText() self.cancelCompletion() return False elif (event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab)): self.acceptCompletion() return False elif (event.key() in (Qt.Key_Up, Qt.Key_Down)): return False else: self.keyPressEvent(event) # update the completer cursor = self.textCursor() text = projex.text.toUtf8(cursor.block().text()) text = text[:cursor.columnNumber()].split(' ')[-1] text = text.split('.')[-1] self._completerTree.blockSignals(True) self._completerTree.setUpdatesEnabled(False) self._completerTree.setCurrentItem(None) for i in range(self._completerTree.topLevelItemCount()): item = self._completerTree.topLevelItem(i) if projex.text.toUtf8(item.text(0)).startswith(text): self._completerTree.setCurrentItem(item) break self._completerTree.blockSignals(False) self._completerTree.setUpdatesEnabled(True) return True def executeCommand(self, command, mode='>>>'): """ Executes the inputed command in the global scope. :param command | <unicode> :return <variant> """ # check to see if we're starting a new line if mode == '...' and not command.strip(): command = '\n'.join(self._commandStack) elif command.endswith(':') or mode == '...': self._commandStack.append(command) self.insertPlainText('\n... ') return # if we're not at the end of the console, then add it to the end elif not self.textCursor().atEnd(): self.waitForInput() self.insertPlainText(command) return self._commandStack = [] # insert a new line self.insertPlainText('\n') cmdresult = None try: cmdresult = eval(command, __main__.__dict__, __main__.__dict__) except SyntaxError: exec(command) in __main__.__dict__, __main__.__dict__ # print the resulting commands if cmdresult != None: self.information(projex.text.toUtf8(cmdresult)) self.waitForInput() def highlighter(self): """ Returns the console highlighter for this widget. :return <XConsoleHighlighter> """ return self._highlighter def gotoHome(self): """ Navigates to the home position for the edit. """ mode = QTextCursor.MoveAnchor # select the home if QApplication.instance().keyboardModifiers() == Qt.ShiftModifier: mode = QTextCursor.KeepAnchor cursor = self.textCursor() block = projex.text.toUtf8(cursor.block().text()) cursor.movePosition(QTextCursor.StartOfBlock, mode) if (block.startswith('>>> ')): cursor.movePosition(QTextCursor.Right, mode, 4) self.setTextCursor(cursor) def keyPressEvent(self, event): """ Overloads the key press event to control keystroke modifications for \ the console widget. :param event | <QKeyEvent> """ # enter || return keys will apply the command if event.key() in (Qt.Key_Return, Qt.Key_Enter): self.applyCommand() # home key will move the cursor to the home position elif event.key() == Qt.Key_Home: self.gotoHome() elif event.key() in (Qt.Key_Backspace, Qt.Key_Delete): super(XConsoleEdit, self).keyPressEvent(event) # update the completer cursor = self.textCursor() text = projex.text.toUtf8(cursor.block().text()) text = text[:cursor.columnNumber()].split(' ')[-1] if not '.' in text: self.cancelCompletion() # period key will trigger a completion popup elif event.key() == Qt.Key_Period: self.startCompletion() super(XConsoleEdit, self).keyPressEvent(event) # space, tab, backspace and delete will cancel the completion elif event.key() == Qt.Key_Space: self.cancelCompletion() super(XConsoleEdit, self).keyPressEvent(event) # left parenthesis will start method help elif event.key() == Qt.Key_ParenLeft: self.cancelCompletion() self.showMethodToolTip() super(XConsoleEdit, self).keyPressEvent(event) # otherwise, handle the event like normal else: super(XConsoleEdit, self).keyPressEvent(event) def objectAtCursor(self): """ Returns the python object that the text is representing. :return <object> || None """ # determine the text block cursor = self.textCursor() text = projex.text.toUtf8(cursor.block().text()) col = cursor.columnNumber() end = col while (col): col -= 1 if (re.match('[^a-zA-Z\._\(\)]', text[col])): break symbol = text[col:end].rstrip('.(') try: return eval(symbol, __main__.__dict__, __main__.__dict__) except: return None def showMethodToolTip(self): """ Pops up a tooltip message with the help for the object under the \ cursor. :return <bool> success """ self.cancelCompletion() obj = self.objectAtCursor() if (not obj): return False docs = inspect.getdoc(obj) if (not docs): return False # determine the cursor position rect = self.cursorRect() cursor = self.textCursor() point = QPoint(rect.left(), rect.top() + 18) QToolTip.showText(self.mapToGlobal(point), docs, self) return True def startCompletion(self): """ Starts a new completion popup for the current object. :return <bool> success """ # add the top level items tree = self.completerTree() tree.clear() # make sure we have a valid object obj = self.objectAtCursor() if (obj is None): return False # determine the cursor position rect = self.cursorRect() cursor = self.textCursor() point = QPoint(rect.left(), rect.top() + 18) try: o_keys = obj.__dir__() except (AttributeError, TypeError): o_keys = dir(obj) keys = [key for key in sorted(o_keys) if not key.startswith('_')] if (not keys): return False for key in keys: tree.addTopLevelItem(QTreeWidgetItem([key])) tree.move(self.mapToGlobal(point)) tree.show() return True def waitForInput(self): """ Inserts a new input command into the console editor. """ if (self.isReadOnly()): return self.moveCursor(QTextCursor.End) if (self.textCursor().block().text() == '>>> '): return # if there is already text on the line, then start a new line newln = '>>> ' if projex.text.toUtf8(self.textCursor().block().text()): newln = '\n' + newln # insert the text self.setCurrentMode('standard') self.insertPlainText(newln) self.scrollToEnd() self._blankCache = ''
class TreeSymbolsWidget(QDialog): """Class of Dialog for Tree Symbols""" def __init__(self, parent=None): super(TreeSymbolsWidget, self).__init__(parent, Qt.WindowStaysOnTopHint) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.tree = QTreeWidget() vbox.addWidget(self.tree) self.tree.header().setHidden(True) self.tree.setSelectionMode(self.tree.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.actualSymbols = ('', {}) self.docstrings = {} self.collapsedItems = {} self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self._go_to_definition) self.connect(self, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self._go_to_definition) self.tree.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self, SIGNAL("customContextMenuRequested(const QPoint &)"), self._menu_context_tree) self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"), self._item_collapsed) self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"), self._item_expanded) IDE.register_service('symbols_explorer', self) ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self) def install_tab(self): """Connect signals for goingdown""" ide = IDE.get_service('ide') self.connect(ide, SIGNAL("goingDown()"), self.close) def _menu_context_tree(self, point): """Context menu""" index = self.tree.indexAt(point) if not index.isValid(): return menu = QMenu(self) f_all = menu.addAction(translations.TR_FOLD_ALL) u_all = menu.addAction(translations.TR_UNFOLD_ALL) menu.addSeparator() u_class = menu.addAction(translations.TR_UNFOLD_CLASSES) u_class_method = menu.addAction( translations.TR_UNFOLD_CLASSES_AND_METHODS) u_class_attr = menu.addAction( translations.TR_UNFOLD_CLASSES_AND_ATTRIBUTES) menu.addSeparator() #save_state = menu.addAction(self.tr("Save State")) self.connect(f_all, SIGNAL("triggered()"), lambda: self.tree.collapseAll()) self.connect(u_all, SIGNAL("triggered()"), lambda: self.tree.expandAll()) self.connect(u_class, SIGNAL("triggered()"), self._unfold_class) self.connect(u_class_method, SIGNAL("triggered()"), self._unfold_class_method) self.connect(u_class_attr, SIGNAL("triggered()"), self._unfold_class_attribute) #self.connect(save_state, SIGNAL("triggered()"), #self._save_symbols_state) menu.exec_(QCursor.pos()) def _get_classes_root(self): """Return the root of classes""" class_root = None for i in range(self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) if item.isClass and not item.isClickable: class_root = item break return class_root def _unfold_class(self): """Method to Unfold Classes""" self.tree.collapseAll() classes_root = self._get_classes_root() if not classes_root: return classes_root.setExpanded(True) def _unfold_class_method(self): """Method to Unfold Methods""" self.tree.expandAll() classes_root = self._get_classes_root() if not classes_root: return #for each class! for i in range(classes_root.childCount()): class_item = classes_root.child(i) #for each attribute or functions for j in range(class_item.childCount()): item = class_item.child(j) #METHODS ROOT!! if not item.isMethod and not item.isClickable: item.setExpanded(False) break def _unfold_class_attribute(self): """Method to Unfold Attributes""" self.tree.expandAll() classes_root = self._get_classes_root() if not classes_root: return #for each class! for i in range(classes_root.childCount()): class_item = classes_root.child(i) #for each attribute or functions for j in range(class_item.childCount()): item = class_item.child(j) #ATTRIBUTES ROOT!! if not item.isAttribute and not item.isClickable: item.setExpanded(False) break def _save_symbols_state(self): """Method to Save a persistent Symbols state""" #filename = self.actualSymbols[0] #TODO: persist self.collapsedItems[filename] in QSettings pass def _get_expand(self, item): """ Returns True or False to be used as setExpanded() with the items It method is based on the click that the user made in the tree """ name = self._get_unique_name(item) filename = self.actualSymbols[0] collapsed_items = self.collapsedItems.get(filename, []) can_check = (not item.isClickable) or item.isClass or item.isMethod if can_check and name in collapsed_items: return False return True @staticmethod def _get_unique_name(item): """ Returns a string used as unique name """ # className_Attributes/className_Functions parent = item.parent() if parent: return "%s_%s" % (parent.text(0), item.text(0)) return "_%s" % item.text(0) def update_symbols_tree(self, symbols, filename='', parent=None): """Method to Update the symbols on the Tree""" TIP = "{} {}" if not parent: if filename == self.actualSymbols[0] and \ self.actualSymbols[1] and not symbols: return if symbols == self.actualSymbols[1]: # Nothing new then return return # we have new symbols refresh it self.tree.clear() self.actualSymbols = (filename, symbols) self.docstrings = symbols.get('docstrings', {}) parent = self.tree if 'attributes' in symbols: globalAttribute = ItemTree(parent, [translations.TR_ATTRIBUTES]) globalAttribute.isClickable = False globalAttribute.isAttribute = True globalAttribute.setExpanded(self._get_expand(globalAttribute)) globalAttribute.setToolTip( 0, TIP.format(len(symbols['attributes']), translations.TR_ATTRIBUTES)) for glob in sorted(symbols['attributes']): globItem = ItemTree(globalAttribute, [glob], lineno=symbols['attributes'][glob]) globItem.isAttribute = True globItem.setIcon(0, QIcon(":img/attribute")) globItem.setExpanded(self._get_expand(globItem)) if 'functions' in symbols and symbols['functions']: functionsItem = ItemTree(parent, [translations.TR_FUNCTIONS]) functionsItem.isClickable = False functionsItem.isMethod = True functionsItem.setExpanded(self._get_expand(functionsItem)) functionsItem.setToolTip( 0, TIP.format(len(symbols['functions']), translations.TR_FUNCTIONS)) for func in sorted(symbols['functions']): item = ItemTree(functionsItem, [func], lineno=symbols['functions'][func]['lineno']) tooltip = self.create_tooltip( func, symbols['functions'][func]['lineno']) item.isMethod = True item.setIcon(0, QIcon(":img/function")) item.setToolTip(0, tooltip) item.setExpanded(self._get_expand(item)) self.update_symbols_tree( symbols['functions'][func]['functions'], parent=item) if 'classes' in symbols and symbols['classes']: classItem = ItemTree(parent, [translations.TR_CLASSES]) classItem.isClickable = False classItem.isClass = True classItem.setExpanded(self._get_expand(classItem)) classItem.setToolTip( 0, TIP.format(len(symbols['classes']), translations.TR_CLASSES)) for claz in sorted(symbols['classes']): line_number = symbols['classes'][claz]['lineno'] item = ItemTree(classItem, [claz], lineno=line_number) item.isClass = True tooltip = self.create_tooltip(claz, line_number) item.setToolTip(0, tooltip) item.setIcon(0, QIcon(":img/class")) item.setExpanded(self._get_expand(item)) self.update_symbols_tree(symbols['classes'][claz]['members'], parent=item) def _go_to_definition(self, item): """Takes and item object and goes to definition on the editor""" main_container = IDE.get_service('main_container') if item.isClickable and main_container: main_container.editor_go_to_line(item.lineno - 1) def create_tooltip(self, name, lineno): """Takes a name and line number and returns a tooltip""" doc = self.docstrings.get(lineno, None) if doc is None: doc = '' else: doc = '\n' + doc tooltip = name + doc return tooltip def _item_collapsed(self, item): """When item collapsed""" super(TreeSymbolsWidget, self).collapseItem(item) can_check = (not item.isClickable) or item.isClass or item.isMethod if can_check: n = self._get_unique_name(item) filename = self.actualSymbols[0] self.collapsedItems.setdefault(filename, []) if not n in self.collapsedItems[filename]: self.collapsedItems[filename].append(n) def _item_expanded(self, item): """When item expanded""" super(TreeSymbolsWidget, self).expandItem(item) n = self._get_unique_name(item) filename = self.actualSymbols[0] if n in self.collapsedItems.get(filename, []): self.collapsedItems[filename].remove(n) if not len(self.collapsedItems[filename]): # no more items, free space del self.collapsedItems[filename] def clean(self): """ Reset the tree and reset attributes """ self.tree.clear() self.collapsedItems = {} def reject(self): if self.parent() is None: self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) def closeEvent(self, event): """On Close event handling""" self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore()
class PluginWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.pluginMetadata = {} # Main layout self.mainLayout = QVBoxLayout() self.setLayout(self.mainLayout) # Define size used for the underlines self.underlineSize = QSize() self.underlineSize.setHeight(1) # Define font used for headers self.font = QFont() self.font.setPointSize(11) self.font.setBold(True) self.font.setUnderline(True) # Plugins Description self.pluginDescription = QLabel() self.pluginDescription.setText( "Click a plugin to see more information." + " Plugins can be configured from the Recording tab. \n") self.pluginDescription.setWordWrap(True) # Plugins GroupBox self.pluginLayout = QVBoxLayout() self.pluginGroupBox = QGroupBox( "Plugins extend the functionality of Freeseer") self.pluginGroupBox.setLayout(self.pluginLayout) self.pluginLayout.insertWidget(0, self.pluginDescription) self.mainLayout.insertWidget(0, self.pluginGroupBox) # Plugins list self.list = QTreeWidget() self.list.setHeaderHidden(True) self.list.headerItem().setText(0, "1") self.pluginLayout.insertWidget(1, self.list) # Details self.detailPane = QGroupBox() self.detailLayout = QVBoxLayout() self.detailPane.setLayout(self.detailLayout) self.detailPaneDesc = QLabel() self.detailPaneDesc.setWordWrap(True) self.detailLayout.addWidget(self.detailPaneDesc) self.pluginLayout.insertWidget(2, self.detailPane) self.list.itemSelectionChanged.connect(self.treeViewSelect) def treeViewSelect(self): item = self.list.currentItem() key = str(item.text(0)) if key in self.pluginMetadata.keys(): self.showDetails(key) else: self.hideDetails() def showDetails(self, key): self.detailPane.setTitle(key) self.detailPaneDesc.setText(self.pluginMetadata[key]) self.detailPane.show() def hideDetails(self): self.detailPane.hide() def getWidgetPlugin(self, plugin, plugin_category, plugman): plugin_name = plugin.plugin_object.get_name() item = QTreeWidgetItem() # Display Plugin's meta data in a tooltip pluginDetails = """ <table> <tr> <td>Name: </td> <td><b>%(name)s</b></td> </tr> <tr> <td>Version: </td> <td><b>%(version)s</b></td> <tr> <td>Author: </td> <td><b>%(author)s</b></td> </tr> <tr> <td>Website: </td> <td><b>%(website)s</b></td> </tr> <tr> <td>Description: </td> <td><b>%(description)s</b></td> </tr> </table> """ % { "name": plugin.name, "version": plugin.version, "author": plugin.author, "website": plugin.website, "description": plugin.description } # put the details in the hash table self.pluginMetadata[plugin_name] = pluginDetails item.setText(0, plugin_name) return item
class AddToProject(QDialog): def __init__(self, pathProjects, parent=None): #pathProjects must be a list QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Add File to Project")) self.pathSelected = '' vbox = QVBoxLayout(self) self._tree = QTreeWidget() self._tree.header().setHidden(True) self._tree.setSelectionMode(QTreeWidget.SingleSelection) self._tree.setAnimated(True) vbox.addWidget(self._tree) hbox = QHBoxLayout() btnAdd = QPushButton(self.tr("Add here!")) btnCancel = QPushButton(self.tr("Cancel")) hbox.addWidget(btnCancel) hbox.addWidget(btnAdd) vbox.addLayout(hbox) #load folders self._root = None self._loading_items = {} self.loading_projects(pathProjects) self._thread_execution = ThreadExecution(self._thread_load_projects, args=[pathProjects]) self.connect(self._thread_execution, SIGNAL("finished()"), self._callback_load_project) self._thread_execution.start() self.connect(btnCancel, SIGNAL("clicked()"), self.close) self.connect(btnAdd, SIGNAL("clicked()"), self._select_path) def loading_projects(self, projects): for project in projects: loadingItem = LoadingItem() item = loadingItem.add_item_to_tree(project, self._tree, parent=self) self._loading_items[project] = item def _thread_load_projects(self, projects): structures = [] for pathProject in projects: folderStructure = file_manager.open_project(pathProject) structures.append((folderStructure, pathProject)) self._thread_execution.storage_values = structures def _callback_load_project(self): structures = self._thread_execution.storage_values for structure, path in structures: item = self._loading_items.pop(path, None) if item is not None: index = self._tree.indexOfTopLevelItem(item) self._tree.takeTopLevelItem(index) self._load_project(structure, path) def _select_path(self): item = self._tree.currentItem() if item: self.pathSelected = unicode(item.toolTip(0)) self.close() def _load_project(self, folderStructure, folder): if not folder: return name = file_manager.get_basename(folder) item = QTreeWidgetItem(self._tree) item.setText(0, name) item.setToolTip(0, folder) item.setIcon(0, QIcon(resources.IMAGES['tree-folder'])) if folderStructure[folder][1] is not None: folderStructure[folder][1].sort() self._load_folder(folderStructure, folder, item) item.setExpanded(True) self._root = item def _load_folder(self, folderStructure, folder, parentItem): items = folderStructure[folder] if items[1] is not None: items[1].sort() for _file in items[1]: if _file.startswith('.'): continue subfolder = QTreeWidgetItem(parentItem) subfolder.setText(0, _file) subfolder.setToolTip(0, os.path.join(folder, _file)) subfolder.setIcon(0, QIcon(resources.IMAGES['tree-folder'])) self._load_folder(folderStructure, os.path.join(folder, _file), subfolder)
class StepKwMultiClassifications(WizardStep, FORM_CLASS): """InaSAFE Wizard Step Multi Classifications.""" def __init__(self, parent=None): """Constructor for the tab. :param parent: widget to use as parent (Wizard Dialog). :type parent: QWidget """ WizardStep.__init__(self, parent) self.exposures = [] self.exposure_labels = [] self.exposure_combo_boxes = [] self.exposure_edit_buttons = [] self.mode = CHOOSE_MODE self.layer_purpose = None self.layer_mode = None # Store the current representative state of the UI. # self.classifications = {} self.value_maps = {} self.thresholds = {} # Temporary attributes self.threshold_classes = OrderedDict() self.active_exposure = None self.list_unique_values = None self.tree_mapping_widget = None # GUI, good for testing self.save_button = None # Has default threshold # Trick for EQ raster for population #3853 self.use_default_thresholds = False # Index of the special case exposure classification self.special_case_index = None def is_ready_to_next_step(self): """Check if the step is complete. :returns: True if new step may be enabled. :rtype: bool """ # Still editing if self.mode == EDIT_MODE: return False for combo_box in self.exposure_combo_boxes: # Enable if there is one that has classification if combo_box.currentIndex() > 0: return True # Trick for EQ raster for population #3853 if self.use_default_thresholds: return True return False def get_next_step(self): """Find the proper step when user clicks the Next button. :returns: The step to be switched to. :rtype: WizardStep instance or None """ if self.layer_purpose != layer_purpose_aggregation: subcategory = self.parent.step_kw_subcategory.\ selected_subcategory() else: subcategory = {'key': None} if is_raster_layer(self.parent.layer): return self.parent.step_kw_source # Check if it can go to inasafe field step inasafe_fields = get_non_compulsory_fields(self.layer_purpose['key'], subcategory['key']) if not skip_inasafe_field(self.parent.layer, inasafe_fields): return self.parent.step_kw_inasafe_fields # Check if it can go to inasafe default field step default_inasafe_fields = get_fields(self.layer_purpose['key'], subcategory['key'], replace_null=True, in_group=False) if default_inasafe_fields: return self.parent.step_kw_default_inasafe_fields # Any other case return self.parent.step_kw_source def set_wizard_step_description(self): """Set the text for description.""" subcategory = self.parent.step_kw_subcategory.selected_subcategory() field = self.parent.step_kw_field.selected_fields() is_raster = is_raster_layer(self.parent.layer) if is_raster: if self.layer_mode == layer_mode_continuous: text_label = multiple_continuous_hazard_classifications_raster else: text_label = multiple_classified_hazard_classifications_raster # noinspection PyAugmentAssignment text_label = text_label % (subcategory['name'], self.layer_purpose['name']) else: if self.layer_mode == layer_mode_continuous: text_label = multiple_continuous_hazard_classifications_vector else: text_label = multiple_classified_hazard_classifications_vector # noinspection PyAugmentAssignment text_label = text_label % (subcategory['name'], self.layer_purpose['name'], field) self.multi_classifications_label.setText(text_label) def setup_left_panel(self): """Setup the UI for left panel. Generate all exposure, combobox, and edit button. """ hazard = self.parent.step_kw_subcategory.selected_subcategory() left_panel_heading = QLabel(tr('Classifications')) left_panel_heading.setFont(big_font) self.left_layout.addWidget(left_panel_heading) inner_left_layout = QGridLayout() row = 0 for exposure in exposure_all: special_case = False # Filter out unsupported exposure for the hazard if exposure in hazard['disabled_exposures']: # Remove from the storage if the exposure is disabled if self.layer_mode == layer_mode_continuous: if exposure['key'] in self.thresholds: self.thresholds.pop(exposure['key']) else: if exposure['key'] in self.value_maps: self.value_maps.pop(exposure['key']) continue # Trick for EQ raster for population #3853 if exposure == exposure_population and hazard == hazard_earthquake: if is_raster_layer(self.parent.layer): if self.layer_mode == layer_mode_continuous: self.use_default_thresholds = True special_case = True # Set classification for EQ Raster for Population self.thresholds[exposure_population['key']] = { earthquake_mmi_scale['key']: { 'classes': default_classification_thresholds( earthquake_mmi_scale), 'active': True } } # Add label # Hazard on Exposure Classifications label = tr( '{hazard_name} on {exposure_name} Classifications').format( hazard_name=hazard['name'], exposure_name=exposure['name']) exposure_label = QLabel(label) # Add combo box exposure_combo_box = QComboBox() hazard_classifications = hazard.get('classifications') exposure_combo_box.addItem(tr('No classifications')) exposure_combo_box.setItemData(0, None, Qt.UserRole) current_index = 0 i = 0 # Iterate through all available hazard classifications for hazard_classification in hazard_classifications: # Skip if the classification is not for the exposure if 'exposures' in hazard_classification: if exposure not in hazard_classification['exposures']: continue exposure_combo_box.addItem(hazard_classification['name']) exposure_combo_box.setItemData(i + 1, hazard_classification, Qt.UserRole) if self.layer_mode == layer_mode_continuous: current_hazard_classifications = self.thresholds.get( exposure['key']) else: current_hazard_classifications = self.value_maps.get( exposure['key']) if current_hazard_classifications: current_hazard_classification = \ current_hazard_classifications.get( hazard_classification['key']) if current_hazard_classification: is_active = current_hazard_classification.get('active') if is_active: current_index = i + 1 i += 1 # Set current classification exposure_combo_box.setCurrentIndex(current_index) # Add edit button exposure_edit_button = QPushButton(tr('Edit')) # For special case. Raster EQ on Population. if special_case: mmi_index = exposure_combo_box.findText( earthquake_mmi_scale['name']) exposure_combo_box.setCurrentIndex(mmi_index) exposure_combo_box.setEnabled(False) exposure_edit_button.setEnabled(False) tool_tip_message = tr( 'InaSAFE use default classification for Raster Earthquake ' 'hazard on population.') exposure_label.setToolTip(tool_tip_message) exposure_combo_box.setToolTip(tool_tip_message) exposure_edit_button.setToolTip(tool_tip_message) else: if current_index == 0: # Disable if there is no classification chosen. exposure_edit_button.setEnabled(False) exposure_edit_button.clicked.connect( partial(self.edit_button_clicked, edit_button=exposure_edit_button, exposure_combo_box=exposure_combo_box, exposure=exposure)) exposure_combo_box.currentIndexChanged.connect( partial(self.classifications_combo_box_changed, exposure=exposure, exposure_combo_box=exposure_combo_box, edit_button=exposure_edit_button)) # Arrange in layout inner_left_layout.addWidget(exposure_label, row, 0) inner_left_layout.addWidget(exposure_combo_box, row, 1) inner_left_layout.addWidget(exposure_edit_button, row, 2) # Adding to step's attribute self.exposures.append(exposure) self.exposure_combo_boxes.append(exposure_combo_box) self.exposure_edit_buttons.append(exposure_edit_button) self.exposure_labels.append(label) if special_case: self.special_case_index = len(self.exposures) - 1 row += 1 self.left_layout.addLayout(inner_left_layout) # To push the inner_left_layout up self.left_layout.addStretch(1) # noinspection PyUnusedLocal def edit_button_clicked(self, edit_button, exposure_combo_box, exposure): """Method to handle when an edit button is clicked. :param edit_button: The edit button. :type edit_button: QPushButton :param exposure_combo_box: The combo box of the exposure, contains list of classifications. :type exposure_combo_box: QComboBox :param exposure: Exposure definition. :type exposure: dict """ # Note(IS): Do not change the text of edit button for now until we # have better behaviour. classification = self.get_classification(exposure_combo_box) if self.mode == CHOOSE_MODE: # Change mode self.mode = EDIT_MODE # Set active exposure self.active_exposure = exposure # Disable all edit button for exposure_edit_button in self.exposure_edit_buttons: exposure_edit_button.setEnabled(False) # Except one that was clicked # edit_button.setEnabled(True) # Disable all combo box for exposure_combo_box in self.exposure_combo_boxes: exposure_combo_box.setEnabled(False) # Change the edit button to cancel # edit_button.setText(tr('Cancel')) # Clear right panel clear_layout(self.right_layout) # Show edit threshold or value mapping if self.layer_mode == layer_mode_continuous: self.setup_thresholds_panel(classification) else: self.setup_value_mapping_panels(classification) self.add_buttons(classification) elif self.mode == EDIT_MODE: # Behave the same as cancel button clicked. self.cancel_button_clicked() self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) def show_current_state(self): """Setup the UI for QTextEdit to show the current state.""" right_panel_heading = QLabel(tr('Status')) right_panel_heading.setFont(big_font) right_panel_heading.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.right_layout.addWidget(right_panel_heading) message = m.Message() if self.layer_mode == layer_mode_continuous: title = tr('Thresholds') else: title = tr('Value maps') message.add(m.Heading(title, **INFO_STYLE)) for i in range(len(self.exposures)): message.add(m.Text(self.exposure_labels[i])) classification = self.get_classification( self.exposure_combo_boxes[i]) if self.layer_mode == layer_mode_continuous: thresholds = self.thresholds.get(self.exposures[i]['key']) if not thresholds or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Minimum'))) header.add(m.Cell(tr('Maximum'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: threshold = thresholds[classification['key']]['classes'][ the_class['key']] row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(threshold[0])) row.add(m.Cell(threshold[1])) table.add(row) else: value_maps = self.value_maps.get(self.exposures[i]['key']) if not value_maps or not classification: message.add(m.Paragraph(tr('No classifications set.'))) continue table = m.Table( style_class='table table-condensed table-striped') header = m.Row() header.add(m.Cell(tr('Class name'))) header.add(m.Cell(tr('Value'))) table.add(header) classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda k: k['value']) for the_class in classes: value_map = value_maps[ classification['key']]['classes'].get( the_class['key'], []) row = m.Row() row.add(m.Cell(the_class['name'])) row.add(m.Cell(', '.join([str(v) for v in value_map]))) table.add(row) message.add(table) # status_text_edit = QTextBrowser(None) status_text_edit = QWebView(None) status_text_edit.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) status_text_edit.page().mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff) html_string = html_header() + message.to_html() + html_footer() status_text_edit.setHtml(html_string) self.right_layout.addWidget(status_text_edit) def set_widgets(self): """Set widgets on the Multi classification step.""" self.clear() self.layer_mode = self.parent.step_kw_layermode.selected_layermode() self.layer_purpose = self.parent.step_kw_purpose.selected_purpose() self.set_current_state() # Set the step description self.set_wizard_step_description() # Set the left panel self.setup_left_panel() # Set the right panel, for the beginning show the viewer self.show_current_state() def clear(self): """Clear current state.""" self.exposures = [] self.exposure_labels = [] self.exposure_combo_boxes = [] self.exposure_edit_buttons = [] self.mode = CHOOSE_MODE self.layer_purpose = None self.layer_mode = None self.special_case_index = None self.value_maps = {} self.thresholds = {} # Temporary attributes self.threshold_classes = OrderedDict() self.active_exposure = None self.list_unique_values = None self.tree_mapping_widget = None clear_layout(self.left_layout) clear_layout(self.right_layout) def get_current_state(self): """Obtain current classification and value map / threshold.""" def clean_state(dictionary): """Clean dictionary from bad value. :param dictionary: Dictionary of value maps or thresholds. :type dictionary: dict :returns: Clean state. :rtype: dict """ clean_dictionary = { k: v for k, v in dictionary.items() if isinstance(v, dict) } return clean_dictionary if self.layer_mode == layer_mode_continuous: output = {'thresholds': clean_state(self.thresholds)} key = 'thresholds' else: output = {'value_maps': clean_state(self.value_maps)} key = 'value_maps' # Clean non existing hazard class key empty_exposure_classifications = [] for the_exposure, the_hazard_classifications in output[key].items(): for the_hazard_classification in the_hazard_classifications.\ keys(): invalid_classifications = [] if not definition(the_hazard_classification): invalid_classifications.append(the_hazard_classification) for invalid_classification in invalid_classifications: the_hazard_classifications.pop(invalid_classification) if not the_hazard_classifications: empty_exposure_classifications.append(the_exposure) for empty_exposure_classification in empty_exposure_classifications: output[key].pop(empty_exposure_classification) return output @staticmethod def get_classification(combo_box): """Helper to obtain the classification from a combo box. :param combo_box: A classification combo box. :type combo_box: QComboBox. :returns: Classification definitions. :rtype: dict """ return combo_box.itemData(combo_box.currentIndex(), Qt.UserRole) def setup_thresholds_panel(self, classification): """Setup threshold panel in the right panel. :param classification: Classification definition. :type classification: dict """ # Set text in the label layer_purpose = self.parent.step_kw_purpose.selected_purpose() layer_subcategory = self.parent.step_kw_subcategory.\ selected_subcategory() if is_raster_layer(self.parent.layer): statistics = self.parent.layer.dataProvider().bandStatistics( 1, QgsRasterBandStats.All, self.parent.layer.extent(), 0) description_text = continuous_raster_question % ( layer_purpose['name'], layer_subcategory['name'], classification['name'], statistics.minimumValue, statistics.maximumValue) else: field_name = self.parent.step_kw_field.selected_fields() field_index = self.parent.layer.fieldNameIndex(field_name) min_value_layer = self.parent.layer.minimumValue(field_index) max_value_layer = self.parent.layer.maximumValue(field_index) description_text = continuous_vector_question % ( layer_purpose['name'], layer_subcategory['name'], field_name, classification['name'], min_value_layer, max_value_layer) # Set description description_label = QLabel(description_text) description_label.setWordWrap(True) self.right_layout.addWidget(description_label) if self.thresholds: thresholds = self.thresholds else: thresholds = self.parent.get_existing_keyword('thresholds') selected_unit = self.parent.step_kw_unit.selected_unit()['key'] self.threshold_classes = OrderedDict() classes = classification.get('classes') # Sort by value, put the lowest first classes = sorted(classes, key=lambda the_key: the_key['value']) grid_layout_thresholds = QGridLayout() for i, the_class in enumerate(classes): class_layout = QHBoxLayout() # Class label class_label = QLabel(the_class['name']) # Min label min_label = QLabel(tr('Min >')) # Min value as double spin min_value_input = QDoubleSpinBox() # TODO(IS) We can set the min and max depends on the unit, later min_value_input.setMinimum(0) min_value_input.setMaximum(999999) if thresholds.get(self.active_exposure['key']): exposure_thresholds = thresholds.get( self.active_exposure['key']) if exposure_thresholds.get(classification['key']): exposure_thresholds_classifications = exposure_thresholds\ .get(classification['key']) min_value_input.setValue( exposure_thresholds_classifications['classes'][ the_class['key']][0]) else: default_min = the_class['numeric_default_min'] if isinstance(default_min, dict): default_min = the_class['numeric_default_min'][ selected_unit] min_value_input.setValue(default_min) else: default_min = the_class['numeric_default_min'] if isinstance(default_min, dict): default_min = the_class['numeric_default_min'][ selected_unit] min_value_input.setValue(default_min) min_value_input.setSingleStep(0.1) # Max label max_label = QLabel(tr('Max <=')) # Max value as double spin max_value_input = QDoubleSpinBox() # TODO(IS) We can set the min and max depends on the unit, later max_value_input.setMinimum(0) max_value_input.setMaximum(999999) if thresholds.get(self.active_exposure['key']): exposure_thresholds = thresholds.get( self.active_exposure['key']) if exposure_thresholds.get(classification['key']): exposure_thresholds_classifications = exposure_thresholds \ .get(classification['key']) max_value_input.setValue( exposure_thresholds_classifications['classes'][ the_class['key']][1]) else: default_max = the_class['numeric_default_max'] if isinstance(default_max, dict): default_max = the_class['numeric_default_max'][ selected_unit] max_value_input.setValue(default_max) else: default_max = the_class['numeric_default_max'] if isinstance(default_max, dict): default_max = the_class['numeric_default_max'][ selected_unit] max_value_input.setValue(default_max) max_value_input.setSingleStep(0.1) # Add to class_layout class_layout.addWidget(min_label) class_layout.addWidget(min_value_input) class_layout.addWidget(max_label) class_layout.addWidget(max_value_input) class_layout.setStretch(0, 1) class_layout.setStretch(1, 2) class_layout.setStretch(2, 1) class_layout.setStretch(3, 2) # Add to grid_layout grid_layout_thresholds.addWidget(class_label, i, 0) grid_layout_thresholds.addLayout(class_layout, i, 1) self.threshold_classes[the_class['key']] = [ min_value_input, max_value_input ] grid_layout_thresholds.setColumnStretch(0, 1) grid_layout_thresholds.setColumnStretch(0, 2) def min_max_changed(double_spin_index, mode): """Slot when min or max value change. :param double_spin_index: The index of the double spin. :type double_spin_index: int :param mode: The flag to indicate the min or max value. :type mode: int """ if mode == MAX_VALUE_MODE: current_max_value = self.threshold_classes.values( )[double_spin_index][1] target_min_value = self.threshold_classes.values()[ double_spin_index + 1][0] if current_max_value.value() != target_min_value.value(): target_min_value.setValue(current_max_value.value()) elif mode == MIN_VALUE_MODE: current_min_value = self.threshold_classes.values( )[double_spin_index][0] target_max_value = self.threshold_classes.values()[ double_spin_index - 1][1] if current_min_value.value() != target_max_value.value(): target_max_value.setValue(current_min_value.value()) # Set behaviour for k, v in self.threshold_classes.items(): index = self.threshold_classes.keys().index(k) if index < len(self.threshold_classes) - 1: # Max value changed v[1].valueChanged.connect( partial(min_max_changed, double_spin_index=index, mode=MAX_VALUE_MODE)) if index > 0: # Min value v[0].valueChanged.connect( partial(min_max_changed, double_spin_index=index, mode=MIN_VALUE_MODE)) grid_layout_thresholds.setSpacing(0) self.right_layout.addLayout(grid_layout_thresholds) def add_buttons(self, classification): """Helper to setup 3 buttons. :param classification: The current classification. :type classification: dict """ # Note(IS): Until we have good behaviour, we will disable load # default and cancel button. # Add 3 buttons: Load default, Cancel, Save # load_default_button = QPushButton(tr('Load Default')) # cancel_button = QPushButton(tr('Cancel')) self.save_button = QPushButton(tr('Save')) # Action for buttons # cancel_button.clicked.connect(self.cancel_button_clicked) self.save_button.clicked.connect( partial(self.save_button_clicked, classification=classification)) button_layout = QHBoxLayout() # button_layout.addWidget(load_default_button) button_layout.addStretch(1) # button_layout.addWidget(cancel_button) button_layout.addWidget(self.save_button) button_layout.setStretch(0, 3) button_layout.setStretch(1, 1) # button_layout.setStretch(2, 1) # button_layout.setStretch(3, 1) self.right_layout.addLayout(button_layout) def setup_value_mapping_panels(self, classification): """Setup value mapping panel in the right panel. :param classification: Classification definition. :type classification: dict """ # Set text in the label layer_purpose = self.parent.step_kw_purpose.selected_purpose() layer_subcategory = self.parent.step_kw_subcategory. \ selected_subcategory() if is_raster_layer(self.parent.layer): description_text = classify_raster_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name']) dataset = gdal.Open(self.parent.layer.source(), GA_ReadOnly) active_band = self.parent.step_kw_band_selector.selected_band() unique_values = numpy.unique( numpy.array(dataset.GetRasterBand(active_band).ReadAsArray())) field_type = 0 # Convert datatype to a json serializable type if numpy.issubdtype(unique_values.dtype, float): unique_values = [float(i) for i in unique_values] else: unique_values = [int(i) for i in unique_values] else: field = self.parent.step_kw_field.selected_fields() field_index = self.parent.layer.dataProvider().fields(). \ indexFromName(field) field_type = self.parent.layer.dataProvider(). \ fields()[field_index].type() description_text = classify_vector_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name'], field.upper()) unique_values = self.parent.layer.uniqueValues(field_index) # Set description description_label = QLabel(description_text) description_label.setWordWrap(True) self.right_layout.addWidget(description_label) self.list_unique_values = QListWidget() self.list_unique_values.setDragDropMode(QAbstractItemView.DragDrop) self.list_unique_values.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget = QTreeWidget() self.tree_mapping_widget.setDragDropMode(QAbstractItemView.DragDrop) self.tree_mapping_widget.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget.header().hide() self.tree_mapping_widget.itemChanged.connect( self.update_dragged_item_flags) value_mapping_layout = QHBoxLayout() value_mapping_layout.addWidget(self.list_unique_values) value_mapping_layout.addWidget(self.tree_mapping_widget) self.right_layout.addLayout(value_mapping_layout) default_classes = classification['classes'] # Assign unique values to classes (according to default) unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance(unique_value, QPyNullVariant): # Don't classify features with NULL value continue # Capitalization of the value and removing '_' (raw OSM data). value_as_string = unicode(unique_value).upper().replace('_', ' ') assigned = False for default_class in default_classes: if 'string_defaults' in default_class: condition_1 = (field_type > 9 and value_as_string in [ c.upper() for c in default_class['string_defaults'] ]) else: condition_1 = False condition_2 = ( field_type < 10 and 'numeric_default_min' in default_class and 'numeric_default_max' in default_class and (default_class['numeric_default_min'] <= unique_value < default_class['numeric_default_max'])) if condition_1 or condition_2: assigned_values[default_class['key']] += [unique_value] assigned = True if not assigned: # add to unassigned values list otherwise unassigned_values += [unique_value] self.populate_classified_values(unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget) # Current value map for exposure and classification available_classifications = self.value_maps.get( self.active_exposure['key']) if not available_classifications: return # Get active one current_classification = available_classifications.get( classification['key']) if not current_classification: return current_value_map = current_classification.get('classes') if not current_value_map: return unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance(unique_value, QPyNullVariant): # Don't classify features with NULL value continue # check in value map assigned = False for key, value_list in current_value_map.items(): if unique_value in value_list and key in assigned_values: assigned_values[key] += [unique_value] assigned = True if not assigned: unassigned_values += [unique_value] self.populate_classified_values(unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget) # noinspection PyMethodMayBeStatic def update_dragged_item_flags(self, item): """Fix the drop flag after the item is dropped. Check if it looks like an item dragged from QListWidget to QTreeWidget and disable the drop flag. For some reasons the flag is set when dragging. :param item: Item which is dragged. :type item: QTreeWidgetItem .. note:: This is a slot executed when the item change. """ if int(item.flags() & Qt.ItemIsDropEnabled) \ and int(item.flags() & Qt.ItemIsDragEnabled): item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled) @staticmethod def populate_classified_values(unassigned_values, assigned_values, default_classes, list_unique_values, tree_mapping_widget): """Populate lstUniqueValues and treeClasses.from the parameters. :param unassigned_values: List of values that haven't been assigned to a class. It will be put in list_unique_values. :type unassigned_values: list :param assigned_values: Dictionary with class as the key and list of value as the value of the dictionary. It will be put in tree_mapping_widget. :type assigned_values: dict :param default_classes: Default classes from unit. :type default_classes: list :param list_unique_values: List Widget for unique values :type list_unique_values: QListWidget :param tree_mapping_widget: Tree Widget for classifying. :type tree_mapping_widget: QTreeWidget """ # Populate the unique values list list_unique_values.clear() list_unique_values.setSelectionMode( QAbstractItemView.ExtendedSelection) for value in unassigned_values: value_as_string = value is not None and unicode(value) or 'NULL' list_item = QListWidgetItem(list_unique_values) list_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) list_item.setData(Qt.UserRole, value) list_item.setText(value_as_string) list_unique_values.addItem(list_item) # Populate assigned values tree tree_mapping_widget.clear() bold_font = QFont() bold_font.setItalic(True) bold_font.setBold(True) bold_font.setWeight(75) tree_mapping_widget.invisibleRootItem().setFlags(Qt.ItemIsEnabled) for default_class in default_classes: # Create branch for class tree_branch = QTreeWidgetItem(tree_mapping_widget) tree_branch.setFlags(Qt.ItemIsDropEnabled | Qt.ItemIsEnabled) tree_branch.setExpanded(True) tree_branch.setFont(0, bold_font) if 'name' in default_class: default_class_name = default_class['name'] else: default_class_name = default_class['key'] tree_branch.setText(0, default_class_name) tree_branch.setData(0, Qt.UserRole, default_class['key']) if 'description' in default_class: tree_branch.setToolTip(0, default_class['description']) # Assign known values for value in assigned_values[default_class['key']]: string_value = value is not None and unicode(value) or 'NULL' tree_leaf = QTreeWidgetItem(tree_branch) tree_leaf.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) tree_leaf.setData(0, Qt.UserRole, value) tree_leaf.setText(0, string_value) def cancel_button_clicked(self): """Action for cancel button clicked.""" # Change mode self.mode = CHOOSE_MODE # Enable all edit buttons and combo boxes for i in range(len(self.exposures)): if i == self.special_case_index: self.exposure_edit_buttons[i].setEnabled(False) self.exposure_combo_boxes[i].setEnabled(False) continue if self.get_classification(self.exposure_combo_boxes[i]): self.exposure_edit_buttons[i].setEnabled(True) else: self.exposure_edit_buttons[i].setEnabled(False) # self.exposure_edit_buttons[i].setText(tr('Edit')) self.exposure_combo_boxes[i].setEnabled(True) # Clear right panel clear_layout(self.right_layout) # Show current state self.show_current_state() # Unset active exposure self.active_exposure = None self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) def save_button_clicked(self, classification): """Action for save button clicked. :param classification: The classification that being edited. :type classification: dict """ # Save current edit if self.layer_mode == layer_mode_continuous: thresholds = self.get_threshold() classification_class = {'classes': thresholds, 'active': True} if self.thresholds.get(self.active_exposure['key']): # Set other class to not active for current_classification in self.thresholds.get( self.active_exposure['key']).values(): current_classification['active'] = False else: self.thresholds[self.active_exposure['key']] = {} self.thresholds[self.active_exposure['key']][ classification['key']] = classification_class else: value_maps = self.get_value_map() classification_class = {'classes': value_maps, 'active': True} if self.value_maps.get(self.active_exposure['key']): # Set other class to not active for current_classification in self.value_maps.get( self.active_exposure['key']).values(): current_classification['active'] = False else: self.value_maps[self.active_exposure['key']] = {} self.value_maps[self.active_exposure['key']][ classification['key']] = classification_class # Back to choose mode self.cancel_button_clicked() def get_threshold(self): """Return threshold based on current state.""" value_map = dict() for key, value in self.threshold_classes.items(): value_map[key] = [ value[0].value(), value[1].value(), ] return value_map def get_value_map(self): """Obtain the value-to-class mapping set by user. :returns: The complete mapping as a dict of lists. :rtype: dict """ value_map = {} tree_clone = self.tree_mapping_widget.invisibleRootItem().clone() for tree_branch in tree_clone.takeChildren(): value_list = [] for tree_leaf in tree_branch.takeChildren(): value_list += [tree_leaf.data(0, Qt.UserRole)] if value_list: value_map[tree_branch.data(0, Qt.UserRole)] = value_list return value_map def set_current_state(self): """"Helper to set the state of the step from current keywords.""" if not self.thresholds: self.thresholds = self.parent.get_existing_keyword('thresholds') if not self.value_maps: self.value_maps = self.parent.get_existing_keyword('value_maps') def classifications_combo_box_changed(self, index, exposure, exposure_combo_box, edit_button): """Action when classification combo box changed. :param index: The index of the combo box. :type index: int :param exposure: The exposure associated with the combo box. :type exposure: dict :param exposure_combo_box: Combo box for the classification. :type exposure_combo_box: QComboBox :param edit_button: The edit button associate with combo box. :type edit_button: QPushButton """ # Disable button if it's no classification edit_button.setEnabled(bool(index)) classification = self.get_classification(exposure_combo_box) self.activate_classification(exposure, classification) clear_layout(self.right_layout) self.show_current_state() self.parent.pbnNext.setEnabled(self.is_ready_to_next_step()) # Open edit panel directly edit_button.click() def activate_classification(self, exposure, classification=None): """Set active to True for classification for the exposure. If classification = None, all classification set active = False. :param exposure: Exposure definition. :type exposure: dict :param classification: Classification definition. :type classification: dict """ if self.layer_mode == layer_mode_continuous: selected_unit = self.parent.step_kw_unit.selected_unit()['key'] target = self.thresholds.get(exposure['key']) if target is None: self.thresholds[exposure['key']] = {} target = self.thresholds.get(exposure['key']) else: selected_unit = None target = self.value_maps.get(exposure['key']) if target is None: self.value_maps[exposure['key']] = {} target = self.value_maps.get(exposure['key']) if classification is not None: if classification['key'] not in target: if self.layer_mode == layer_mode_continuous: default_classes = default_classification_thresholds( classification, selected_unit) target[classification['key']] = { 'classes': default_classes, 'active': True } else: default_classes = default_classification_value_maps( classification) target[classification['key']] = { 'classes': default_classes, 'active': True } return for classification_key, value in target.items(): if classification is None: value['active'] = False continue if classification_key == classification['key']: value['active'] = True else: value['active'] = False @property def step_name(self): """Get the human friendly name for the wizard step. :returns: The name of the wizard step. :rtype: str """ return tr('Multi Classification Step') def help_content(self): """Return the content of help for this step wizard. We only needs to re-implement this method in each wizard step. :returns: A message object contains help. :rtype: m.Message """ message = m.Message() message.add( m.Paragraph( tr('In this wizard step: {step_name}, you will be able to set the ' 'classification that you will use per exposure type. You can also ' 'set the threshold or value map for each classification.'). format(step_name=self.step_name))) return message
def setup_value_mapping_panels(self, classification): """Setup value mapping panel in the right panel. :param classification: Classification definition. :type classification: dict """ # Set text in the label layer_purpose = self.parent.step_kw_purpose.selected_purpose() layer_subcategory = self.parent.step_kw_subcategory. \ selected_subcategory() if is_raster_layer(self.parent.layer): description_text = classify_raster_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name']) dataset = gdal.Open(self.parent.layer.source(), GA_ReadOnly) active_band = self.parent.step_kw_band_selector.selected_band() unique_values = numpy.unique( numpy.array(dataset.GetRasterBand(active_band).ReadAsArray())) field_type = 0 # Convert datatype to a json serializable type if numpy.issubdtype(unique_values.dtype, float): unique_values = [float(i) for i in unique_values] else: unique_values = [int(i) for i in unique_values] else: field = self.parent.step_kw_field.selected_fields() field_index = self.parent.layer.dataProvider().fields(). \ indexFromName(field) field_type = self.parent.layer.dataProvider(). \ fields()[field_index].type() description_text = classify_vector_question % ( layer_subcategory['name'], layer_purpose['name'], classification['name'], field.upper()) unique_values = self.parent.layer.uniqueValues(field_index) # Set description description_label = QLabel(description_text) description_label.setWordWrap(True) self.right_layout.addWidget(description_label) self.list_unique_values = QListWidget() self.list_unique_values.setDragDropMode(QAbstractItemView.DragDrop) self.list_unique_values.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget = QTreeWidget() self.tree_mapping_widget.setDragDropMode(QAbstractItemView.DragDrop) self.tree_mapping_widget.setDefaultDropAction(Qt.MoveAction) self.tree_mapping_widget.header().hide() self.tree_mapping_widget.itemChanged.connect( self.update_dragged_item_flags) value_mapping_layout = QHBoxLayout() value_mapping_layout.addWidget(self.list_unique_values) value_mapping_layout.addWidget(self.tree_mapping_widget) self.right_layout.addLayout(value_mapping_layout) default_classes = classification['classes'] # Assign unique values to classes (according to default) unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance(unique_value, QPyNullVariant): # Don't classify features with NULL value continue # Capitalization of the value and removing '_' (raw OSM data). value_as_string = unicode(unique_value).upper().replace('_', ' ') assigned = False for default_class in default_classes: if 'string_defaults' in default_class: condition_1 = (field_type > 9 and value_as_string in [ c.upper() for c in default_class['string_defaults'] ]) else: condition_1 = False condition_2 = ( field_type < 10 and 'numeric_default_min' in default_class and 'numeric_default_max' in default_class and (default_class['numeric_default_min'] <= unique_value < default_class['numeric_default_max'])) if condition_1 or condition_2: assigned_values[default_class['key']] += [unique_value] assigned = True if not assigned: # add to unassigned values list otherwise unassigned_values += [unique_value] self.populate_classified_values(unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget) # Current value map for exposure and classification available_classifications = self.value_maps.get( self.active_exposure['key']) if not available_classifications: return # Get active one current_classification = available_classifications.get( classification['key']) if not current_classification: return current_value_map = current_classification.get('classes') if not current_value_map: return unassigned_values = list() assigned_values = dict() for default_class in default_classes: assigned_values[default_class['key']] = list() for unique_value in unique_values: if unique_value is None or isinstance(unique_value, QPyNullVariant): # Don't classify features with NULL value continue # check in value map assigned = False for key, value_list in current_value_map.items(): if unique_value in value_list and key in assigned_values: assigned_values[key] += [unique_value] assigned = True if not assigned: unassigned_values += [unique_value] self.populate_classified_values(unassigned_values, assigned_values, default_classes, self.list_unique_values, self.tree_mapping_widget)
def mousePressEvent(self, event): if event.button() == Qt.RightButton: return else: QTreeWidget.mousePressEvent(self, event)
class GmApp(QMainWindow): def __init__(self): super(QMainWindow, self).__init__() self.setWindowTitle("GuloMail by GulonSoft") self.setWindowIcon(QIcon("g-square.png")) self.createActions() self.createStatusBar() self.createMenus() self.createToolbars() self.createWidgets() self.createLayouts() def createActions(self): self.newAction = QAction("&New", self, shortcut=QKeySequence.New, statusTip="New") self.sendReceiveAction = QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive") self.printAction = QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print") self.quitAction = QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) self.copyAction = QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy) self.deleteAction = QAction("&Delete", self, statusTip="Delete Message") self.nextAction = QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message") self.previousAction = QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message") self.replyAction = QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply) self.replyToAllAction = QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll) self.forwardAction = QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward") self.junkAction = QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk") self.notJunkAction = QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk") self.contentsAction = QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents) self.aboutAction = QAction("&About", self, statusTip="About GuloMail", triggered=self.about) self.cancelAction = QAction("&Cancel", self, statusTip="Cancel") def createStatusBar(self): self.statusBar() def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.sendReceiveAction) self.fileMenu.addAction(self.printAction) self.fileMenu.addAction(self.quitAction) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.deleteAction) self.viewMenu = self.menuBar().addMenu("&View") self.folderMenu = self.menuBar().addMenu("F&older") self.messageMenu = self.menuBar().addMenu("&Message") self.goToMenu = self.messageMenu.addMenu("&Go To") self.goToMenu.addAction(self.nextAction) self.goToMenu.addAction(self.previousAction) self.messageMenu.addAction(self.replyAction) self.messageMenu.addAction(self.replyToAllAction) self.messageMenu.addAction(self.forwardAction) self.markAsMenu = self.messageMenu.addMenu("Mar&k as...") self.markAsMenu.addAction(self.junkAction) self.markAsMenu.addAction(self.notJunkAction) self.searchMenu = self.menuBar().addMenu("&Search") self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.contentsAction) self.helpMenu.addAction(self.aboutAction) def createToolbars(self): self.toolbar = self.addToolBar('Main Toolbar') self.toolbar.setMovable(False) self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.sendReceiveAction) self.toolbar.addSeparator() self.toolbar.addAction(self.replyAction) self.toolbar.addAction(self.replyToAllAction) self.toolbar.addAction(self.forwardAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addAction(self.deleteAction) self.toolbar.addAction(self.junkAction) self.toolbar.addAction(self.notJunkAction) self.toolbar.addAction(self.cancelAction) self.toolbar.addSeparator() self.toolbar.addAction(self.previousAction) self.toolbar.addAction(self.nextAction) def createWidgets(self): ## Message Table self.table = QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag = 0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree = QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem = QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox = QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems = QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts = QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk = QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox = QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent = QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit = QTextEdit() self.textEdit2 = QTextEdit() def createLayouts(self): self.mainSplitter = QSplitter() self.setCentralWidget(self.mainSplitter) self.mainSplitter.addWidget(self.folderTree) self.messageSplitter = QSplitter(Qt.Vertical) self.messageSplitter.addWidget(self.table) self.messageSplitter.addWidget(self.textEdit2) self.mainSplitter.addWidget(self.messageSplitter) def helpContents(self): print "Help" def reply(self): print "Reply" def replyToAll(self): print "Reply To All" def about(self): text = QString("GuloMail v0.1\n\n") text.append( "GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n" ) text.append(QChar(0x00A9)) text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/") QMessageBox.about(self, "About GuloMail", text)
def __init__(self, *args, **kwargs): super(ShortcutManagerDlg, self).__init__(*args, **kwargs) self.setWindowTitle("Shortcut Preferences") self.setMinimumWidth(500) self.setMinimumHeight(500) mgr = ShortcutManager() # Singleton scrollWidget = QWidget(parent=self) tempLayout = QVBoxLayout(scrollWidget) scrollWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) treeWidget = QTreeWidget(parent=scrollWidget) treeWidget.setHeaderLabels(["Action", "Shortcut"]) treeWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) treeWidget.setColumnWidth(0, 300) treeWidget.setColumnWidth(1, 50) # Create a LineEdit for each shortcut, # and keep track of them in a dict shortcutEdits = collections.OrderedDict() for group, shortcutDict in mgr.shortcuts.items(): groupItem = QTreeWidgetItem(treeWidget, QStringList(group)) ListOfActions = set() for i, (shortcut, (desc, obj)) in enumerate(shortcutDict.items()): if desc in ListOfActions: continue edit = QLineEdit(str(shortcut.key().toString())) shortcutEdits[shortcut] = edit item = QTreeWidgetItem(groupItem, QStringList(desc)) item.setText(0, desc) ListOfActions.add(desc) treeWidget.setItemWidget(item, 1, edit) tempLayout.addWidget(treeWidget) # Add ok and cancel buttons buttonLayout = QHBoxLayout() cancelButton = QPushButton("Cancel") cancelButton.clicked.connect(self.reject) okButton = QPushButton("OK") okButton.clicked.connect(self.accept) okButton.setDefault(True) buttonLayout.addSpacerItem(QSpacerItem(10, 0, QSizePolicy.Expanding)) buttonLayout.addWidget(cancelButton) buttonLayout.addWidget(okButton) tempLayout.addLayout(buttonLayout) scroll = QScrollArea(parent=self) scroll.setWidget(scrollWidget) scroll.setWidgetResizable(True) scroll.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) dlgLayout = QVBoxLayout() dlgLayout.addWidget(scroll) self.setLayout(dlgLayout) # Show the window result = self.exec_() # If the user didn't hit "cancel", apply his changes to the manager's shortcuts if result == QDialog.Accepted: for shortcut, edit in shortcutEdits.items(): oldKey = str(shortcut.key().toString()).lower() newKey = str(edit.text()).lower() if oldKey != newKey and newKey != "": # Before we add this shortcut to our dict, disable any other shortcuts it replaces conflicting_shortcuts = mgr._findExistingShortcuts(newKey) for conflicted in conflicting_shortcuts: conflicted.setKey(QKeySequence("")) shortcutEdits[conflicted].setText("") shortcut.setKey(QKeySequence(newKey)) # Make sure the tooltips get updated. mgr.updateToolTip(shortcut) mgr.storeToPreferences()
def createWidgets(self): ## Message Table self.table = QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag = 0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree = QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem = QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox = QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems = QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts = QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk = QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox = QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent = QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit = QTextEdit() self.textEdit2 = QTextEdit()
def __init__(self, parent=None, signalManager=None, name="KEGG Pathways"): OWWidget.__init__(self, parent, signalManager, name, wantGraph=True) self.inputs = [("Examples", Orange.data.Table, self.SetData), ("Reference", Orange.data.Table, self.SetRefData)] self.outputs = [("Selected Examples", Orange.data.Table), ("Unselected Examples", Orange.data.Table)] self.organismIndex = 0 self.geneAttrIndex = 0 self.autoCommit = False self.autoResize = True self.useReference = False self.useAttrNames = 0 self.showOrthology = True self.loadSettings() self.organismCodes = [] self._changedFlag = False self.controlArea.setMaximumWidth(250) box = OWGUI.widgetBox(self.controlArea, "Info") self.infoLabel = OWGUI.widgetLabel(box, "No data on input\n") # Organism selection. box = OWGUI.widgetBox(self.controlArea, "Organism") self.organismComboBox = OWGUI.comboBox( box, self, "organismIndex", items=[], callback=self.Update, addSpace=True, debuggingEnabled=0, tooltip="Select the organism of the input genes") # Selection of genes attribute box = OWGUI.widgetBox(self.controlArea, "Gene attribute") self.geneAttrCandidates = VariableListModel(parent=self) self.geneAttrCombo = OWGUI.comboBox( box, self, "geneAttrIndex", callback=self.Update) self.geneAttrCombo.setModel(self.geneAttrCandidates) OWGUI.checkBox(box, self, "useAttrNames", "Use variable names", disables=[(-1, self.geneAttrCombo)], callback=self.Update) self.geneAttrCombo.setDisabled(bool(self.useAttrNames)) OWGUI.separator(self.controlArea) OWGUI.checkBox(self.controlArea, self, "useReference", "From signal", box="Reference", callback=self.Update) OWGUI.separator(self.controlArea) OWGUI.checkBox(self.controlArea, self, "showOrthology", "Show pathways in full orthology", box="Orthology", callback=self.UpdateListView) OWGUI.checkBox(self.controlArea, self, "autoResize", "Resize to fit", box="Image", callback=self.UpdatePathwayViewTransform) box = OWGUI.widgetBox(self.controlArea, "Cache Control") OWGUI.button(box, self, "Clear cache", callback=self.ClearCache, tooltip="Clear all locally cached KEGG data.") OWGUI.separator(self.controlArea) box = OWGUI.widgetBox(self.controlArea, "Selection") cb = OWGUI.checkBox(box, self, "autoCommit", "Commit on update") button = OWGUI.button(box, self, "Commit", callback=self.Commit, default=True) OWGUI.setStopper(self, button, cb, "_changedFlag", self.Commit) OWGUI.rubber(self.controlArea) spliter = QSplitter(Qt.Vertical, self.mainArea) self.pathwayView = PathwayView(self, spliter) self.pathwayView.scene().selectionChanged.connect( self._onSelectionChanged ) self.mainArea.layout().addWidget(spliter) self.listView = QTreeWidget(spliter) spliter.addWidget(self.listView) self.listView.setAllColumnsShowFocus(1) self.listView.setColumnCount(4) self.listView.setHeaderLabels(["Pathway", "P value", "Genes", "Reference"]) self.listView.setSelectionMode(QTreeWidget.SingleSelection) self.listView.setSortingEnabled(True) self.listView.setMaximumHeight(200) self.connect(self.listView, SIGNAL("itemSelectionChanged()"), self.UpdatePathwayView) self.connect(self.graphButton, SIGNAL("clicked()"), self.saveGraph) select = QAction( "Select All", self, shortcut=QKeySequence.SelectAll ) select.triggered.connect(self.selectAll) self.addAction(select) self.data = None self.refData = None self.resize(800, 600) self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.onStateChange) self.has_new_data = False self.has_new_reference_set = False self._executor = ThreadExecutor() self.setEnabled(False) self.setBlocking(True) QTimer.singleShot(0, self._initialize) self.infoLabel.setText("Fetching organism definitions\n")
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(PixmapCache().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 = detectFileType(fileName) fileItem.setIcon(0, getFileIcon(fileType)) if fileType in [PythonFileType, Python3FileType]: infoSrc = GlobalData().briefModinfoCache info = infoSrc.get(fileName) if info.docstring is not None: fileItem.setToolTip(0, info.docstring.text) else: fileItem.setToolTip(0, "") 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() return
class OWKEGGPathwayBrowser(OWWidget): settingsList = ["organismIndex", "geneAttrIndex", "autoCommit", "autoResize", "useReference", "useAttrNames", "showOrthology"] contextHandlers = { "": DomainContextHandler( "", [ContextField("organismIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes), ContextField("geneAttrIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes), ContextField("useAttrNames", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes)] ) } def __init__(self, parent=None, signalManager=None, name="KEGG Pathways"): OWWidget.__init__(self, parent, signalManager, name, wantGraph=True) self.inputs = [("Examples", Orange.data.Table, self.SetData), ("Reference", Orange.data.Table, self.SetRefData)] self.outputs = [("Selected Examples", Orange.data.Table), ("Unselected Examples", Orange.data.Table)] self.organismIndex = 0 self.geneAttrIndex = 0 self.autoCommit = False self.autoResize = True self.useReference = False self.useAttrNames = 0 self.showOrthology = True self.loadSettings() self.organismCodes = [] self._changedFlag = False self.controlArea.setMaximumWidth(250) box = OWGUI.widgetBox(self.controlArea, "Info") self.infoLabel = OWGUI.widgetLabel(box, "No data on input\n") # Organism selection. box = OWGUI.widgetBox(self.controlArea, "Organism") self.organismComboBox = OWGUI.comboBox( box, self, "organismIndex", items=[], callback=self.Update, addSpace=True, debuggingEnabled=0, tooltip="Select the organism of the input genes") # Selection of genes attribute box = OWGUI.widgetBox(self.controlArea, "Gene attribute") self.geneAttrCandidates = VariableListModel(parent=self) self.geneAttrCombo = OWGUI.comboBox( box, self, "geneAttrIndex", callback=self.Update) self.geneAttrCombo.setModel(self.geneAttrCandidates) OWGUI.checkBox(box, self, "useAttrNames", "Use variable names", disables=[(-1, self.geneAttrCombo)], callback=self.Update) self.geneAttrCombo.setDisabled(bool(self.useAttrNames)) OWGUI.separator(self.controlArea) OWGUI.checkBox(self.controlArea, self, "useReference", "From signal", box="Reference", callback=self.Update) OWGUI.separator(self.controlArea) OWGUI.checkBox(self.controlArea, self, "showOrthology", "Show pathways in full orthology", box="Orthology", callback=self.UpdateListView) OWGUI.checkBox(self.controlArea, self, "autoResize", "Resize to fit", box="Image", callback=self.UpdatePathwayViewTransform) box = OWGUI.widgetBox(self.controlArea, "Cache Control") OWGUI.button(box, self, "Clear cache", callback=self.ClearCache, tooltip="Clear all locally cached KEGG data.") OWGUI.separator(self.controlArea) box = OWGUI.widgetBox(self.controlArea, "Selection") cb = OWGUI.checkBox(box, self, "autoCommit", "Commit on update") button = OWGUI.button(box, self, "Commit", callback=self.Commit, default=True) OWGUI.setStopper(self, button, cb, "_changedFlag", self.Commit) OWGUI.rubber(self.controlArea) spliter = QSplitter(Qt.Vertical, self.mainArea) self.pathwayView = PathwayView(self, spliter) self.pathwayView.scene().selectionChanged.connect( self._onSelectionChanged ) self.mainArea.layout().addWidget(spliter) self.listView = QTreeWidget(spliter) spliter.addWidget(self.listView) self.listView.setAllColumnsShowFocus(1) self.listView.setColumnCount(4) self.listView.setHeaderLabels(["Pathway", "P value", "Genes", "Reference"]) self.listView.setSelectionMode(QTreeWidget.SingleSelection) self.listView.setSortingEnabled(True) self.listView.setMaximumHeight(200) self.connect(self.listView, SIGNAL("itemSelectionChanged()"), self.UpdatePathwayView) self.connect(self.graphButton, SIGNAL("clicked()"), self.saveGraph) select = QAction( "Select All", self, shortcut=QKeySequence.SelectAll ) select.triggered.connect(self.selectAll) self.addAction(select) self.data = None self.refData = None self.resize(800, 600) self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.onStateChange) self.has_new_data = False self.has_new_reference_set = False self._executor = ThreadExecutor() self.setEnabled(False) self.setBlocking(True) QTimer.singleShot(0, self._initialize) self.infoLabel.setText("Fetching organism definitions\n") def _initialize(self): # First try to import slumber to see if we can even use the # kegg module. try: import slumber except ImportError: QMessageBox.warning(self, "'slumber' library required.", '<p>Please install ' '<a href="http://pypi.python.org/pypi/slumber">slumber</a> ' 'library to use KEGG Pathways widget.</p>' ) self.infoLabel.setText( '<p>Please install ' '<a href="http://pypi.python.org/pypi/slumber">slumber</a> ' 'library to use KEGG Pathways widget.</p>' ) self.error(0, "Missing slumber/requests library") return progress = methodinvoke(self, "setProgress", (float,)) def get_genome(): """Return a KEGGGenome with the common org entries precached.""" genome = kegg.KEGGGenome() essential = genome.essential_organisms() common = genome.common_organisms() # Remove duplicates of essential from common. # (essential + common list as defined here will be used in the # GUI.) common = [c for c in common if c not in essential] # TODO: Add option to specify additional organisms not # in the common list. keys = map(genome.org_code_to_entry_key, essential + common) genome.pre_cache(keys, progress_callback=progress) return (keys, genome) self._genomeTask = task = Task(function=get_genome) task.finished.connect(self._initializeOrganisms) self.progressBarInit() self._executor.submit(task) def _initializeOrganisms(self): self.progressBarFinished() try: keys, genome = self._genomeTask.result() except Exception as err: self.error(0, str(err)) return entries = [genome[key] for key in keys] items = [entry.definition for entry in entries] codes = [entry.organism_code for entry in entries] self.organismCodes = codes self.organismComboBox.clear() self.organismComboBox.addItems(items) self.organismComboBox.setCurrentIndex(self.organismIndex) self.setEnabled(True) self.setBlocking(False) self.infoLabel.setText("No data on input\n") def Clear(self): """ Clear the widget state. """ self.queryGenes = [] self.referenceGenes = [] self.genes = {} self.uniqueGenesDict = {} self.revUniqueGenesDict = {} self.pathways = {} self.org = None self.geneAttrCandidates[:] = [] self.infoLabel.setText("No data on input\n") self.listView.clear() self.pathwayView.SetPathway(None) self.send("Selected Examples", None) self.send("Unselected Examples", None) def SetData(self, data=None): self.closeContext() self.data = data self.warning(0) self.error(0) self.information(0) if data is not None: vars = data.domain.variables + data.domain.getmetas().values() vars = [var for var in vars if isinstance(var, (Orange.feature.String, Orange.feature.Discrete))] self.geneAttrCandidates[:] = vars # Try to guess the gene name variable names_lower = [v.name.lower() for v in vars] scores = [(name == "gene", "gene" in name) for name in names_lower] imax, _ = max(enumerate(scores), key=itemgetter(1)) self.geneAttrIndex = imax taxid = data_hints.get_hint(data, "taxid", None) if taxid: try: code = kegg.from_taxid(taxid) self.organismIndex = self.organismCodes.index(code) except Exception as ex: print ex, taxid self.useAttrNames = data_hints.get_hint(data, "genesinrows", self.useAttrNames) self.openContext("", data) else: self.Clear() self.has_new_data = True def SetRefData(self, data=None): self.refData = data self.information(1) self.has_new_reference_set = True def handleNewSignals(self): if self.has_new_data or (self.has_new_reference_set and \ self.useReference): self.Update() self.has_new_data = False self.has_new_reference_set = False def UpdateListView(self): self.bestPValueItem = None self.listView.clear() if not self.data: return allPathways = self.org.pathways() allRefPathways = kegg.pathways("map") items = [] kegg_pathways = kegg.KEGGPathways() org_code = self.organismCodes[min(self.organismIndex, len(self.organismCodes) - 1)] if self.showOrthology: self.koOrthology = kegg.KEGGBrite("ko00001") self.listView.setRootIsDecorated(True) path_ids = set([s[-5:] for s in self.pathways.keys()]) def _walkCollect(koEntry): num = koEntry.title[:5] if koEntry.title else None if num in path_ids: return ([koEntry] + reduce(lambda li, c: li + _walkCollect(c), [child for child in koEntry.entries], [])) else: c = reduce(lambda li, c: li + _walkCollect(c), [child for child in koEntry.entries], []) return c + (c and [koEntry] or []) allClasses = reduce(lambda li1, li2: li1 + li2, [_walkCollect(c) for c in self.koOrthology], []) def _walkCreate(koEntry, lvItem): item = QTreeWidgetItem(lvItem) id = "path:" + org_code + koEntry.title[:5] if koEntry.title[:5] in path_ids: p = kegg_pathways.get_entry(id) if p is None: # In case the genesets still have obsolete entries name = koEntry.title else: name = p.name genes, p_value, ref = self.pathways[id] item.setText(0, name) item.setText(1, "%.5f" % p_value) item.setText(2, "%i of %i" % (len(genes), len(self.genes))) item.setText(3, "%i of %i" % (ref, len(self.referenceGenes))) item.pathway_id = id if p is not None else None else: if id in allPathways: text = kegg_pathways.get_entry(id).name else: text = koEntry.title item.setText(0, text) if id in allPathways: item.pathway_id = id elif "path:map" + koEntry.title[:5] in allRefPathways: item.pathway_id = "path:map" + koEntry.title[:5] else: item.pathway_id = None for child in koEntry.entries: if child in allClasses: _walkCreate(child, item) for koEntry in self.koOrthology: if koEntry in allClasses: _walkCreate(koEntry, self.listView) self.listView.update() else: self.listView.setRootIsDecorated(False) pathways = self.pathways.items() pathways.sort(lambda a, b: cmp(a[1][1], b[1][1])) for id, (genes, p_value, ref) in pathways: item = QTreeWidgetItem(self.listView) item.setText(0, kegg_pathways.get_entry(id).name) item.setText(1, "%.5f" % p_value) item.setText(2, "%i of %i" % (len(genes), len(self.genes))) item.setText(3, "%i of %i" % (ref, len(self.referenceGenes))) item.pathway_id = id items.append(item) self.bestPValueItem = items and items[0] or None self.listView.expandAll() for i in range(4): self.listView.resizeColumnToContents(i) if self.bestPValueItem: index = self.listView.indexFromItem(self.bestPValueItem) self.listView.selectionModel().select( index, QItemSelectionModel.ClearAndSelect ) def UpdatePathwayView(self): items = self.listView.selectedItems() if len(items) > 0: item = items[0] else: item = None self.Commit() item = item or self.bestPValueItem if not item or not item.pathway_id: self.pathwayView.SetPathway(None) return def get_kgml_and_image(pathway_id): """Return an initialized KEGGPathway with pre-cached data""" p = kegg.KEGGPathway(pathway_id) p._get_kgml() # makes sure the kgml file is downloaded p._get_image_filename() # makes sure the image is downloaded return (pathway_id, p) self.setEnabled(False) self._pathwayTask = Task( function=lambda: get_kgml_and_image(item.pathway_id) ) self._pathwayTask.finished.connect(self._onPathwayTaskFinshed) self._executor.submit(self._pathwayTask) def _onPathwayTaskFinshed(self): self.setEnabled(True) pathway_id, self.pathway = self._pathwayTask.result() self.pathwayView.SetPathway( self.pathway, self.pathways.get(pathway_id, [[]])[0] ) def UpdatePathwayViewTransform(self): self.pathwayView.updateTransform() def Update(self): """ Update (recompute enriched pathways) the widget state. """ if not self.data: return self.error(0) self.information(0) # XXX: Check data in setData, do not even alow this to be executed if # data has no genes try: genes = self.GeneNamesFromData(self.data) except ValueError: self.error(0, "Cannot extract gene names from input.") genes = [] if not self.useAttrNames and any("," in gene for gene in genes): genes = reduce(add, (split_and_strip(gene, ",") for gene in genes), []) self.information(0, "Separators detected in input gene names. " "Assuming multiple genes per instance.") self.queryGenes = genes self.information(1) reference = None if self.useReference and self.refData: reference = self.GeneNamesFromData(self.refData) if not self.useAttrNames \ and any("," in gene for gene in reference): reference = reduce(add, (split_and_strip(gene, ",") for gene in reference), []) self.information(1, "Separators detected in reference gene " "names. Assuming multiple genes per " "instance.") org_code = self.SelectedOrganismCode() def run_enrichment(org_code, genes, reference=None, progress=None): org = kegg.KEGGOrganism(org_code) if reference is None: reference = org.get_genes() # Map 'genes' and 'reference' sets to unique KEGG identifiers unique_genes, _, _ = org.get_unique_gene_ids(set(genes)) unique_ref_genes, _, _ = org.get_unique_gene_ids(set(reference)) taxid = kegg.to_taxid(org.org_code) # Map the taxid back to standard 'common' taxids # (as used by 'geneset') if applicable r_tax_map = dict((v, k) for k, v in kegg.KEGGGenome.TAXID_MAP.items()) if taxid in r_tax_map: taxid = r_tax_map[taxid] # We use the kegg pathway gene sets provided by 'geneset' for # the enrichment calculation. # Ensure we are using the latest genesets # TODO: ?? Is updating the index enough? serverfiles.update(geneset.sfdomain, "index.pck") kegg_gs_collections = geneset.collections( (("KEGG", "pathways"), taxid) ) pathways = pathway_enrichment( kegg_gs_collections, unique_genes.keys(), unique_ref_genes.keys(), callback=progress ) # Ensure that pathway entries are pre-cached for later use in the # list/tree view kegg_pathways = kegg.KEGGPathways() kegg_pathways.pre_cache( pathways.keys(), progress_callback=progress ) return pathways, org, unique_genes, unique_ref_genes self.progressBarInit() self.setEnabled(False) self.infoLabel.setText("Retrieving...\n") progress = methodinvoke(self, "setProgress", (float,)) self._enrichTask = Task( function=lambda: run_enrichment(org_code, genes, reference, progress) ) self._enrichTask.finished.connect(self._onEnrichTaskFinished) self._executor.submit(self._enrichTask) def _onEnrichTaskFinished(self): self.setEnabled(True) self.setBlocking(False) self.progressBarFinished() try: pathways, org, unique_genes, unique_ref_genes = \ self._enrichTask.result() except Exception: raise self.org = org self.genes = unique_genes.keys() self.uniqueGenesDict = unique_genes self.revUniqueGenesDict = dict([(val, key) for key, val in self.uniqueGenesDict.items()]) self.referenceGenes = unique_ref_genes.keys() self.pathways = pathways if not self.pathways: self.warning(0, "No enriched pathways found.") else: self.warning(0) count = len(set(self.queryGenes)) self.infoLabel.setText( "%i unique gene names on input\n" "%i (%.1f%%) genes names matched" % (count, len(unique_genes), 100.0 * len(unique_genes) / count if count else 0.0) ) self.UpdateListView() @pyqtSlot(float) def setProgress(self, value): self.progressBarValue = value def GeneNamesFromData(self, data): """ Extract and return gene names from `data`. """ if self.useAttrNames: genes = [str(v.name).strip() for v in data.domain.attributes] elif self.geneAttrCandidates: index = min(self.geneAttrIndex, len(self.geneAttrCandidates) - 1) geneAttr = self.geneAttrCandidates[index] genes = [str(e[geneAttr]) for e in data if not e[geneAttr].isSpecial()] else: raise ValueError("No gene names in data.") return genes def SelectedOrganismCode(self): """ Return the selected organism code. """ return self.organismCodes[min(self.organismIndex, len(self.organismCodes) - 1)] def selectAll(self): """ Select all items in the pathway view. """ changed = False scene = self.pathwayView.scene() with disconnected(scene.selectionChanged, self._onSelectionChanged): for item in scene.items(): if item.flags() & QGraphicsItem.ItemIsSelectable and \ not item.isSelected(): item.setSelected(True) changed = True if changed: self._onSelectionChanged() def _onSelectionChanged(self): # Item selection in the pathwayView/scene has changed if self.autoCommit: self.Commit() else: self._changedFlag = True def Commit(self): if self.data: selectedItems = self.pathwayView.scene().selectedItems() selectedGenes = reduce(set.union, [item.marked_objects for item in selectedItems], set()) if self.useAttrNames: selectedVars = [self.data.domain[self.uniqueGenesDict[gene]] for gene in selectedGenes] newDomain = Orange.data.Domain(selectedVars, 0) data = Orange.data.Table(newDomain, self.data) self.send("Selected Examples", data) elif self.geneAttrCandidates: geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates) - 1)] selectedExamples = [] otherExamples = [] for ex in self.data: names = [self.revUniqueGenesDict.get(name, None) for name in split_and_strip(str(ex[geneAttr]), ",")] if any(name and name in selectedGenes for name in names): selectedExamples.append(ex) else: otherExamples.append(ex) if selectedExamples: selectedExamples = Orange.data.Table(selectedExamples) else: selectedExamples = None if otherExamples: otherExamples = Orange.data.Table(otherExamples) else: otherExamples = None self.send("Selected Examples", selectedExamples) self.send("Unselected Examples", otherExamples) else: self.send("Selected Examples", None) self.send("Unselected Examples", None) def ClearCache(self): from ..kegg import caching try: caching.clear_cache() except Exception, ex: QMessageBox.warning(self, "Cache clear", ex.args[0])
def event(self, event): if (event.type() == QEvent.KeyPress) and (event.key() == Qt.Key_Space): self.emit(SIGNAL("spacePressed")) return True return QTreeWidget.event(self, event)
class PluginsDialog(QDialog): " Codimension plugins dialog " def __init__(self, pluginManager, parent=None): QDialog.__init__(self, parent) self.setWindowTitle("Plugin Manager") self.__pluginManager = pluginManager self.__configFuncs = {} # int -> callable self.__createLayout() self.__populate() self.__pluginsView.setFocus() self.__inItemChange = False return def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors(True) self.__pluginsView.setRootIsDecorated(False) self.__pluginsView.setItemsExpandable(False) self.__pluginsView.setSortingEnabled(True) self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__pluginsView.setUniformRowHeights(True) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( ["", "", "", "Name", "Version", ""]) self.__pluginsView.setHeaderItem(self.__pluginsHeader) self.__pluginsView.header().setSortIndicator(NAME_COL, Qt.AscendingOrder) self.connect(self.__pluginsView, SIGNAL("itemSelectionChanged()"), self.__pluginSelectionChanged) self.connect(self.__pluginsView, SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.__onItemChanged) layout.addWidget(self.__pluginsView) # Detailed information detailsLabel = QLabel("Detailed information") layout.addWidget(detailsLabel) self.__details = QTreeWidget() self.__details.setAlternatingRowColors(False) self.__details.setRootIsDecorated(False) self.__details.setItemsExpandable(False) self.__details.setSortingEnabled(False) self.__details.setItemDelegate(NoOutlineHeightDelegate(4)) self.__details.setUniformRowHeights(True) detailsHeader = QTreeWidgetItem(["", ""]) self.__details.setHeaderItem(detailsHeader) self.__details.setHeaderHidden(True) metrics = QFontMetrics(self.__details.font()) rect = metrics.boundingRect("X") self.__details.setFixedHeight(rect.height() * 6 + 5) layout.addWidget(self.__details) # Errors/warnings errorsLabel = QLabel("Errors / warnings") layout.addWidget(errorsLabel) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly(True) self.__errorsText.setAcceptRichText(False) metrics = QFontMetrics(self.__errorsText.font()) rect = metrics.boundingRect("X") self.__errorsText.setFixedHeight(rect.height() * 4 + 5) layout.addWidget(self.__errorsText) # Buttons box buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setDefault(True) self.connect(buttonBox, SIGNAL("accepted()"), self.close) self.connect(buttonBox, SIGNAL("rejected()"), self.close) layout.addWidget(buttonBox) self.setLayout(layout) return def __createConfigButton(self): " Creates a configure button for a plugin " button = SettingsButton() self.connect(button, SIGNAL('CustomClick'), self.onPluginSettings) return button def __populate(self): " Populates the list with the plugins " index = 0 for category in self.__pluginManager.activePlugins: for cdmPlugin in self.__pluginManager.activePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, True, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except Exception: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for category in self.__pluginManager.inactivePlugins: for cdmPlugin in self.__pluginManager.inactivePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip( "Enable plugin and then click to configure") settingsButton.setEnabled(False) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for cdmPlugin in self.__pluginManager.unknownPlugins: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, None) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() settingsButton.setToolTip("Unknown plugins are not configurable") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) self.__sortPlugins() self.__resizePlugins() return def __sortPlugins(self): " Sorts the plugins table " self.__pluginsView.sortItems( self.__pluginsView.sortColumn(), self.__pluginsView.header().sortIndicatorOrder()) return def __resizePlugins(self): " Resizes the plugins table " self.__pluginsView.header().setStretchLastSection(False) self.__pluginsView.header().resizeSections( QHeaderView.ResizeToContents) self.__pluginsView.header().resizeSection(STATE_COL, 28) self.__pluginsView.header().setResizeMode(STATE_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(CONFLICT_COL, 28) self.__pluginsView.header().setResizeMode(CONFLICT_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(TYPE_COL, 28) self.__pluginsView.header().setResizeMode(TYPE_COL, QHeaderView.Fixed) self.__pluginsView.header().setResizeMode(VERSION_COL, QHeaderView.Stretch) self.__pluginsView.header().resizeSection(SETTINGS_COL, 24) self.__pluginsView.header().setResizeMode(SETTINGS_COL, QHeaderView.Fixed) return def __pluginSelectionChanged(self): " Triggered when an item is selected " selected = list(self.__pluginsView.selectedItems()) if selected: self.__updateDetails(selected[0]) else: self.__updateDetails(None) return def __updateDetails(self, item): " Updates the content of the details and the error boxes " self.__details.clear() self.__errorsText.setText("") if item is None: return self.__details.addTopLevelItem( QTreeWidgetItem(["Author", item.plugin.getAuthor()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Path", os.path.normpath(item.plugin.getPath())])) self.__details.addTopLevelItem( QTreeWidgetItem(["Description", item.plugin.getDescription()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Web site", item.plugin.getWebsite()])) copyright = item.plugin.getCopyright() if copyright is not None: if copyright.lower() != "unknown": self.__details.addTopLevelItem( QTreeWidgetItem(["Copyright", copyright])) for name in item.plugin.getDetails(): value = item.plugin.getDetails()[name] self.__details.addTopLevelItem(QTreeWidgetItem([name, value])) self.__errorsText.setText(item.plugin.conflictMessage) return def __onItemChanged(self, item, column): " Triggered when an item is changed " if self.__inItemChange: return if item.active: self.__inItemChange = True item.plugin.disable() item.active = False settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) settingsButton.setEnabled(False) if settingsButton.index != -1: settingsButton.setToolTip( "Enable plugin and then click to configure") if item.category in self.__pluginManager.inactivePlugins: self.__pluginManager.inactivePlugins[item.category].append( item.plugin) else: self.__pluginManager.inactivePlugins[item.category] = [ item.plugin ] self.__pluginManager.activePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__inItemChange = False self.__pluginManager.sendPluginDeactivated(item.plugin) return self.__inItemChange = True message = self.__pluginManager.checkConflict(item.plugin) if message is not None: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText(message) self.__inItemChange = False return try: item.plugin.enable() item.active = True if item.category in self.__pluginManager.activePlugins: self.__pluginManager.activePlugins[item.category].append( item.plugin) else: self.__pluginManager.activePlugins[item.category] = [ item.plugin ] self.__pluginManager.inactivePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__errorsText.setText("") item.setIcon(CONFLICT_COL, PixmapCache().getIcon('empty.png')) item.setToolTip(CONFLICT_COL, "") settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) if settingsButton.index != -1: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__pluginManager.sendPluginActivated(item.plugin) except: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText( "Error activating the plugin - exception is generated") self.__inItemChange = False return def onPluginSettings(self, index): " Triggered when a configuring function is called " if index not in self.__configFuncs: return try: self.__configFuncs[index]() except Exception, exc: logging.error("Error calling the plugin configuration function. " "Message: " + str(exc)) return
def mousePressEvent(self, event): """ Mouse press event to manage the layers drag """ if ( event.button() == Qt.LeftButton ): self.lastPressPos = event.pos() self.bMousePressedFlag = True QTreeWidget.mousePressEvent( self, event )
def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors(True) self.__pluginsView.setRootIsDecorated(False) self.__pluginsView.setItemsExpandable(False) self.__pluginsView.setSortingEnabled(True) self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__pluginsView.setUniformRowHeights(True) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( ["", "", "", "Name", "Version", ""]) self.__pluginsView.setHeaderItem(self.__pluginsHeader) self.__pluginsView.header().setSortIndicator(NAME_COL, Qt.AscendingOrder) self.connect(self.__pluginsView, SIGNAL("itemSelectionChanged()"), self.__pluginSelectionChanged) self.connect(self.__pluginsView, SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.__onItemChanged) layout.addWidget(self.__pluginsView) # Detailed information detailsLabel = QLabel("Detailed information") layout.addWidget(detailsLabel) self.__details = QTreeWidget() self.__details.setAlternatingRowColors(False) self.__details.setRootIsDecorated(False) self.__details.setItemsExpandable(False) self.__details.setSortingEnabled(False) self.__details.setItemDelegate(NoOutlineHeightDelegate(4)) self.__details.setUniformRowHeights(True) detailsHeader = QTreeWidgetItem(["", ""]) self.__details.setHeaderItem(detailsHeader) self.__details.setHeaderHidden(True) metrics = QFontMetrics(self.__details.font()) rect = metrics.boundingRect("X") self.__details.setFixedHeight(rect.height() * 6 + 5) layout.addWidget(self.__details) # Errors/warnings errorsLabel = QLabel("Errors / warnings") layout.addWidget(errorsLabel) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly(True) self.__errorsText.setAcceptRichText(False) metrics = QFontMetrics(self.__errorsText.font()) rect = metrics.boundingRect("X") self.__errorsText.setFixedHeight(rect.height() * 4 + 5) layout.addWidget(self.__errorsText) # Buttons box buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setDefault(True) self.connect(buttonBox, SIGNAL("accepted()"), self.close) self.connect(buttonBox, SIGNAL("rejected()"), self.close) layout.addWidget(buttonBox) self.setLayout(layout) return
class PythonConsoleWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setWindowTitle( QCoreApplication.translate("PythonConsole", "Python Console")) self.settings = QSettings() self.shell = ShellScintilla(self) self.setFocusProxy(self.shell) self.shellOut = ShellOutputScintilla(self) self.tabEditorWidget = EditorTabWidget(self) ##------------ UI ------------------------------- self.splitterEditor = QSplitter(self) self.splitterEditor.setOrientation(Qt.Horizontal) self.splitterEditor.setHandleWidth(6) self.splitterEditor.setChildrenCollapsible(True) self.shellOutWidget = QWidget(self) self.shellOutWidget.setLayout(QVBoxLayout()) self.shellOutWidget.layout().setContentsMargins(0, 0, 0, 0) self.shellOutWidget.layout().addWidget(self.shellOut) self.splitter = QSplitter(self.splitterEditor) self.splitter.setOrientation(Qt.Vertical) self.splitter.setHandleWidth(3) self.splitter.setChildrenCollapsible(False) self.splitter.addWidget(self.shellOutWidget) self.splitter.addWidget(self.shell) #self.splitterEditor.addWidget(self.tabEditorWidget) self.splitterObj = QSplitter(self.splitterEditor) self.splitterObj.setHandleWidth(3) self.splitterObj.setOrientation(Qt.Horizontal) #self.splitterObj.setSizes([0, 0]) #self.splitterObj.setStretchFactor(0, 1) self.widgetEditor = QWidget(self.splitterObj) self.widgetFind = QWidget(self) self.listClassMethod = QTreeWidget(self.splitterObj) self.listClassMethod.setColumnCount(2) objInspLabel = QCoreApplication.translate("PythonConsole", "Object Inspector") self.listClassMethod.setHeaderLabels([objInspLabel, '']) self.listClassMethod.setColumnHidden(1, True) self.listClassMethod.setAlternatingRowColors(True) #self.splitterEditor.addWidget(self.widgetEditor) #self.splitterObj.addWidget(self.listClassMethod) #self.splitterObj.addWidget(self.widgetEditor) # Hide side editor on start up self.splitterObj.hide() self.listClassMethod.hide() # Hide search widget on start up self.widgetFind.hide() sizes = self.splitter.sizes() self.splitter.setSizes(sizes) ##----------------Restore Settings------------------------------------ self.restoreSettingsConsole() ##------------------Toolbar Editor------------------------------------- ## Action for Open File openFileBt = QCoreApplication.translate("PythonConsole", "Open file") self.openFileButton = QAction(self) self.openFileButton.setCheckable(False) self.openFileButton.setEnabled(True) self.openFileButton.setIcon( QgsApplication.getThemeIcon("console/iconOpenConsole.png")) self.openFileButton.setMenuRole(QAction.PreferencesRole) self.openFileButton.setIconVisibleInMenu(True) self.openFileButton.setToolTip(openFileBt) self.openFileButton.setText(openFileBt) openExtEditorBt = QCoreApplication.translate( "PythonConsole", "Open in external editor") self.openInEditorButton = QAction(self) self.openInEditorButton.setCheckable(False) self.openInEditorButton.setEnabled(True) self.openInEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.openInEditorButton.setMenuRole(QAction.PreferencesRole) self.openInEditorButton.setIconVisibleInMenu(True) self.openInEditorButton.setToolTip(openExtEditorBt) self.openInEditorButton.setText(openExtEditorBt) ## Action for Save File saveFileBt = QCoreApplication.translate("PythonConsole", "Save") self.saveFileButton = QAction(self) self.saveFileButton.setCheckable(False) self.saveFileButton.setEnabled(False) self.saveFileButton.setIcon( QgsApplication.getThemeIcon("console/iconSaveConsole.png")) self.saveFileButton.setMenuRole(QAction.PreferencesRole) self.saveFileButton.setIconVisibleInMenu(True) self.saveFileButton.setToolTip(saveFileBt) self.saveFileButton.setText(saveFileBt) ## Action for Save File As saveAsFileBt = QCoreApplication.translate("PythonConsole", "Save As...") self.saveAsFileButton = QAction(self) self.saveAsFileButton.setCheckable(False) self.saveAsFileButton.setEnabled(True) self.saveAsFileButton.setIcon( QgsApplication.getThemeIcon("console/iconSaveAsConsole.png")) self.saveAsFileButton.setMenuRole(QAction.PreferencesRole) self.saveAsFileButton.setIconVisibleInMenu(True) self.saveAsFileButton.setToolTip(saveAsFileBt) self.saveAsFileButton.setText(saveAsFileBt) ## Action Cut cutEditorBt = QCoreApplication.translate("PythonConsole", "Cut") self.cutEditorButton = QAction(self) self.cutEditorButton.setCheckable(False) self.cutEditorButton.setEnabled(True) self.cutEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconCutEditorConsole.png")) self.cutEditorButton.setMenuRole(QAction.PreferencesRole) self.cutEditorButton.setIconVisibleInMenu(True) self.cutEditorButton.setToolTip(cutEditorBt) self.cutEditorButton.setText(cutEditorBt) ## Action Copy copyEditorBt = QCoreApplication.translate("PythonConsole", "Copy") self.copyEditorButton = QAction(self) self.copyEditorButton.setCheckable(False) self.copyEditorButton.setEnabled(True) self.copyEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconCopyEditorConsole.png")) self.copyEditorButton.setMenuRole(QAction.PreferencesRole) self.copyEditorButton.setIconVisibleInMenu(True) self.copyEditorButton.setToolTip(copyEditorBt) self.copyEditorButton.setText(copyEditorBt) ## Action Paste pasteEditorBt = QCoreApplication.translate("PythonConsole", "Paste") self.pasteEditorButton = QAction(self) self.pasteEditorButton.setCheckable(False) self.pasteEditorButton.setEnabled(True) self.pasteEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconPasteEditorConsole.png")) self.pasteEditorButton.setMenuRole(QAction.PreferencesRole) self.pasteEditorButton.setIconVisibleInMenu(True) self.pasteEditorButton.setToolTip(pasteEditorBt) self.pasteEditorButton.setText(pasteEditorBt) ## Action Run Script (subprocess) runScriptEditorBt = QCoreApplication.translate("PythonConsole", "Run script") self.runScriptEditorButton = QAction(self) self.runScriptEditorButton.setCheckable(False) self.runScriptEditorButton.setEnabled(True) self.runScriptEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconRunScriptConsole.png")) self.runScriptEditorButton.setMenuRole(QAction.PreferencesRole) self.runScriptEditorButton.setIconVisibleInMenu(True) self.runScriptEditorButton.setToolTip(runScriptEditorBt) self.runScriptEditorButton.setText(runScriptEditorBt) ## Action Run Script (subprocess) commentEditorBt = QCoreApplication.translate("PythonConsole", "Comment") self.commentEditorButton = QAction(self) self.commentEditorButton.setCheckable(False) self.commentEditorButton.setEnabled(True) self.commentEditorButton.setIcon( QgsApplication.getThemeIcon( "console/iconCommentEditorConsole.png")) self.commentEditorButton.setMenuRole(QAction.PreferencesRole) self.commentEditorButton.setIconVisibleInMenu(True) self.commentEditorButton.setToolTip(commentEditorBt) self.commentEditorButton.setText(commentEditorBt) ## Action Run Script (subprocess) uncommentEditorBt = QCoreApplication.translate("PythonConsole", "Uncomment") self.uncommentEditorButton = QAction(self) self.uncommentEditorButton.setCheckable(False) self.uncommentEditorButton.setEnabled(True) self.uncommentEditorButton.setIcon( QgsApplication.getThemeIcon( "console/iconUncommentEditorConsole.png")) self.uncommentEditorButton.setMenuRole(QAction.PreferencesRole) self.uncommentEditorButton.setIconVisibleInMenu(True) self.uncommentEditorButton.setToolTip(uncommentEditorBt) self.uncommentEditorButton.setText(uncommentEditorBt) ## Action for Object browser objList = QCoreApplication.translate("PythonConsole", "Object Inspector") self.objectListButton = QAction(self) self.objectListButton.setCheckable(True) self.objectListButton.setEnabled( self.settings.value("pythonConsole/enableObjectInsp", False, type=bool)) self.objectListButton.setIcon( QgsApplication.getThemeIcon("console/iconClassBrowserConsole.png")) self.objectListButton.setMenuRole(QAction.PreferencesRole) self.objectListButton.setIconVisibleInMenu(True) self.objectListButton.setToolTip(objList) self.objectListButton.setText(objList) ## Action for Find text findText = QCoreApplication.translate("PythonConsole", "Find Text") self.findTextButton = QAction(self) self.findTextButton.setCheckable(True) self.findTextButton.setEnabled(True) self.findTextButton.setIcon( QgsApplication.getThemeIcon("console/iconSearchEditorConsole.png")) self.findTextButton.setMenuRole(QAction.PreferencesRole) self.findTextButton.setIconVisibleInMenu(True) self.findTextButton.setToolTip(findText) self.findTextButton.setText(findText) ##----------------Toolbar Console------------------------------------- ## Action Show Editor showEditor = QCoreApplication.translate("PythonConsole", "Show editor") self.showEditorButton = QAction(self) self.showEditorButton.setEnabled(True) self.showEditorButton.setCheckable(True) self.showEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.showEditorButton.setMenuRole(QAction.PreferencesRole) self.showEditorButton.setIconVisibleInMenu(True) self.showEditorButton.setToolTip(showEditor) self.showEditorButton.setText(showEditor) ## Action for Clear button clearBt = QCoreApplication.translate("PythonConsole", "Clear console") self.clearButton = QAction(self) self.clearButton.setCheckable(False) self.clearButton.setEnabled(True) self.clearButton.setIcon( QgsApplication.getThemeIcon("console/iconClearConsole.png")) self.clearButton.setMenuRole(QAction.PreferencesRole) self.clearButton.setIconVisibleInMenu(True) self.clearButton.setToolTip(clearBt) self.clearButton.setText(clearBt) ## Action for settings optionsBt = QCoreApplication.translate("PythonConsole", "Settings") self.optionsButton = QAction(self) self.optionsButton.setCheckable(False) self.optionsButton.setEnabled(True) self.optionsButton.setIcon( QgsApplication.getThemeIcon("console/iconSettingsConsole.png")) self.optionsButton.setMenuRole(QAction.PreferencesRole) self.optionsButton.setIconVisibleInMenu(True) self.optionsButton.setToolTip(optionsBt) self.optionsButton.setText(optionsBt) ## Action menu for class actionClassBt = QCoreApplication.translate("PythonConsole", "Import Class") self.actionClass = QAction(self) self.actionClass.setCheckable(False) self.actionClass.setEnabled(True) self.actionClass.setIcon( QgsApplication.getThemeIcon("console/iconClassConsole.png")) self.actionClass.setMenuRole(QAction.PreferencesRole) self.actionClass.setIconVisibleInMenu(True) self.actionClass.setToolTip(actionClassBt) self.actionClass.setText(actionClassBt) ## Import Processing class loadProcessingBt = QCoreApplication.translate( "PythonConsole", "Import Processing class") self.loadProcessingButton = QAction(self) self.loadProcessingButton.setCheckable(False) self.loadProcessingButton.setEnabled(True) self.loadProcessingButton.setIcon( QgsApplication.getThemeIcon("console/iconProcessingConsole.png")) self.loadProcessingButton.setMenuRole(QAction.PreferencesRole) self.loadProcessingButton.setIconVisibleInMenu(True) self.loadProcessingButton.setToolTip(loadProcessingBt) self.loadProcessingButton.setText(loadProcessingBt) ## Import QtCore class loadQtCoreBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtCore class") self.loadQtCoreButton = QAction(self) self.loadQtCoreButton.setCheckable(False) self.loadQtCoreButton.setEnabled(True) self.loadQtCoreButton.setIcon( QgsApplication.getThemeIcon("console/iconQtCoreConsole.png")) self.loadQtCoreButton.setMenuRole(QAction.PreferencesRole) self.loadQtCoreButton.setIconVisibleInMenu(True) self.loadQtCoreButton.setToolTip(loadQtCoreBt) self.loadQtCoreButton.setText(loadQtCoreBt) ## Import QtGui class loadQtGuiBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtGui class") self.loadQtGuiButton = QAction(self) self.loadQtGuiButton.setCheckable(False) self.loadQtGuiButton.setEnabled(True) self.loadQtGuiButton.setIcon( QgsApplication.getThemeIcon("console/iconQtGuiConsole.png")) self.loadQtGuiButton.setMenuRole(QAction.PreferencesRole) self.loadQtGuiButton.setIconVisibleInMenu(True) self.loadQtGuiButton.setToolTip(loadQtGuiBt) self.loadQtGuiButton.setText(loadQtGuiBt) ## Action for Run script runBt = QCoreApplication.translate("PythonConsole", "Run command") self.runButton = QAction(self) self.runButton.setCheckable(False) self.runButton.setEnabled(True) self.runButton.setIcon( QgsApplication.getThemeIcon("console/iconRunConsole.png")) self.runButton.setMenuRole(QAction.PreferencesRole) self.runButton.setIconVisibleInMenu(True) self.runButton.setToolTip(runBt) self.runButton.setText(runBt) ## Help action helpBt = QCoreApplication.translate("PythonConsole", "Help") self.helpButton = QAction(self) self.helpButton.setCheckable(False) self.helpButton.setEnabled(True) self.helpButton.setIcon( QgsApplication.getThemeIcon("console/iconHelpConsole.png")) self.helpButton.setMenuRole(QAction.PreferencesRole) self.helpButton.setIconVisibleInMenu(True) self.helpButton.setToolTip(helpBt) self.helpButton.setText(helpBt) self.toolBar = QToolBar() self.toolBar.setEnabled(True) self.toolBar.setFocusPolicy(Qt.NoFocus) self.toolBar.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBar.setLayoutDirection(Qt.LeftToRight) self.toolBar.setIconSize(QSize(16, 16)) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.addAction(self.clearButton) self.toolBar.addAction(self.actionClass) self.toolBar.addAction(self.runButton) self.toolBar.addSeparator() self.toolBar.addAction(self.showEditorButton) self.toolBar.addSeparator() self.toolBar.addAction(self.optionsButton) self.toolBar.addAction(self.helpButton) self.toolBarEditor = QToolBar() self.toolBarEditor.setEnabled(False) self.toolBarEditor.setFocusPolicy(Qt.NoFocus) self.toolBarEditor.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBarEditor.setLayoutDirection(Qt.LeftToRight) self.toolBarEditor.setIconSize(QSize(16, 16)) self.toolBarEditor.setMovable(False) self.toolBarEditor.setFloatable(False) self.toolBarEditor.addAction(self.openFileButton) self.toolBarEditor.addAction(self.openInEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.saveFileButton) self.toolBarEditor.addAction(self.saveAsFileButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.runScriptEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.findTextButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.cutEditorButton) self.toolBarEditor.addAction(self.copyEditorButton) self.toolBarEditor.addAction(self.pasteEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.commentEditorButton) self.toolBarEditor.addAction(self.uncommentEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.objectListButton) ## Menu Import Class self.classMenu = QMenu() self.classMenu.addAction(self.loadProcessingButton) self.classMenu.addAction(self.loadQtCoreButton) self.classMenu.addAction(self.loadQtGuiButton) cM = self.toolBar.widgetForAction(self.actionClass) cM.setMenu(self.classMenu) cM.setPopupMode(QToolButton.InstantPopup) self.widgetButton = QWidget() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.widgetButton.sizePolicy().hasHeightForWidth()) self.widgetButton.setSizePolicy(sizePolicy) self.widgetButtonEditor = QWidget(self.widgetEditor) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.widgetButtonEditor.sizePolicy().hasHeightForWidth()) self.widgetButtonEditor.setSizePolicy(sizePolicy) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.shellOut.sizePolicy().hasHeightForWidth()) self.shellOut.setSizePolicy(sizePolicy) self.shellOut.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.shell.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) ##------------ Layout ------------------------------- self.mainLayout = QGridLayout(self) self.mainLayout.setMargin(0) self.mainLayout.setSpacing(0) self.mainLayout.addWidget(self.widgetButton, 0, 0, 1, 1) self.mainLayout.addWidget(self.splitterEditor, 0, 1, 1, 1) self.shellOutWidget.layout().insertWidget(0, self.toolBar) self.layoutEditor = QGridLayout(self.widgetEditor) self.layoutEditor.setMargin(0) self.layoutEditor.setSpacing(0) self.layoutEditor.addWidget(self.toolBarEditor, 0, 1, 1, 1) self.layoutEditor.addWidget(self.widgetButtonEditor, 1, 0, 2, 1) self.layoutEditor.addWidget(self.tabEditorWidget, 1, 1, 1, 1) self.layoutEditor.addWidget(self.widgetFind, 2, 1, 1, 1) ## Layout for the find widget self.layoutFind = QGridLayout(self.widgetFind) self.layoutFind.setContentsMargins(0, 0, 0, 0) self.lineEditFind = QgsFilterLineEdit() placeHolderTxt = QCoreApplication.translate("PythonConsole", "Enter text to find...") if pyqtconfig.Configuration().qt_version >= 0x40700: self.lineEditFind.setPlaceholderText(placeHolderTxt) else: self.lineEditFind.setToolTip(placeHolderTxt) self.findNextButton = QToolButton() self.findNextButton.setEnabled(False) toolTipfindNext = QCoreApplication.translate("PythonConsole", "Find Next") self.findNextButton.setToolTip(toolTipfindNext) self.findNextButton.setIcon( QgsApplication.getThemeIcon( "console/iconSearchNextEditorConsole.png")) self.findNextButton.setIconSize(QSize(24, 24)) self.findNextButton.setAutoRaise(True) self.findPrevButton = QToolButton() self.findPrevButton.setEnabled(False) toolTipfindPrev = QCoreApplication.translate("PythonConsole", "Find Previous") self.findPrevButton.setToolTip(toolTipfindPrev) self.findPrevButton.setIcon( QgsApplication.getThemeIcon( "console/iconSearchPrevEditorConsole.png")) self.findPrevButton.setIconSize(QSize(24, 24)) self.findPrevButton.setAutoRaise(True) self.caseSensitive = QCheckBox() caseSensTr = QCoreApplication.translate("PythonConsole", "Case Sensitive") self.caseSensitive.setText(caseSensTr) self.wholeWord = QCheckBox() wholeWordTr = QCoreApplication.translate("PythonConsole", "Whole Word") self.wholeWord.setText(wholeWordTr) self.wrapAround = QCheckBox() self.wrapAround.setChecked(True) wrapAroundTr = QCoreApplication.translate("PythonConsole", "Wrap Around") self.wrapAround.setText(wrapAroundTr) self.layoutFind.addWidget(self.lineEditFind, 0, 1, 1, 1) self.layoutFind.addWidget(self.findPrevButton, 0, 2, 1, 1) self.layoutFind.addWidget(self.findNextButton, 0, 3, 1, 1) self.layoutFind.addWidget(self.caseSensitive, 0, 4, 1, 1) self.layoutFind.addWidget(self.wholeWord, 0, 5, 1, 1) self.layoutFind.addWidget(self.wrapAround, 0, 6, 1, 1) ##------------ Add first Tab in Editor ------------------------------- #self.tabEditorWidget.newTabEditor(tabName='first', filename=None) ##------------ Signal ------------------------------- self.findTextButton.toggled.connect(self.findTextEditor) self.objectListButton.toggled.connect(self.toggleObjectListWidget) self.commentEditorButton.triggered.connect(self.commentCode) self.uncommentEditorButton.triggered.connect(self.uncommentCode) self.runScriptEditorButton.triggered.connect(self.runScriptEditor) self.cutEditorButton.triggered.connect(self.cutEditor) self.copyEditorButton.triggered.connect(self.copyEditor) self.pasteEditorButton.triggered.connect(self.pasteEditor) self.showEditorButton.toggled.connect(self.toggleEditor) self.clearButton.triggered.connect(self.shellOut.clearConsole) self.optionsButton.triggered.connect(self.openSettings) self.loadProcessingButton.triggered.connect(self.processing) self.loadQtCoreButton.triggered.connect(self.qtCore) self.loadQtGuiButton.triggered.connect(self.qtGui) self.runButton.triggered.connect(self.shell.entered) self.openFileButton.triggered.connect(self.openScriptFile) self.openInEditorButton.triggered.connect(self.openScriptFileExtEditor) self.saveFileButton.triggered.connect(self.saveScriptFile) self.saveAsFileButton.triggered.connect(self.saveAsScriptFile) self.helpButton.triggered.connect(self.openHelp) self.connect(self.listClassMethod, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), self.onClickGoToLine) self.lineEditFind.returnPressed.connect(self._findText) self.findNextButton.clicked.connect(self._findNext) self.findPrevButton.clicked.connect(self._findPrev) self.lineEditFind.textChanged.connect(self._textFindChanged) def _findText(self): self.tabEditorWidget.currentWidget().newEditor.findText(True) def _findNext(self): self.tabEditorWidget.currentWidget().newEditor.findText(True) def _findPrev(self): self.tabEditorWidget.currentWidget().newEditor.findText(False) def _textFindChanged(self): if self.lineEditFind.text(): self.findNextButton.setEnabled(True) self.findPrevButton.setEnabled(True) else: self.lineEditFind.setStyleSheet('') self.findNextButton.setEnabled(False) self.findPrevButton.setEnabled(False) def onClickGoToLine(self, item, column): tabEditor = self.tabEditorWidget.currentWidget().newEditor if item.text(1) == 'syntaxError': check = tabEditor.syntaxCheck(fromContextMenu=False) if check and not tabEditor.isReadOnly(): self.tabEditorWidget.currentWidget().save() return linenr = int(item.text(1)) itemName = str(item.text(0)) charPos = itemName.find(' ') if charPos != -1: objName = itemName[0:charPos] else: objName = itemName tabEditor.goToLine(objName, linenr) def processing(self): self.shell.commandConsole('processing') def qtCore(self): self.shell.commandConsole('qtCore') def qtGui(self): self.shell.commandConsole('qtGui') def toggleEditor(self, checked): self.splitterObj.show() if checked else self.splitterObj.hide() if not self.tabEditorWidget: self.tabEditorWidget.enableToolBarEditor(checked) self.tabEditorWidget.restoreTabsOrAddNew() def toggleObjectListWidget(self, checked): self.listClassMethod.show() if checked else self.listClassMethod.hide() def findTextEditor(self, checked): self.widgetFind.show() if checked else self.widgetFind.hide() def pasteEditor(self): self.tabEditorWidget.currentWidget().newEditor.paste() def cutEditor(self): self.tabEditorWidget.currentWidget().newEditor.cut() def copyEditor(self): self.tabEditorWidget.currentWidget().newEditor.copy() def runScriptEditor(self): self.tabEditorWidget.currentWidget().newEditor.runScriptCode() def commentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(True) def uncommentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(False) def openScriptFileExtEditor(self): tabWidget = self.tabEditorWidget.currentWidget() path = tabWidget.path import subprocess try: subprocess.Popen([os.environ['EDITOR'], path]) except KeyError: QDesktopServices.openUrl(QUrl.fromLocalFile(path)) def openScriptFile(self): lastDirPath = self.settings.value("pythonConsole/lastDirPath", QDir.homePath()) openFileTr = QCoreApplication.translate("PythonConsole", "Open File") fileList = QFileDialog.getOpenFileNames(self, openFileTr, lastDirPath, "Script file (*.py)") if fileList: for pyFile in fileList: for i in range(self.tabEditorWidget.count()): tabWidget = self.tabEditorWidget.widget(i) if tabWidget.path == pyFile: self.tabEditorWidget.setCurrentWidget(tabWidget) break else: tabName = QFileInfo(pyFile).fileName() self.tabEditorWidget.newTabEditor(tabName, pyFile) lastDirPath = QFileInfo(pyFile).path() self.settings.setValue("pythonConsole/lastDirPath", pyFile) self.updateTabListScript(pyFile, action='append') def saveScriptFile(self): tabWidget = self.tabEditorWidget.currentWidget() try: tabWidget.save() except (IOError, OSError) as error: msgText = QCoreApplication.translate( 'PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}').format( tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) def saveAsScriptFile(self, index=None): tabWidget = self.tabEditorWidget.currentWidget() if not index: index = self.tabEditorWidget.currentIndex() if not tabWidget.path: fileName = self.tabEditorWidget.tabText(index) + '.py' folder = self.settings.value("pythonConsole/lastDirPath", QDir.home()) pathFileName = os.path.join(folder, fileName) fileNone = True else: pathFileName = tabWidget.path fileNone = False saveAsFileTr = QCoreApplication.translate("PythonConsole", "Save File As") filename = QFileDialog.getSaveFileName(self, saveAsFileTr, pathFileName, "Script file (*.py)") if filename: try: tabWidget.save(filename) except (IOError, OSError) as error: msgText = QCoreApplication.translate( 'PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}' ).format(tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) if fileNone: tabWidget.path = None else: tabWidget.path = pathFileName return if not fileNone: self.updateTabListScript(pathFileName, action='remove') def openHelp(self): QgsContextHelp.run("PythonConsole") def openSettings(self): if optionsDialog(self).exec_(): self.shell.refreshSettingsShell() self.shellOut.refreshSettingsOutput() self.tabEditorWidget.refreshSettingsEditor() def callWidgetMessageBar(self, text): self.shellOut.widgetMessageBar(iface, text) def callWidgetMessageBarEditor(self, text, level, timed): self.tabEditorWidget.widgetMessageBar(iface, text, level, timed) def updateTabListScript(self, script, action=None): if action == 'remove': self.tabListScript.remove(script) elif action == 'append': if not self.tabListScript: self.tabListScript = [] if script not in self.tabListScript: self.tabListScript.append(script) else: self.tabListScript = [] self.settings.setValue("pythonConsole/tabScripts", self.tabListScript) def saveSettingsConsole(self): self.settings.setValue("pythonConsole/splitterConsole", self.splitter.saveState()) self.settings.setValue("pythonConsole/splitterObj", self.splitterObj.saveState()) self.settings.setValue("pythonConsole/splitterEditor", self.splitterEditor.saveState()) self.shell.writeHistoryFile(True) def restoreSettingsConsole(self): storedTabScripts = self.settings.value("pythonConsole/tabScripts", []) self.tabListScript = storedTabScripts self.splitter.restoreState( self.settings.value("pythonConsole/splitterConsole", QByteArray())) self.splitterEditor.restoreState( self.settings.value("pythonConsole/splitterEditor", QByteArray())) self.splitterObj.restoreState( self.settings.value("pythonConsole/splitterObj", QByteArray()))
def __init__(self, parent=None): QWidget.__init__(self, parent) self.setWindowTitle( QCoreApplication.translate("PythonConsole", "Python Console")) self.settings = QSettings() self.shell = ShellScintilla(self) self.setFocusProxy(self.shell) self.shellOut = ShellOutputScintilla(self) self.tabEditorWidget = EditorTabWidget(self) ##------------ UI ------------------------------- self.splitterEditor = QSplitter(self) self.splitterEditor.setOrientation(Qt.Horizontal) self.splitterEditor.setHandleWidth(6) self.splitterEditor.setChildrenCollapsible(True) self.shellOutWidget = QWidget(self) self.shellOutWidget.setLayout(QVBoxLayout()) self.shellOutWidget.layout().setContentsMargins(0, 0, 0, 0) self.shellOutWidget.layout().addWidget(self.shellOut) self.splitter = QSplitter(self.splitterEditor) self.splitter.setOrientation(Qt.Vertical) self.splitter.setHandleWidth(3) self.splitter.setChildrenCollapsible(False) self.splitter.addWidget(self.shellOutWidget) self.splitter.addWidget(self.shell) #self.splitterEditor.addWidget(self.tabEditorWidget) self.splitterObj = QSplitter(self.splitterEditor) self.splitterObj.setHandleWidth(3) self.splitterObj.setOrientation(Qt.Horizontal) #self.splitterObj.setSizes([0, 0]) #self.splitterObj.setStretchFactor(0, 1) self.widgetEditor = QWidget(self.splitterObj) self.widgetFind = QWidget(self) self.listClassMethod = QTreeWidget(self.splitterObj) self.listClassMethod.setColumnCount(2) objInspLabel = QCoreApplication.translate("PythonConsole", "Object Inspector") self.listClassMethod.setHeaderLabels([objInspLabel, '']) self.listClassMethod.setColumnHidden(1, True) self.listClassMethod.setAlternatingRowColors(True) #self.splitterEditor.addWidget(self.widgetEditor) #self.splitterObj.addWidget(self.listClassMethod) #self.splitterObj.addWidget(self.widgetEditor) # Hide side editor on start up self.splitterObj.hide() self.listClassMethod.hide() # Hide search widget on start up self.widgetFind.hide() sizes = self.splitter.sizes() self.splitter.setSizes(sizes) ##----------------Restore Settings------------------------------------ self.restoreSettingsConsole() ##------------------Toolbar Editor------------------------------------- ## Action for Open File openFileBt = QCoreApplication.translate("PythonConsole", "Open file") self.openFileButton = QAction(self) self.openFileButton.setCheckable(False) self.openFileButton.setEnabled(True) self.openFileButton.setIcon( QgsApplication.getThemeIcon("console/iconOpenConsole.png")) self.openFileButton.setMenuRole(QAction.PreferencesRole) self.openFileButton.setIconVisibleInMenu(True) self.openFileButton.setToolTip(openFileBt) self.openFileButton.setText(openFileBt) openExtEditorBt = QCoreApplication.translate( "PythonConsole", "Open in external editor") self.openInEditorButton = QAction(self) self.openInEditorButton.setCheckable(False) self.openInEditorButton.setEnabled(True) self.openInEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.openInEditorButton.setMenuRole(QAction.PreferencesRole) self.openInEditorButton.setIconVisibleInMenu(True) self.openInEditorButton.setToolTip(openExtEditorBt) self.openInEditorButton.setText(openExtEditorBt) ## Action for Save File saveFileBt = QCoreApplication.translate("PythonConsole", "Save") self.saveFileButton = QAction(self) self.saveFileButton.setCheckable(False) self.saveFileButton.setEnabled(False) self.saveFileButton.setIcon( QgsApplication.getThemeIcon("console/iconSaveConsole.png")) self.saveFileButton.setMenuRole(QAction.PreferencesRole) self.saveFileButton.setIconVisibleInMenu(True) self.saveFileButton.setToolTip(saveFileBt) self.saveFileButton.setText(saveFileBt) ## Action for Save File As saveAsFileBt = QCoreApplication.translate("PythonConsole", "Save As...") self.saveAsFileButton = QAction(self) self.saveAsFileButton.setCheckable(False) self.saveAsFileButton.setEnabled(True) self.saveAsFileButton.setIcon( QgsApplication.getThemeIcon("console/iconSaveAsConsole.png")) self.saveAsFileButton.setMenuRole(QAction.PreferencesRole) self.saveAsFileButton.setIconVisibleInMenu(True) self.saveAsFileButton.setToolTip(saveAsFileBt) self.saveAsFileButton.setText(saveAsFileBt) ## Action Cut cutEditorBt = QCoreApplication.translate("PythonConsole", "Cut") self.cutEditorButton = QAction(self) self.cutEditorButton.setCheckable(False) self.cutEditorButton.setEnabled(True) self.cutEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconCutEditorConsole.png")) self.cutEditorButton.setMenuRole(QAction.PreferencesRole) self.cutEditorButton.setIconVisibleInMenu(True) self.cutEditorButton.setToolTip(cutEditorBt) self.cutEditorButton.setText(cutEditorBt) ## Action Copy copyEditorBt = QCoreApplication.translate("PythonConsole", "Copy") self.copyEditorButton = QAction(self) self.copyEditorButton.setCheckable(False) self.copyEditorButton.setEnabled(True) self.copyEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconCopyEditorConsole.png")) self.copyEditorButton.setMenuRole(QAction.PreferencesRole) self.copyEditorButton.setIconVisibleInMenu(True) self.copyEditorButton.setToolTip(copyEditorBt) self.copyEditorButton.setText(copyEditorBt) ## Action Paste pasteEditorBt = QCoreApplication.translate("PythonConsole", "Paste") self.pasteEditorButton = QAction(self) self.pasteEditorButton.setCheckable(False) self.pasteEditorButton.setEnabled(True) self.pasteEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconPasteEditorConsole.png")) self.pasteEditorButton.setMenuRole(QAction.PreferencesRole) self.pasteEditorButton.setIconVisibleInMenu(True) self.pasteEditorButton.setToolTip(pasteEditorBt) self.pasteEditorButton.setText(pasteEditorBt) ## Action Run Script (subprocess) runScriptEditorBt = QCoreApplication.translate("PythonConsole", "Run script") self.runScriptEditorButton = QAction(self) self.runScriptEditorButton.setCheckable(False) self.runScriptEditorButton.setEnabled(True) self.runScriptEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconRunScriptConsole.png")) self.runScriptEditorButton.setMenuRole(QAction.PreferencesRole) self.runScriptEditorButton.setIconVisibleInMenu(True) self.runScriptEditorButton.setToolTip(runScriptEditorBt) self.runScriptEditorButton.setText(runScriptEditorBt) ## Action Run Script (subprocess) commentEditorBt = QCoreApplication.translate("PythonConsole", "Comment") self.commentEditorButton = QAction(self) self.commentEditorButton.setCheckable(False) self.commentEditorButton.setEnabled(True) self.commentEditorButton.setIcon( QgsApplication.getThemeIcon( "console/iconCommentEditorConsole.png")) self.commentEditorButton.setMenuRole(QAction.PreferencesRole) self.commentEditorButton.setIconVisibleInMenu(True) self.commentEditorButton.setToolTip(commentEditorBt) self.commentEditorButton.setText(commentEditorBt) ## Action Run Script (subprocess) uncommentEditorBt = QCoreApplication.translate("PythonConsole", "Uncomment") self.uncommentEditorButton = QAction(self) self.uncommentEditorButton.setCheckable(False) self.uncommentEditorButton.setEnabled(True) self.uncommentEditorButton.setIcon( QgsApplication.getThemeIcon( "console/iconUncommentEditorConsole.png")) self.uncommentEditorButton.setMenuRole(QAction.PreferencesRole) self.uncommentEditorButton.setIconVisibleInMenu(True) self.uncommentEditorButton.setToolTip(uncommentEditorBt) self.uncommentEditorButton.setText(uncommentEditorBt) ## Action for Object browser objList = QCoreApplication.translate("PythonConsole", "Object Inspector") self.objectListButton = QAction(self) self.objectListButton.setCheckable(True) self.objectListButton.setEnabled( self.settings.value("pythonConsole/enableObjectInsp", False, type=bool)) self.objectListButton.setIcon( QgsApplication.getThemeIcon("console/iconClassBrowserConsole.png")) self.objectListButton.setMenuRole(QAction.PreferencesRole) self.objectListButton.setIconVisibleInMenu(True) self.objectListButton.setToolTip(objList) self.objectListButton.setText(objList) ## Action for Find text findText = QCoreApplication.translate("PythonConsole", "Find Text") self.findTextButton = QAction(self) self.findTextButton.setCheckable(True) self.findTextButton.setEnabled(True) self.findTextButton.setIcon( QgsApplication.getThemeIcon("console/iconSearchEditorConsole.png")) self.findTextButton.setMenuRole(QAction.PreferencesRole) self.findTextButton.setIconVisibleInMenu(True) self.findTextButton.setToolTip(findText) self.findTextButton.setText(findText) ##----------------Toolbar Console------------------------------------- ## Action Show Editor showEditor = QCoreApplication.translate("PythonConsole", "Show editor") self.showEditorButton = QAction(self) self.showEditorButton.setEnabled(True) self.showEditorButton.setCheckable(True) self.showEditorButton.setIcon( QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.showEditorButton.setMenuRole(QAction.PreferencesRole) self.showEditorButton.setIconVisibleInMenu(True) self.showEditorButton.setToolTip(showEditor) self.showEditorButton.setText(showEditor) ## Action for Clear button clearBt = QCoreApplication.translate("PythonConsole", "Clear console") self.clearButton = QAction(self) self.clearButton.setCheckable(False) self.clearButton.setEnabled(True) self.clearButton.setIcon( QgsApplication.getThemeIcon("console/iconClearConsole.png")) self.clearButton.setMenuRole(QAction.PreferencesRole) self.clearButton.setIconVisibleInMenu(True) self.clearButton.setToolTip(clearBt) self.clearButton.setText(clearBt) ## Action for settings optionsBt = QCoreApplication.translate("PythonConsole", "Settings") self.optionsButton = QAction(self) self.optionsButton.setCheckable(False) self.optionsButton.setEnabled(True) self.optionsButton.setIcon( QgsApplication.getThemeIcon("console/iconSettingsConsole.png")) self.optionsButton.setMenuRole(QAction.PreferencesRole) self.optionsButton.setIconVisibleInMenu(True) self.optionsButton.setToolTip(optionsBt) self.optionsButton.setText(optionsBt) ## Action menu for class actionClassBt = QCoreApplication.translate("PythonConsole", "Import Class") self.actionClass = QAction(self) self.actionClass.setCheckable(False) self.actionClass.setEnabled(True) self.actionClass.setIcon( QgsApplication.getThemeIcon("console/iconClassConsole.png")) self.actionClass.setMenuRole(QAction.PreferencesRole) self.actionClass.setIconVisibleInMenu(True) self.actionClass.setToolTip(actionClassBt) self.actionClass.setText(actionClassBt) ## Import Processing class loadProcessingBt = QCoreApplication.translate( "PythonConsole", "Import Processing class") self.loadProcessingButton = QAction(self) self.loadProcessingButton.setCheckable(False) self.loadProcessingButton.setEnabled(True) self.loadProcessingButton.setIcon( QgsApplication.getThemeIcon("console/iconProcessingConsole.png")) self.loadProcessingButton.setMenuRole(QAction.PreferencesRole) self.loadProcessingButton.setIconVisibleInMenu(True) self.loadProcessingButton.setToolTip(loadProcessingBt) self.loadProcessingButton.setText(loadProcessingBt) ## Import QtCore class loadQtCoreBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtCore class") self.loadQtCoreButton = QAction(self) self.loadQtCoreButton.setCheckable(False) self.loadQtCoreButton.setEnabled(True) self.loadQtCoreButton.setIcon( QgsApplication.getThemeIcon("console/iconQtCoreConsole.png")) self.loadQtCoreButton.setMenuRole(QAction.PreferencesRole) self.loadQtCoreButton.setIconVisibleInMenu(True) self.loadQtCoreButton.setToolTip(loadQtCoreBt) self.loadQtCoreButton.setText(loadQtCoreBt) ## Import QtGui class loadQtGuiBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtGui class") self.loadQtGuiButton = QAction(self) self.loadQtGuiButton.setCheckable(False) self.loadQtGuiButton.setEnabled(True) self.loadQtGuiButton.setIcon( QgsApplication.getThemeIcon("console/iconQtGuiConsole.png")) self.loadQtGuiButton.setMenuRole(QAction.PreferencesRole) self.loadQtGuiButton.setIconVisibleInMenu(True) self.loadQtGuiButton.setToolTip(loadQtGuiBt) self.loadQtGuiButton.setText(loadQtGuiBt) ## Action for Run script runBt = QCoreApplication.translate("PythonConsole", "Run command") self.runButton = QAction(self) self.runButton.setCheckable(False) self.runButton.setEnabled(True) self.runButton.setIcon( QgsApplication.getThemeIcon("console/iconRunConsole.png")) self.runButton.setMenuRole(QAction.PreferencesRole) self.runButton.setIconVisibleInMenu(True) self.runButton.setToolTip(runBt) self.runButton.setText(runBt) ## Help action helpBt = QCoreApplication.translate("PythonConsole", "Help") self.helpButton = QAction(self) self.helpButton.setCheckable(False) self.helpButton.setEnabled(True) self.helpButton.setIcon( QgsApplication.getThemeIcon("console/iconHelpConsole.png")) self.helpButton.setMenuRole(QAction.PreferencesRole) self.helpButton.setIconVisibleInMenu(True) self.helpButton.setToolTip(helpBt) self.helpButton.setText(helpBt) self.toolBar = QToolBar() self.toolBar.setEnabled(True) self.toolBar.setFocusPolicy(Qt.NoFocus) self.toolBar.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBar.setLayoutDirection(Qt.LeftToRight) self.toolBar.setIconSize(QSize(16, 16)) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.addAction(self.clearButton) self.toolBar.addAction(self.actionClass) self.toolBar.addAction(self.runButton) self.toolBar.addSeparator() self.toolBar.addAction(self.showEditorButton) self.toolBar.addSeparator() self.toolBar.addAction(self.optionsButton) self.toolBar.addAction(self.helpButton) self.toolBarEditor = QToolBar() self.toolBarEditor.setEnabled(False) self.toolBarEditor.setFocusPolicy(Qt.NoFocus) self.toolBarEditor.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBarEditor.setLayoutDirection(Qt.LeftToRight) self.toolBarEditor.setIconSize(QSize(16, 16)) self.toolBarEditor.setMovable(False) self.toolBarEditor.setFloatable(False) self.toolBarEditor.addAction(self.openFileButton) self.toolBarEditor.addAction(self.openInEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.saveFileButton) self.toolBarEditor.addAction(self.saveAsFileButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.runScriptEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.findTextButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.cutEditorButton) self.toolBarEditor.addAction(self.copyEditorButton) self.toolBarEditor.addAction(self.pasteEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.commentEditorButton) self.toolBarEditor.addAction(self.uncommentEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.objectListButton) ## Menu Import Class self.classMenu = QMenu() self.classMenu.addAction(self.loadProcessingButton) self.classMenu.addAction(self.loadQtCoreButton) self.classMenu.addAction(self.loadQtGuiButton) cM = self.toolBar.widgetForAction(self.actionClass) cM.setMenu(self.classMenu) cM.setPopupMode(QToolButton.InstantPopup) self.widgetButton = QWidget() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.widgetButton.sizePolicy().hasHeightForWidth()) self.widgetButton.setSizePolicy(sizePolicy) self.widgetButtonEditor = QWidget(self.widgetEditor) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.widgetButtonEditor.sizePolicy().hasHeightForWidth()) self.widgetButtonEditor.setSizePolicy(sizePolicy) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.shellOut.sizePolicy().hasHeightForWidth()) self.shellOut.setSizePolicy(sizePolicy) self.shellOut.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.shell.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) ##------------ Layout ------------------------------- self.mainLayout = QGridLayout(self) self.mainLayout.setMargin(0) self.mainLayout.setSpacing(0) self.mainLayout.addWidget(self.widgetButton, 0, 0, 1, 1) self.mainLayout.addWidget(self.splitterEditor, 0, 1, 1, 1) self.shellOutWidget.layout().insertWidget(0, self.toolBar) self.layoutEditor = QGridLayout(self.widgetEditor) self.layoutEditor.setMargin(0) self.layoutEditor.setSpacing(0) self.layoutEditor.addWidget(self.toolBarEditor, 0, 1, 1, 1) self.layoutEditor.addWidget(self.widgetButtonEditor, 1, 0, 2, 1) self.layoutEditor.addWidget(self.tabEditorWidget, 1, 1, 1, 1) self.layoutEditor.addWidget(self.widgetFind, 2, 1, 1, 1) ## Layout for the find widget self.layoutFind = QGridLayout(self.widgetFind) self.layoutFind.setContentsMargins(0, 0, 0, 0) self.lineEditFind = QgsFilterLineEdit() placeHolderTxt = QCoreApplication.translate("PythonConsole", "Enter text to find...") if pyqtconfig.Configuration().qt_version >= 0x40700: self.lineEditFind.setPlaceholderText(placeHolderTxt) else: self.lineEditFind.setToolTip(placeHolderTxt) self.findNextButton = QToolButton() self.findNextButton.setEnabled(False) toolTipfindNext = QCoreApplication.translate("PythonConsole", "Find Next") self.findNextButton.setToolTip(toolTipfindNext) self.findNextButton.setIcon( QgsApplication.getThemeIcon( "console/iconSearchNextEditorConsole.png")) self.findNextButton.setIconSize(QSize(24, 24)) self.findNextButton.setAutoRaise(True) self.findPrevButton = QToolButton() self.findPrevButton.setEnabled(False) toolTipfindPrev = QCoreApplication.translate("PythonConsole", "Find Previous") self.findPrevButton.setToolTip(toolTipfindPrev) self.findPrevButton.setIcon( QgsApplication.getThemeIcon( "console/iconSearchPrevEditorConsole.png")) self.findPrevButton.setIconSize(QSize(24, 24)) self.findPrevButton.setAutoRaise(True) self.caseSensitive = QCheckBox() caseSensTr = QCoreApplication.translate("PythonConsole", "Case Sensitive") self.caseSensitive.setText(caseSensTr) self.wholeWord = QCheckBox() wholeWordTr = QCoreApplication.translate("PythonConsole", "Whole Word") self.wholeWord.setText(wholeWordTr) self.wrapAround = QCheckBox() self.wrapAround.setChecked(True) wrapAroundTr = QCoreApplication.translate("PythonConsole", "Wrap Around") self.wrapAround.setText(wrapAroundTr) self.layoutFind.addWidget(self.lineEditFind, 0, 1, 1, 1) self.layoutFind.addWidget(self.findPrevButton, 0, 2, 1, 1) self.layoutFind.addWidget(self.findNextButton, 0, 3, 1, 1) self.layoutFind.addWidget(self.caseSensitive, 0, 4, 1, 1) self.layoutFind.addWidget(self.wholeWord, 0, 5, 1, 1) self.layoutFind.addWidget(self.wrapAround, 0, 6, 1, 1) ##------------ Add first Tab in Editor ------------------------------- #self.tabEditorWidget.newTabEditor(tabName='first', filename=None) ##------------ Signal ------------------------------- self.findTextButton.toggled.connect(self.findTextEditor) self.objectListButton.toggled.connect(self.toggleObjectListWidget) self.commentEditorButton.triggered.connect(self.commentCode) self.uncommentEditorButton.triggered.connect(self.uncommentCode) self.runScriptEditorButton.triggered.connect(self.runScriptEditor) self.cutEditorButton.triggered.connect(self.cutEditor) self.copyEditorButton.triggered.connect(self.copyEditor) self.pasteEditorButton.triggered.connect(self.pasteEditor) self.showEditorButton.toggled.connect(self.toggleEditor) self.clearButton.triggered.connect(self.shellOut.clearConsole) self.optionsButton.triggered.connect(self.openSettings) self.loadProcessingButton.triggered.connect(self.processing) self.loadQtCoreButton.triggered.connect(self.qtCore) self.loadQtGuiButton.triggered.connect(self.qtGui) self.runButton.triggered.connect(self.shell.entered) self.openFileButton.triggered.connect(self.openScriptFile) self.openInEditorButton.triggered.connect(self.openScriptFileExtEditor) self.saveFileButton.triggered.connect(self.saveScriptFile) self.saveAsFileButton.triggered.connect(self.saveAsScriptFile) self.helpButton.triggered.connect(self.openHelp) self.connect(self.listClassMethod, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), self.onClickGoToLine) self.lineEditFind.returnPressed.connect(self._findText) self.findNextButton.clicked.connect(self._findNext) self.findPrevButton.clicked.connect(self._findPrev) self.lineEditFind.textChanged.connect(self._textFindChanged)