eric7/EricWidgets/EricSideBar.py

branch
eric7
changeset 8583
aac629a05f8b
parent 8579
cfd0e44ef084
child 8584
90391fda03d5
--- a/eric7/EricWidgets/EricSideBar.py	Sun Sep 05 18:07:03 2021 +0200
+++ b/eric7/EricWidgets/EricSideBar.py	Mon Sep 06 19:52:37 2021 +0200
@@ -10,14 +10,11 @@
 import enum
 import json
 
-from PyQt6.QtCore import QEvent, QSize, Qt, QTimer
-from PyQt6.QtWidgets import (
-    QTabBar, QWidget, QStackedWidget, QBoxLayout, QToolButton, QSizePolicy
-)
+from PyQt6.QtCore import pyqtSlot, Qt, QSize
+from PyQt6.QtGui import QIcon
+from PyQt6.QtWidgets import QWidget, QStackedWidget, QBoxLayout
 
-from EricWidgets.EricApplication import ericApp
-
-import UI.PixmapCache
+from .EricIconBar import EricIconBar
 
 
 class EricSideBarSide(enum.Enum):
@@ -30,60 +27,37 @@
     WEST = 3
 
 
-# TODO: change to used a QListWidget with icons (48px) instead of QTabBar and
-#       remove the auto hide/show feature (?)
 class EricSideBar(QWidget):
     """
     Class implementing a sidebar with a widget area, that is hidden or shown,
     if the current tab is clicked again.
     """
-    Version = 2
+    Version = 3
     
-    def __init__(self, orientation=None, delay=200, parent=None):
+    def __init__(self, orientation=None, parent=None):
         """
         Constructor
         
         @param orientation orientation of the sidebar widget
         @type EricSideBarSide
-        @param delay value for the expand/shrink delay in milliseconds
-        @type int
         @param parent parent widget
         @type QWidget
         """
         super().__init__(parent)
         
-        self.__tabBar = QTabBar()
-        self.__tabBar.setDrawBase(True)
-        self.__tabBar.setShape(QTabBar.Shape.RoundedNorth)
-        self.__tabBar.setUsesScrollButtons(True)
-        self.__tabBar.setDrawBase(False)
+        # initial layout is done for NORTH
+        self.__iconBar = EricIconBar(Qt.Orientation.Horizontal)
+        
         self.__stackedWidget = QStackedWidget(self)
         self.__stackedWidget.setContentsMargins(0, 0, 0, 0)
-        self.__autoHideButton = QToolButton()
-        self.__autoHideButton.setCheckable(True)
-        self.__autoHideButton.setIcon(
-            UI.PixmapCache.getIcon("autoHideOff"))
-        self.__autoHideButton.setChecked(True)
-        self.__autoHideButton.setToolTip(
-            self.tr("Deselect to activate automatic collapsing"))
-        self.barLayout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
-        self.barLayout.setContentsMargins(0, 0, 0, 0)
+        
         self.layout = QBoxLayout(QBoxLayout.Direction.TopToBottom)
         self.layout.setContentsMargins(0, 0, 0, 0)
         self.layout.setSpacing(0)
-        self.barLayout.addWidget(self.__autoHideButton)
-        self.barLayout.addWidget(self.__tabBar)
-        self.layout.addLayout(self.barLayout)
+        self.layout.addWidget(self.__iconBar)
         self.layout.addWidget(self.__stackedWidget)
         self.setLayout(self.layout)
         
-        # initialize the delay timer
-        self.__actionMethod = None
-        self.__delayTimer = QTimer(self)
-        self.__delayTimer.setSingleShot(True)
-        self.__delayTimer.setInterval(delay)
-        self.__delayTimer.timeout.connect(self.__delayedAction)
-        
         self.__minimized = False
         self.__minSize = 0
         self.__maxSize = 0
@@ -96,17 +70,17 @@
         # flag storing if this widget or any child has the focus
         self.__autoHide = False
         
-        self.__tabBar.installEventFilter(self)
-        
         self.__orientation = EricSideBarSide.NORTH
         if orientation is None:
             orientation = EricSideBarSide.NORTH
         self.setOrientation(orientation)
         
-        self.__tabBar.currentChanged[int].connect(
+        self.__iconBar.currentChanged.connect(
             self.__stackedWidget.setCurrentIndex)
-        ericApp().focusChanged.connect(self.__appFocusChanged)
-        self.__autoHideButton.toggled[bool].connect(self.__autoHideToggled)
+        self.__iconBar.currentChanged.connect(
+            self.__currentIconChanged)
+        self.__iconBar.currentClicked.connect(
+            self.__currentIconClicked)
     
     def setSplitter(self, splitter):
         """
@@ -130,47 +104,6 @@
         if self.splitter:
             self.splitterSizes = self.splitter.sizes()
     
-    def __delayedAction(self):
-        """
-        Private slot to handle the firing of the delay timer.
-        """
-        if self.__actionMethod is not None:
-            self.__actionMethod()
-    
-    def setDelay(self, delay):
-        """
-        Public method to set the delay value for the expand/shrink delay in
-        milliseconds.
-        
-        @param delay value for the expand/shrink delay in milliseconds
-            (integer)
-        """
-        self.__delayTimer.setInterval(delay)
-    
-    def delay(self):
-        """
-        Public method to get the delay value for the expand/shrink delay in
-        milliseconds.
-        
-        @return value for the expand/shrink delay in milliseconds (integer)
-        """
-        return self.__delayTimer.interval()
-    
-    def __cancelDelayTimer(self):
-        """
-        Private method to cancel the current delay timer.
-        """
-        self.__delayTimer.stop()
-        self.__actionMethod = None
-    
-    def shrink(self):
-        """
-        Public method to record a shrink request.
-        """
-        self.__delayTimer.stop()
-        self.__actionMethod = self.__shrinkIt
-        self.__delayTimer.start()
-   
     def __shrinkIt(self):
         """
         Private method to shrink the sidebar.
@@ -193,19 +126,9 @@
         if self.__orientation in (
             EricSideBarSide.NORTH, EricSideBarSide.SOUTH
         ):
-            self.setFixedHeight(self.__tabBar.minimumSizeHint().height())
+            self.setFixedHeight(self.__iconBar.minimumSizeHint().height())
         else:
-            self.setFixedWidth(self.__tabBar.minimumSizeHint().width())
-        
-        self.__actionMethod = None
-    
-    def expand(self):
-        """
-        Public method to record a expand request.
-        """
-        self.__delayTimer.stop()
-        self.__actionMethod = self.__expandIt
-        self.__delayTimer.start()
+            self.setFixedWidth(self.__iconBar.minimumSizeHint().width())
     
     def __expandIt(self):
         """
@@ -226,8 +149,6 @@
             self.setMaximumWidth(self.__maxSize)
         if self.splitter:
             self.splitter.setSizes(self.splitterSizes)
-        
-        self.__actionMethod = None
     
     def isMinimized(self):
         """
@@ -237,63 +158,44 @@
         """
         return self.__minimized
     
-    def isAutoHiding(self):
-        """
-        Public method to check, if the auto hide function is active.
-        
-        @return flag indicating the state of auto hiding (boolean)
+    @pyqtSlot(int)
+    def __currentIconChanged(self, index):
         """
-        return self.__autoHide
-    
-    def eventFilter(self, obj, evt):
-        """
-        Public method to handle some events for the tabbar.
+        Private slot to handle a change of the current icon.
         
-        @param obj reference to the object (QObject)
-        @param evt reference to the event object (QEvent)
-        @return flag indicating, if the event was handled (boolean)
+        @param index index of the current icon
+        @type int
         """
-        if obj == self.__tabBar:
-            if evt.type() == QEvent.Type.MouseButtonPress:
-                pos = evt.position().toPoint()
-                for i in range(self.__tabBar.count()):
-                    if self.__tabBar.tabRect(i).contains(pos):
-                        break
-                
-                if i == self.__tabBar.currentIndex():
-                    if self.isMinimized():
-                        self.expand()
-                    else:
-                        self.shrink()
-                    return True
-                elif self.isMinimized():
-                    self.expand()
-            elif evt.type() == QEvent.Type.Wheel:
-                delta = evt.angleDelta().y()
-                if delta > 0:
-                    self.prevTab()
-                else:
-                    self.nextTab()
-                return True
+        if self.isMinimized():
+            self.__expandIt()
+    
+    @pyqtSlot(int)
+    def __currentIconClicked(self, index):
+        """
+        Private slot to handle a click of the current icon.
         
-        return QWidget.eventFilter(self, obj, evt)
+        @param index index of the clicked icon
+        @type int
+        """
+        if self.isMinimized():
+            self.__expandIt()
+        else:
+            self.__shrinkIt()
     
-    def addTab(self, widget, iconOrLabel, label=None):
+    def addTab(self, widget, icon, label=None):
         """
         Public method to add a tab to the sidebar.
         
-        @param widget reference to the widget to add (QWidget)
-        @param iconOrLabel reference to the icon or the label text of the tab
-            (QIcon, string)
-        @param label the labeltext of the tab (string) (only to be
-            used, if the second parameter is a QIcon)
+        @param widget reference to the widget to add
+        @type QWidget
+        @param icon reference to the icon of the widget
+        @type QIcon or QPixmap
+        @param label the label text of the widget
+        @type str
         """
-        if label:
-            index = self.__tabBar.addTab(iconOrLabel, label)
-            self.__tabBar.setTabToolTip(index, label)
-        else:
-            index = self.__tabBar.addTab(iconOrLabel)
-            self.__tabBar.setTabToolTip(index, iconOrLabel)
+        if isinstance(icon, QIcon):
+            icon = icon.pixmap(48, 48)
+        self.__iconBar.addIcon(icon, label)
         self.__stackedWidget.addWidget(widget)
         if self.__orientation in (
             EricSideBarSide.NORTH, EricSideBarSide.SOUTH
@@ -302,23 +204,23 @@
         else:
             self.__minSize = self.minimumSizeHint().width()
     
-    def insertTab(self, index, widget, iconOrLabel, label=None):
+    def insertTab(self, index, widget, icon, label=None):
         """
         Public method to insert a tab into the sidebar.
         
-        @param index the index to insert the tab at (integer)
-        @param widget reference to the widget to insert (QWidget)
-        @param iconOrLabel reference to the icon or the labeltext of the tab
-            (QIcon, string)
-        @param label the labeltext of the tab (string) (only to be
-            used, if the second parameter is a QIcon)
+        @param index the index to insert the tab at
+        @type int
+        @param widget reference to the widget to insert
+        @type QWidget
+        @param icon reference to the icon of the widget
+        @type QIcon or QPixmap
+        @param label the label text of the widget
+        @type str
         """
-        if label:
-            index = self.__tabBar.insertTab(index, iconOrLabel, label)
-            self.__tabBar.setTabToolTip(index, label)
-        else:
-            index = self.__tabBar.insertTab(index, iconOrLabel)
-            self.__tabBar.setTabToolTip(index, iconOrLabel)
+        if isinstance(icon, QIcon):
+            icon = icon.pixmap(48, 48)
+        self.__iconBar.insertIcon(index, icon, label)
+        
         self.__stackedWidget.insertWidget(index, widget)
         if self.__orientation in (
             EricSideBarSide.NORTH, EricSideBarSide.SOUTH
@@ -331,10 +233,11 @@
         """
         Public method to remove a tab.
         
-        @param index the index of the tab to remove (integer)
+        @param index the index of the tab to remove
+        @type int
         """
         self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
-        self.__tabBar.removeTab(index)
+        self.__iconBar.removeIcon(index)
         if self.__orientation in (
             EricSideBarSide.NORTH, EricSideBarSide.SOUTH
         ):
@@ -377,7 +280,7 @@
         
         @return number of tabs in the sidebar (integer)
         """
-        return self.__tabBar.count()
+        return self.__iconBar.count()
     
     def currentIndex(self):
         """
@@ -393,10 +296,10 @@
         
         @param index the index to set as the current index (integer)
         """
-        self.__tabBar.setCurrentIndex(index)
+        self.__iconBar.setCurrentIndex(index)
         self.__stackedWidget.setCurrentIndex(index)
         if self.isMinimized():
-            self.expand()
+            self.__expandIt()
     
     def currentWidget(self):
         """
@@ -414,9 +317,9 @@
             (QWidget)
         """
         self.__stackedWidget.setCurrentWidget(widget)
-        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
+        self.__iconBar.setCurrentIndex(self.__stackedWidget.currentIndex())
         if self.isMinimized():
-            self.expand()
+            self.__expandIt()
     
     def indexOf(self, widget):
         """
@@ -427,24 +330,6 @@
         """
         return self.__stackedWidget.indexOf(widget)
     
-    def isTabEnabled(self, index):
-        """
-        Public method to check, if a tab is enabled.
-        
-        @param index index of the tab to check (integer)
-        @return flag indicating the enabled state (boolean)
-        """
-        return self.__tabBar.isTabEnabled(index)
-    
-    def setTabEnabled(self, index, enabled):
-        """
-        Public method to set the enabled state of a tab.
-        
-        @param index index of the tab to set (integer)
-        @param enabled enabled state to set (boolean)
-        """
-        self.__tabBar.setTabEnabled(index, enabled)
-    
     def orientation(self):
         """
         Public method to get the orientation of the sidebar.
@@ -462,109 +347,19 @@
         @type EricSideBarSide
         """
         if orient == EricSideBarSide.NORTH:
-            self.__tabBar.setShape(QTabBar.Shape.RoundedNorth)
-            self.__tabBar.setSizePolicy(
-                QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
-            self.barLayout.setDirection(QBoxLayout.Direction.LeftToRight)
+            self.__iconBar.setOrientation(Qt.Orientation.Horizontal)
             self.layout.setDirection(QBoxLayout.Direction.TopToBottom)
-            self.layout.setAlignment(self.barLayout,
-                                     Qt.AlignmentFlag.AlignLeft)
         elif orient == EricSideBarSide.EAST:
-            self.__tabBar.setShape(QTabBar.Shape.RoundedEast)
-            self.__tabBar.setSizePolicy(
-                QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding)
-            self.barLayout.setDirection(QBoxLayout.Direction.TopToBottom)
+            self.__iconBar.setOrientation(Qt.Orientation.Vertical)
             self.layout.setDirection(QBoxLayout.Direction.RightToLeft)
-            self.layout.setAlignment(self.barLayout, Qt.AlignmentFlag.AlignTop)
         elif orient == EricSideBarSide.SOUTH:
-            self.__tabBar.setShape(QTabBar.Shape.RoundedSouth)
-            self.__tabBar.setSizePolicy(
-                QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
-            self.barLayout.setDirection(QBoxLayout.Direction.LeftToRight)
+            self.__iconBar.setOrientation(Qt.Orientation.Horizontal)
             self.layout.setDirection(QBoxLayout.Direction.BottomToTop)
-            self.layout.setAlignment(self.barLayout,
-                                     Qt.AlignmentFlag.AlignLeft)
         elif orient == EricSideBarSide.WEST:
-            self.__tabBar.setShape(QTabBar.Shape.RoundedWest)
-            self.__tabBar.setSizePolicy(
-                QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding)
-            self.barLayout.setDirection(QBoxLayout.Direction.TopToBottom)
+            self.__iconBar.setOrientation(Qt.Orientation.Vertical)
             self.layout.setDirection(QBoxLayout.Direction.LeftToRight)
-            self.layout.setAlignment(self.barLayout, Qt.AlignmentFlag.AlignTop)
         self.__orientation = orient
     
-    def tabIcon(self, index):
-        """
-        Public method to get the icon of a tab.
-        
-        @param index index of the tab (integer)
-        @return icon of the tab (QIcon)
-        """
-        return self.__tabBar.tabIcon(index)
-    
-    def setTabIcon(self, index, icon):
-        """
-        Public method to set the icon of a tab.
-        
-        @param index index of the tab (integer)
-        @param icon icon to be set (QIcon)
-        """
-        self.__tabBar.setTabIcon(index, icon)
-    
-    def tabText(self, index):
-        """
-        Public method to get the text of a tab.
-        
-        @param index index of the tab (integer)
-        @return text of the tab (string)
-        """
-        return self.__tabBar.tabText(index)
-    
-    def setTabText(self, index, text):
-        """
-        Public method to set the text of a tab.
-        
-        @param index index of the tab (integer)
-        @param text text to set (string)
-        """
-        self.__tabBar.setTabText(index, text)
-    
-    def tabToolTip(self, index):
-        """
-        Public method to get the tooltip text of a tab.
-        
-        @param index index of the tab (integer)
-        @return tooltip text of the tab (string)
-        """
-        return self.__tabBar.tabToolTip(index)
-    
-    def setTabToolTip(self, index, tip):
-        """
-        Public method to set the tooltip text of a tab.
-        
-        @param index index of the tab (integer)
-        @param tip tooltip text to set (string)
-        """
-        self.__tabBar.setTabToolTip(index, tip)
-    
-    def tabWhatsThis(self, index):
-        """
-        Public method to get the WhatsThis text of a tab.
-        
-        @param index index of the tab (integer)
-        @return WhatsThis text of the tab (string)
-        """
-        return self.__tabBar.tabWhatsThis(index)
-    
-    def setTabWhatsThis(self, index, text):
-        """
-        Public method to set the WhatsThis text of a tab.
-        
-        @param index index of the tab (integer)
-        @param text WhatsThis text to set (string)
-        """
-        self.__tabBar.setTabWhatsThis(index, text)
-    
     def widget(self, index):
         """
         Public method to get a reference to the widget associated with a tab.
@@ -574,6 +369,24 @@
         """
         return self.__stackedWidget.widget(index)
     
+    def setIconBarColor(self, color):
+        """
+        Public method to set the icon bar color.
+        
+        @param color icon bar color
+        @type QColor
+        """
+        self.__iconBar.setColor(color)
+    
+    def iconBarColor(self):
+        """
+        Public method to get the icon bar color.
+        
+        @return icon bar color
+        @rtype QColor
+        """
+        return self.__iconBar.color()
+    
     def saveState(self):
         """
         Public method to save the state of the sidebar.
@@ -600,7 +413,6 @@
             "min_size": self.__minSize,
             "max_size": self.__maxSize,
             "splitter_sizes": self.splitterSizes,
-            "auto_hide": self.__autoHide
         }
         data = json.dumps(dataDict)
         
@@ -633,90 +445,18 @@
             minSize = self.layout.minimumSize().width()
             maxSize = self.maximumWidth()
         
-        if stateDict["version"] == 2:
+        if stateDict["version"] in (2, 3):
             if stateDict["minimized"] and not self.__minimized:
-                self.shrink()
+                self.__shrinkIt()
             
             self.__bigSize = QSize(*stateDict["big_size"])
             self.__minSize = max(stateDict["min_size"], minSize)
             self.__maxSize = max(stateDict["max_size"], maxSize)
             self.splitterSizes = stateDict["splitter_sizes"]
             
-            self.__autoHide = stateDict["auto_hide"]
-            self.__autoHideButton.setChecked(not self.__autoHide)
-            
             if not stateDict["minimized"]:
-                self.expand()
+                self.__expandIt()
             
             return True
         
         return False
-    
-    #######################################################################
-    ## methods below implement the autohide functionality
-    #######################################################################
-    
-    def __autoHideToggled(self, checked):
-        """
-        Private slot to handle the toggling of the autohide button.
-        
-        @param checked flag indicating the checked state of the button
-            (boolean)
-        """
-        self.__autoHide = not checked
-        if self.__autoHide:
-            self.__autoHideButton.setIcon(
-                UI.PixmapCache.getIcon("autoHideOn"))
-        else:
-            self.__autoHideButton.setIcon(
-                UI.PixmapCache.getIcon("autoHideOff"))
-    
-    def __appFocusChanged(self, old, now):
-        """
-        Private slot to handle a change of the focus.
-        
-        @param old reference to the widget, that lost focus (QWidget or None)
-        @param now reference to the widget having the focus (QWidget or None)
-        """
-        if isinstance(now, QWidget):
-            self.__hasFocus = self.isAncestorOf(now)
-            if (
-                self.__autoHide and
-                not self.__hasFocus and
-                not self.isMinimized()
-            ):
-                self.shrink()
-            elif self.__autoHide and self.__hasFocus and self.isMinimized():
-                self.expand()
-    
-    def enterEvent(self, event):
-        """
-        Protected method to handle the mouse entering this widget.
-        
-        @param event reference to the event (QEvent)
-        """
-        if self.__autoHide and self.isMinimized():
-            self.expand()
-        else:
-            self.__cancelDelayTimer()
-    
-    def leaveEvent(self, event):
-        """
-        Protected method to handle the mouse leaving this widget.
-        
-        @param event reference to the event (QEvent)
-        """
-        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
-            self.shrink()
-        else:
-            self.__cancelDelayTimer()
-    
-    def shutdown(self):
-        """
-        Public method to shut down the object.
-        
-        This method does some preparations so the object can be deleted
-        properly. It disconnects from the focusChanged signal in order to
-        avoid trouble later on.
-        """
-        ericApp().focusChanged.disconnect(self.__appFocusChanged)

eric ide

mercurial