eric7/E5Gui/EricSideBar.py

branch
eric7
changeset 8358
144a6b854f70
parent 8357
a081458cc57b
child 8359
0e29e54e9269
--- a/eric7/E5Gui/EricSideBar.py	Sat May 22 19:52:34 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,706 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2008 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing a sidebar class.
-"""
-
-import enum
-import json
-
-from PyQt6.QtCore import QEvent, QSize, Qt, QTimer
-from PyQt6.QtWidgets import (
-    QTabBar, QWidget, QStackedWidget, QBoxLayout, QToolButton, QSizePolicy
-)
-
-from E5Gui.EricApplication import ericApp
-
-import UI.PixmapCache
-
-
-class EricSideBarSide(enum.Enum):
-    """
-    Class defining the sidebar sides.
-    """
-    NORTH = 0
-    EAST = 1
-    SOUTH = 2
-    WEST = 3
-
-
-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
-    
-    def __init__(self, orientation=None, delay=200, 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)
-        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.__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
-        self.__bigSize = QSize()
-        
-        self.splitter = None
-        self.splitterSizes = []
-        
-        self.__hasFocus = False
-        # 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.__stackedWidget.setCurrentIndex)
-        ericApp().focusChanged.connect(self.__appFocusChanged)
-        self.__autoHideButton.toggled[bool].connect(self.__autoHideToggled)
-    
-    def setSplitter(self, splitter):
-        """
-        Public method to set the splitter managing the sidebar.
-        
-        @param splitter reference to the splitter (QSplitter)
-        """
-        self.splitter = splitter
-        self.splitter.splitterMoved.connect(self.__splitterMoved)
-        self.splitter.setChildrenCollapsible(False)
-        index = self.splitter.indexOf(self)
-        self.splitter.setCollapsible(index, False)
-    
-    def __splitterMoved(self, pos, index):
-        """
-        Private slot to react on splitter moves.
-        
-        @param pos new position of the splitter handle (integer)
-        @param index index of the splitter handle (integer)
-        """
-        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.
-        """
-        self.__minimized = True
-        self.__bigSize = self.size()
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            self.__minSize = self.minimumSizeHint().height()
-            self.__maxSize = self.maximumHeight()
-        else:
-            self.__minSize = self.minimumSizeHint().width()
-            self.__maxSize = self.maximumWidth()
-        if self.splitter:
-            self.splitterSizes = self.splitter.sizes()
-        
-        self.__stackedWidget.hide()
-        
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            self.setFixedHeight(self.__tabBar.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()
-    
-    def __expandIt(self):
-        """
-        Private method to expand the sidebar.
-        """
-        self.__minimized = False
-        self.__stackedWidget.show()
-        self.resize(self.__bigSize)
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            minSize = max(self.__minSize, self.minimumSizeHint().height())
-            self.setMinimumHeight(minSize)
-            self.setMaximumHeight(self.__maxSize)
-        else:
-            minSize = max(self.__minSize, self.minimumSizeHint().width())
-            self.setMinimumWidth(minSize)
-            self.setMaximumWidth(self.__maxSize)
-        if self.splitter:
-            self.splitter.setSizes(self.splitterSizes)
-        
-        self.__actionMethod = None
-    
-    def isMinimized(self):
-        """
-        Public method to check the minimized state.
-        
-        @return flag indicating the minimized state (boolean)
-        """
-        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)
-        """
-        return self.__autoHide
-    
-    def eventFilter(self, obj, evt):
-        """
-        Public method to handle some events for the tabbar.
-        
-        @param obj reference to the object (QObject)
-        @param evt reference to the event object (QEvent)
-        @return flag indicating, if the event was handled (boolean)
-        """
-        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
-        
-        return QWidget.eventFilter(self, obj, evt)
-    
-    def addTab(self, widget, iconOrLabel, 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)
-        """
-        if label:
-            index = self.__tabBar.addTab(iconOrLabel, label)
-            self.__tabBar.setTabToolTip(index, label)
-        else:
-            index = self.__tabBar.addTab(iconOrLabel)
-            self.__tabBar.setTabToolTip(index, iconOrLabel)
-        self.__stackedWidget.addWidget(widget)
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            self.__minSize = self.minimumSizeHint().height()
-        else:
-            self.__minSize = self.minimumSizeHint().width()
-    
-    def insertTab(self, index, widget, iconOrLabel, 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)
-        """
-        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)
-        self.__stackedWidget.insertWidget(index, widget)
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            self.__minSize = self.minimumSizeHint().height()
-        else:
-            self.__minSize = self.minimumSizeHint().width()
-    
-    def removeTab(self, index):
-        """
-        Public method to remove a tab.
-        
-        @param index the index of the tab to remove (integer)
-        """
-        self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
-        self.__tabBar.removeTab(index)
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            self.__minSize = self.minimumSizeHint().height()
-        else:
-            self.__minSize = self.minimumSizeHint().width()
-    
-    def clear(self):
-        """
-        Public method to remove all tabs.
-        """
-        while self.count() > 0:
-            self.removeTab(0)
-    
-    def prevTab(self):
-        """
-        Public slot used to show the previous tab.
-        """
-        ind = self.currentIndex() - 1
-        if ind == -1:
-            ind = self.count() - 1
-            
-        self.setCurrentIndex(ind)
-        self.currentWidget().setFocus()
-    
-    def nextTab(self):
-        """
-        Public slot used to show the next tab.
-        """
-        ind = self.currentIndex() + 1
-        if ind == self.count():
-            ind = 0
-            
-        self.setCurrentIndex(ind)
-        self.currentWidget().setFocus()
-    
-    def count(self):
-        """
-        Public method to get the number of tabs.
-        
-        @return number of tabs in the sidebar (integer)
-        """
-        return self.__tabBar.count()
-    
-    def currentIndex(self):
-        """
-        Public method to get the index of the current tab.
-        
-        @return index of the current tab (integer)
-        """
-        return self.__stackedWidget.currentIndex()
-    
-    def setCurrentIndex(self, index):
-        """
-        Public slot to set the current index.
-        
-        @param index the index to set as the current index (integer)
-        """
-        self.__tabBar.setCurrentIndex(index)
-        self.__stackedWidget.setCurrentIndex(index)
-        if self.isMinimized():
-            self.expand()
-    
-    def currentWidget(self):
-        """
-        Public method to get a reference to the current widget.
-        
-        @return reference to the current widget (QWidget)
-        """
-        return self.__stackedWidget.currentWidget()
-    
-    def setCurrentWidget(self, widget):
-        """
-        Public slot to set the current widget.
-        
-        @param widget reference to the widget to become the current widget
-            (QWidget)
-        """
-        self.__stackedWidget.setCurrentWidget(widget)
-        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
-        if self.isMinimized():
-            self.expand()
-    
-    def indexOf(self, widget):
-        """
-        Public method to get the index of the given widget.
-        
-        @param widget reference to the widget to get the index of (QWidget)
-        @return index of the given widget (integer)
-        """
-        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.
-        
-        @return orientation of the sidebar
-        @rtype EricSideBarSide
-        """
-        return self.__orientation
-    
-    def setOrientation(self, orient):
-        """
-        Public method to set the orientation of the sidebar.
-
-        @param orient orientation of the sidebar
-        @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.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.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.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.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.
-        
-        @param index index of the tab (integer)
-        @return reference to the widget (QWidget)
-        """
-        return self.__stackedWidget.widget(index)
-    
-    def saveState(self):
-        """
-        Public method to save the state of the sidebar.
-        
-        @return saved state as a byte array (QByteArray)
-        """
-        if len(self.splitterSizes) == 0:
-            if self.splitter:
-                self.splitterSizes = self.splitter.sizes()
-            self.__bigSize = self.size()
-            if self.__orientation in (
-                EricSideBarSide.NORTH, EricSideBarSide.SOUTH
-            ):
-                self.__minSize = self.minimumSizeHint().height()
-                self.__maxSize = self.maximumHeight()
-            else:
-                self.__minSize = self.minimumSizeHint().width()
-                self.__maxSize = self.maximumWidth()
-        
-        dataDict = {
-            "version": self.Version,
-            "minimized": self.__minimized,
-            "big_size": [self.__bigSize.width(), self.__bigSize.height()],
-            "min_size": self.__minSize,
-            "max_size": self.__maxSize,
-            "splitter_sizes": self.splitterSizes,
-            "auto_hide": self.__autoHide
-        }
-        data = json.dumps(dataDict)
-        
-        return data
-    
-    def restoreState(self, state):
-        """
-        Public method to restore the state of the sidebar.
-        
-        @param state byte array containing the saved state (QByteArray)
-        @return flag indicating success (boolean)
-        """
-        if not isinstance(state, str) or state == "":
-            return False
-        
-        try:
-            stateDict = json.loads(state)
-        except json.JSONDecodeError:
-            return False
-        
-        if not stateDict:
-            return False
-        
-        if self.__orientation in (EricSideBarSide.NORTH, EricSideBarSide.SOUTH):
-            minSize = self.layout.minimumSize().height()
-            maxSize = self.maximumHeight()
-        else:
-            minSize = self.layout.minimumSize().width()
-            maxSize = self.maximumWidth()
-        
-        if stateDict["version"] == 2:
-            if stateDict["minimized"] and not self.__minimized:
-                self.shrink()
-            
-            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()
-            
-            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