Wed, 02 Sep 2020 18:13:12 +0200
Started implementing the editor outline widget.
# -*- coding: utf-8 -*- # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing an outline widget for source code navigation of the editor. """ from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QTreeView, QAbstractItemView from UI.BrowserSortFilterProxyModel import BrowserSortFilterProxyModel from UI.BrowserModel import BrowserImportsItem, BrowserGlobalsItem from .EditorOutlineModel import EditorOutlineModel # TODO: implement context menu class EditorOutlineView(QTreeView): """ Class implementing an outline widget for source code navigation of the editor. """ def __init__(self, editor, parent=None): """ Constructor @param editor reference to the editor widget @type Editor @param parent reference to the parent widget @type QWidget """ super(EditorOutlineView, self).__init__(parent) self.__editor = editor self.__model = EditorOutlineModel(editor) self.__sortModel = BrowserSortFilterProxyModel() self.__sortModel.setSourceModel(self.__model) self.setModel(self.__sortModel) self.setRootIsDecorated(True) self.setAlternatingRowColors(True) header = self.header() header.setSortIndicator(0, Qt.AscendingOrder) header.setSortIndicatorShown(True) header.setSectionsClickable(True) self.setSortingEnabled(True) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.activated.connect(self.__gotoItem) self.expanded.connect(self.__resizeColumns) self.collapsed.connect(self.__resizeColumns) self.__resizeColumns() self.__expandedNames = [] self.__currentItemName = "" def __resizeColumns(self): """ Private slot to resize the view when items get expanded or collapsed. """ self.resizeColumnToContents(0) def isPopulated(self): """ Public method to check, if the model is populated. @return flag indicating a populated model @rtype bool """ return self.__model.isPopulated() def repopulate(self): """ Public slot to repopulate the model. """ if self.isPopulated(): self.__prepareRepopulate() self.__model.repopulate() self.__completeRepopulate() def __prepareRepopulate(self): """ Private slot to prepare to repopulate the outline view. """ itm = self.__currentItem() if itm is not None: self.__currentItemName = itm.data(0) self.__expandedNames = [] childIndex = self.model().index(0, 0) while childIndex.isValid(): if self.isExpanded(childIndex): self.__expandedNames.append( self.model().item(childIndex).data(0)) childIndex = self.indexBelow(childIndex) def __completeRepopulate(self): """ Private slot to complete the repopulate of the outline view. """ childIndex = self.model().index(0, 0) while childIndex.isValid(): name = self.model().item(childIndex).data(0) if (self.__currentItemName and self.__currentItemName == name): self.setCurrentIndex(childIndex) if name in self.__expandedNames: self.setExpanded(childIndex, True) childIndex = self.indexBelow(childIndex) self.__expandedNames = [] self.__currentItemName = "" def isSupportedLanguage(self, language): """ Public method to check, if outlining a given language is supported. @param language source language to be checked @type str @return flag indicating support @rtype bool """ return language in EditorOutlineModel.SupportedLanguages def __gotoItem(self, index): """ Private slot to set the editor cursor. @param index index of the item to set the cursor for @type QModelIndex """ if index.isValid(): itm = self.model().item(index) if itm: try: lineno = itm.lineno() self.__editor.gotoLine(lineno) except AttributeError: # don't care pass def mouseDoubleClickEvent(self, mouseEvent): """ Protected method of QAbstractItemView. Reimplemented to disable expanding/collapsing of items when double-clicking. Instead the double-clicked entry is opened. @param mouseEvent the mouse event (QMouseEvent) """ index = self.indexAt(mouseEvent.pos()) if index.isValid(): itm = self.model().item(index) if isinstance(itm, (BrowserImportsItem, BrowserGlobalsItem)): self.setExpanded(index, not self.isExpanded(index)) else: self.__gotoItem(index) def __currentItem(self): """ Private method to get a reference to the current item. @return reference to the current item @rtype BrowserItem """ itm = self.model().item(self.currentIndex()) return itm