eric6/QScintilla/EditorOutline.py

Wed, 02 Sep 2020 18:13:12 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 02 Sep 2020 18:13:12 +0200
changeset 7685
0b6e8c0d6403
child 7686
379d402162ca
permissions
-rw-r--r--

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

eric ide

mercurial