eric6/QScintilla/EditorOutline.py

changeset 7685
0b6e8c0d6403
child 7686
379d402162ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/QScintilla/EditorOutline.py	Wed Sep 02 18:13:12 2020 +0200
@@ -0,0 +1,175 @@
+# -*- 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

eric ide

mercurial