eric6/E5Gui/E5TreeWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/E5Gui/E5TreeWidget.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,281 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing specialized tree views.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSignal, Qt
+from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QAbstractItemView
+
+
+class E5TreeWidget(QTreeWidget):
+    """
+    Class implementing an extended tree widget.
+    
+    @signal itemControlClicked(QTreeWidgetItem) emitted after a Ctrl-Click
+            on an item
+    @signal itemMiddleButtonClicked(QTreeWidgetItem) emitted after a click
+            of the middle button on an item
+    """
+    ItemsCollapsed = 0
+    ItemsExpanded = 1
+    
+    itemControlClicked = pyqtSignal(QTreeWidgetItem)
+    itemMiddleButtonClicked = pyqtSignal(QTreeWidgetItem)
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(E5TreeWidget, self).__init__(parent)
+        
+        self.__refreshAllItemsNeeded = True
+        self.__allTreeItems = []
+        self.__showMode = E5TreeWidget.ItemsCollapsed
+        
+        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
+        
+        self.itemChanged.connect(self.__scheduleRefresh)
+    
+    def setDefaultItemShowMode(self, mode):
+        """
+        Public method to set the default item show mode.
+        
+        @param mode default mode (ItemsCollapsed, ItemsExpanded)
+        """
+        assert mode in [E5TreeWidget.ItemsCollapsed,
+                        E5TreeWidget.ItemsExpanded]
+        
+        self.__showMode = mode
+    
+    def allItems(self):
+        """
+        Public method to get a list of all items.
+        
+        @return list of all items (list of QTreeWidgetItem)
+        """
+        if self.__refreshAllItemsNeeded:
+            self.__allTreeItems = []
+            self.__iterateAllItems(None)
+            self.__refreshAllItemsNeeded = False
+        
+        return self.__allTreeItems
+    
+    def appendToParentItem(self, parent, item):
+        """
+        Public method to append an item to a parent item.
+        
+        @param parent text of the parent item (string) or
+            the parent item (QTreeWidgetItem)
+        @param item item to be appended (QTreeWidgetItem)
+        @return flag indicating success (boolean)
+        @exception RuntimeError raised to indicate an illegal type for
+            the parent
+        """
+        if isinstance(parent, QTreeWidgetItem):
+            if parent is None or parent.treeWidget() != self:
+                return False
+            parentItem = parent
+        elif isinstance(parent, str):
+            lst = self.findItems(parent, Qt.MatchExactly)
+            if not lst:
+                return False
+            parentItem = lst[0]
+            if parentItem is None:
+                return False
+        else:
+            raise RuntimeError("illegal type for parent")
+        
+        self.__allTreeItems.append(item)
+        parentItem.addChild(item)
+        return True
+    
+    def prependToParentItem(self, parent, item):
+        """
+        Public method to prepend an item to a parent item.
+        
+        @param parent text of the parent item (string) or
+            the parent item (QTreeWidgetItem)
+        @param item item to be prepended (QTreeWidgetItem)
+        @return flag indicating success (boolean)
+        @exception RuntimeError raised to indicate an illegal type for
+            the parent
+        """
+        if isinstance(parent, QTreeWidgetItem):
+            if parent is None or parent.treeWidget() != self:
+                return False
+            parentItem = parent
+        elif isinstance(parent, str):
+            lst = self.findItems(parent, Qt.MatchExactly)
+            if not lst:
+                return False
+            parentItem = lst[0]
+            if parentItem is None:
+                return False
+        else:
+            raise RuntimeError("illegal type for parent")
+        
+        self.__allTreeItems.append(item)
+        parentItem.insertChild(0, item)
+        return True
+    
+    def addTopLevelItem(self, item):
+        """
+        Public method to add a top level item.
+        
+        @param item item to be added as a top level item (QTreeWidgetItem)
+        """
+        self.__allTreeItems.append(item)
+        super(E5TreeWidget, self).addTopLevelItem(item)
+    
+    def addTopLevelItems(self, items):
+        """
+        Public method to add a list of top level items.
+        
+        @param items items to be added as top level items
+            (list of QTreeWidgetItem)
+        """
+        self.__allTreeItems.extend(items)
+        super(E5TreeWidget, self).addTopLevelItems(items)
+    
+    def insertTopLevelItem(self, index, item):
+        """
+        Public method to insert a top level item.
+        
+        @param index index for the insertion (integer)
+        @param item item to be inserted as a top level item (QTreeWidgetItem)
+        """
+        self.__allTreeItems.append(item)
+        super(E5TreeWidget, self).insertTopLevelItem(index, item)
+    
+    def insertTopLevelItems(self, index, items):
+        """
+        Public method to insert a list of top level items.
+        
+        @param index index for the insertion (integer)
+        @param items items to be inserted as top level items
+            (list of QTreeWidgetItem)
+        """
+        self.__allTreeItems.extend(items)
+        super(E5TreeWidget, self).insertTopLevelItems(index, items)
+    
+    def deleteItem(self, item):
+        """
+        Public method to delete an item.
+        
+        @param item item to be deleted (QTreeWidgetItem)
+        """
+        if item in self.__allTreeItems:
+            self.__allTreeItems.remove(item)
+        
+        self.__refreshAllItemsNeeded = True
+        
+        del item
+    
+    def deleteItems(self, items):
+        """
+        Public method to delete a list of items.
+        
+        @param items items to be deleted (list of QTreeWidgetItem)
+        """
+        for item in items:
+            self.deleteItem(item)
+    
+    def filterString(self, filterStr):
+        """
+        Public slot to set a new filter.
+        
+        @param filterStr filter to be set (string)
+        """
+        self.expandAll()
+        allItems = self.allItems()
+        
+        if filterStr:
+            lFilter = filterStr.lower()
+            for itm in allItems:
+                itm.setHidden(lFilter not in itm.text(0).lower())
+                itm.setExpanded(True)
+            for index in range(self.topLevelItemCount()):
+                self.topLevelItem(index).setHidden(False)
+            
+            firstItm = self.topLevelItem(0)
+            belowItm = self.itemBelow(firstItm)
+            topLvlIndex = 0
+            while firstItm:
+                if lFilter in firstItm.text(0).lower():
+                    firstItm.setHidden(False)
+                elif not firstItm.parent() and not belowItm:
+                    firstItm.setHidden(True)
+                elif not belowItm:
+                    break
+                elif not firstItm.parent() and not belowItm.parent():
+                    firstItm.setHidden(True)
+                
+                topLvlIndex += 1
+                firstItm = self.topLevelItem(topLvlIndex)
+                belowItm = self.itemBelow(firstItm)
+        else:
+            for itm in allItems:
+                itm.setHidden(False)
+            for index in range(self.topLevelItemCount()):
+                self.topLevelItem(index).setHidden(False)
+            if self.__showMode == E5TreeWidget.ItemsCollapsed:
+                self.collapseAll()
+    
+    def clear(self):
+        """
+        Public slot to clear the tree.
+        """
+        self.__allTreeItems = []
+        super(E5TreeWidget, self).clear()
+    
+    def __scheduleRefresh(self):
+        """
+        Private slot to schedule a refresh of the tree.
+        """
+        self.__refreshAllItemsNeeded = True
+    
+    def mousePressEvent(self, evt):
+        """
+        Protected method handling mouse press events.
+        
+        @param evt mouse press event (QMouseEvent)
+        """
+        if evt.modifiers() == Qt.ControlModifier and \
+           evt.buttons() == Qt.LeftButton:
+            self.itemControlClicked.emit(self.itemAt(evt.pos()))
+            return
+        elif evt.buttons() == Qt.MidButton:
+            self.itemMiddleButtonClicked.emit(self.itemAt(evt.pos()))
+            return
+        else:
+            super(E5TreeWidget, self).mousePressEvent(evt)
+    
+    def __iterateAllItems(self, parent):
+        """
+        Private method to iterate over the child items of the parent.
+        
+        @param parent parent item to iterate (QTreeWidgetItem)
+        """
+        if parent:
+            count = parent.childCount()
+        else:
+            count = self.topLevelItemCount()
+        
+        for index in range(count):
+            if parent:
+                itm = parent.child(index)
+            else:
+                itm = self.topLevelItem(index)
+            
+            if itm.childCount() == 0:
+                self.__allTreeItems.append(itm)
+            
+            self.__iterateAllItems(itm)

eric ide

mercurial