Added a 'More' button to the icon bar to show widget icons text in a menu for those who could not be shown due to size constraints. eric7

Mon, 15 Nov 2021 19:50:39 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 15 Nov 2021 19:50:39 +0100
branch
eric7
changeset 8768
09a4a3c5b161
parent 8767
d82b6440eb61
child 8769
142aea04a31b

Added a 'More' button to the icon bar to show widget icons text in a menu for those who could not be shown due to size constraints.

eric7/EricWidgets/EricIconBar.py file | annotate | diff | comparison | revisions
eric7/icons/breeze-light/sbDotsV96.svg file | annotate | diff | comparison | revisions
eric7/icons/breeze-light/sbDotsh96.svg file | annotate | diff | comparison | revisions
--- a/eric7/EricWidgets/EricIconBar.py	Fri Nov 12 17:58:46 2021 +0100
+++ b/eric7/EricWidgets/EricIconBar.py	Mon Nov 15 19:50:39 2021 +0100
@@ -10,11 +10,15 @@
 import contextlib
 
 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication
-from PyQt6.QtGui import QColor, QIcon
-from PyQt6.QtWidgets import QWidget, QBoxLayout, QWIDGETSIZE_MAX
+from PyQt6.QtGui import QColor, QIcon, QCursor, QPalette
+from PyQt6.QtWidgets import QWidget, QBoxLayout, QWIDGETSIZE_MAX, QMenu
+
+from EricWidgets.EricApplication import ericApp
 
 from .EricClickableLabel import EricClickableLabel
 
+import UI.PixmapCache
+
 
 class EricIconBar(QWidget):
     """
@@ -54,6 +58,13 @@
     }
     DefaultBarSize = "md"
     
+    MoreLabelAspect = 36 / 96
+    
+    MenuStyleSheetTemplate = (
+        "QMenu {{ background-color: {0}; "
+        "selection-background-color: {1}; "
+        "border: 1px solid; }}"
+    )
     WidgetStyleSheetTemplate = "QWidget {{ background-color: {0}; }}"
     LabelStyleSheetTemplate = "QLabel {{ background-color: {0}; }}"
     
@@ -85,6 +96,8 @@
         self.__fixedHeightWidth = (
             self.__barSize + 2 * self.__borderSize
         )
+        self.__minimumHeightWidth = int(
+            self.__barSize * self.MoreLabelAspect) + 2 * self.__borderSize
         
         # set initial values
         self.__color = QColor("#008800")
@@ -95,6 +108,7 @@
         # initialize with horizontal layout and change later if needed
         self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
         self.setFixedHeight(self.__fixedHeightWidth)
+        self.setMinimumWidth(self.__minimumHeightWidth)
         
         self.__layout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
         self.__layout.setContentsMargins(
@@ -109,6 +123,11 @@
             self.setOrientation(orientation)
         
         self.setColor(self.__color)
+        
+        self.__createMoreLabel()
+        self.__layout.insertWidget(0, self.__moreLabel)
+        
+        self.__adjustIconLabels()
     
     def setOrientation(self, orientation):
         """
@@ -120,14 +139,26 @@
         # reset list widget size constraints
         self.setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
         
+        # remove the 'More' icon
+        itm = self.__layout.takeAt(self.__layout.count() - 2)
+        itm.widget().deleteLater()
+        del itm
+        
         if orientation == Qt.Orientation.Horizontal:
             self.setFixedHeight(self.__fixedHeightWidth)
+            self.setMinimumWidth(self.__minimumHeightWidth)
             self.__layout.setDirection(QBoxLayout.Direction.LeftToRight)
         elif orientation == Qt.Orientation.Vertical:
             self.setFixedWidth(self.__fixedHeightWidth)
+            self.setMinimumHeight(self.__minimumHeightWidth)
             self.__layout.setDirection(QBoxLayout.Direction.TopToBottom)
         
         self.__orientation = orientation
+        
+        self.__createMoreLabel()
+        self.__layout.insertWidget(self.__layout.count() - 1, self.__moreLabel)
+        
+        self.__adjustIconLabels()
     
     def orientation(self):
         """
@@ -146,17 +177,26 @@
             'lg', 'xl', 'xxl')
         @type str
         """
+        # remove the 'More' icon
+        itm = self.__layout.takeAt(self.__layout.count() - 2)
+        itm.widget().deleteLater()
+        del itm
+        
         self.__barSize, self.__borderSize = (
             EricIconBar.BarSizes[barSize][:2])
         self.__barSizeKey = barSize
         self.__fixedHeightWidth = (
             self.__barSize + 2 * self.__borderSize
         )
+        self.__minimumHeightWidth = int(
+            self.__barSize * self.MoreLabelAspect) + 2 * self.__borderSize
         
         if self.__orientation == Qt.Orientation.Horizontal:
             self.setFixedHeight(self.__fixedHeightWidth)
+            self.setMinimumWidth(self.__minimumHeightWidth)
         elif self.__orientation == Qt.Orientation.Vertical:
             self.setFixedWidth(self.__fixedHeightWidth)
+            self.setMinimumHeight(self.__minimumHeightWidth)
         
         self.__layout.setContentsMargins(
             self.__borderSize, self.__borderSize,
@@ -169,6 +209,11 @@
                 widget.setFixedSize(self.__barSize, self.__barSize)
                 widget.setPixmap(
                     icon.pixmap(self.__barSize, self.__barSize))
+        
+        self.__createMoreLabel()
+        self.__layout.insertWidget(self.__layout.count() - 1, self.__moreLabel)
+        
+        self.__adjustIconLabels()
     
     def barSize(self):
         """
@@ -231,6 +276,31 @@
         
         return iconLabel
     
+    def __createMoreLabel(self):
+        """
+        Private method to create the label to be shown for too many icons.
+        """
+        self.__moreLabel = EricClickableLabel(self)
+        self.__moreLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
+        if self.__orientation == Qt.Orientation.Horizontal:
+            self.__moreLabel.setFixedSize(
+                int(self.__barSize * self.MoreLabelAspect), self.__barSize)
+            self.__moreLabel.setPixmap(
+                UI.PixmapCache.getIcon("sbDotsH96").pixmap(
+                    int(self.__barSize * self.MoreLabelAspect), self.__barSize
+                )
+            )
+        else:
+            self.__moreLabel.setFixedSize(
+                self.__barSize, int(self.__barSize * self.MoreLabelAspect))
+            self.__moreLabel.setPixmap(
+                UI.PixmapCache.getIcon("sbDotsV96").pixmap(
+                    self.__barSize, int(self.__barSize * self.MoreLabelAspect)
+                )
+            )
+        
+        self.__moreLabel.clicked.connect(self.__moreLabelClicked)
+    
     def addIcon(self, icon, label=""):
         """
         Public method to add an icon to the bar.
@@ -262,6 +332,8 @@
             self.setCurrentIndex(index)
         elif index <= self.__currentIndex:
             self.setCurrentIndex(self.__currentIndex + 1)
+        
+        self.__adjustIconLabels()
     
     def removeIcon(self, index):
         """
@@ -282,6 +354,8 @@
                 self.setCurrentIndex(index)
             elif index < self.__currentIndex:
                 self.setCurrentIndex(self.__currentIndex - 1)
+            
+            self.__adjustIconLabels()
     
     @pyqtSlot()
     def __iconClicked(self, label):
@@ -343,7 +417,7 @@
         @return number of icon labels
         @rtype int
         """
-        return self.__layout.count() - 1
+        return len(self.__icons)
     
     def wheelEvent(self, evt):
         """
@@ -381,3 +455,76 @@
             index = 0
         
         self.setCurrentIndex(index)
+    
+    @pyqtSlot()
+    def __moreLabelClicked(self):
+        """
+        Private slot to handle a click onto the 'More' label.
+        """
+        menu = QMenu(self)
+        baseColor = ericApp().palette().color(
+            QPalette.ColorRole.Base)
+        highlightColor = ericApp().palette().color(
+            QPalette.ColorRole.Highlight)
+        menu.setStyleSheet(
+            EricIconBar.MenuStyleSheetTemplate.format(
+                baseColor.name(), highlightColor.name()))
+        
+        for index in range(self.__layout.count() - 2):
+            iconLabel = self.__layout.itemAt(index)
+            if iconLabel:
+                widget = iconLabel.widget()
+                if not widget.isVisible():
+                    act = menu.addAction(widget.toolTip())
+                    act.setData(index)
+        
+        selectedAction = menu.exec(QCursor.pos())
+        if selectedAction is not None:
+            index = selectedAction.data()
+            if index >= 0:
+                if index == self.__currentIndex:
+                    self.currentClicked.emit(self.__currentIndex)
+                else:
+                    self.setCurrentIndex(index)
+    
+    def resizeEvent(self, evt):
+        """
+        Protected method to handle resizing of the icon bar.
+        
+        @param evt reference to the event object
+        @type QResizeEvent
+        """
+        self.__adjustIconLabels()
+    
+    def __adjustIconLabels(self):
+        """
+        Private method to adjust the visibility of the icon labels.
+        """
+        size = (
+            self.width()
+            if self.orientation() == Qt.Orientation.Horizontal else
+            self.height()
+        ) - 2 * self.__borderSize
+        
+        iconsSize = (
+            self.count() * self.__barSize +
+            (self.count() - 1) * self.__layout.spacing()
+        )
+        
+        if size < iconsSize:
+            self.__moreLabel.show()
+            iconsSize += int(self.__barSize * self.MoreLabelAspect)
+            for index in range(self.count() - 1, -1, -1):
+                iconLabel = self.__layout.itemAt(index)
+                if iconLabel:
+                    if size < iconsSize:
+                        iconLabel.widget().hide()
+                        iconsSize -= self.__barSize - self.__layout.spacing()
+                    else:
+                        iconLabel.widget().show()
+        else:
+            self.__moreLabel.hide()
+            for index in range(self.__layout.count() - 2):
+                iconLabel = self.__layout.itemAt(index)
+                if iconLabel:
+                    iconLabel.widget().show()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/icons/breeze-light/sbDotsV96.svg	Mon Nov 15 19:50:39 2021 +0100
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 96 36"
+   version="1.1"
+   id="svg6"
+   sodipodi:docname="sbDotsV96.svg"
+   inkscape:version="0.92.0 r15299"
+   width="96"
+   height="36">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1638"
+     inkscape:window-height="1189"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="7.8997086"
+     inkscape:cx="42.108537"
+     inkscape:cy="41.16976"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg6" />
+  <defs
+     id="defs3051">
+    <style
+       type="text/css"
+       id="current-color-scheme">
+      .ColorScheme-Text {
+        color:#232629;
+      }
+      </style>
+  </defs>
+  <path
+     style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389"
+     d="M 17.423771,6.027476 C 8.4177996,6.021577 2.6993224,17.586698 8.0924243,24.821462 12.741562,32.430976 25.242593,31.43365 28.760656,23.278383 32.827793,15.307844 26.322707,5.4104911 17.423771,6.027476 Z m 0.91844,5.729034 c 6.419372,-0.03931 8.128927,9.92938 2.114081,12.097799 -6.142636,3.055773 -11.9787966,-6.142615 -6.684571,-10.470766 1.222997,-1.13452 2.911011,-1.728507 4.57049,-1.627033 z"
+     id="path4"
+     inkscape:connector-curvature="0" />
+  <path
+     style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389"
+     d="M 47.423771,6.027476 C 38.4178,6.0215786 32.699322,17.586698 38.092425,24.821462 42.741562,32.430976 55.242593,31.43365 58.760656,23.278383 62.827793,15.307844 56.322707,5.4104911 47.423771,6.027476 Z m 0.91844,5.729034 c 6.419372,-0.03931 8.128927,9.92938 2.114081,12.097799 -6.142636,3.055773 -11.978796,-6.142615 -6.684571,-10.470766 1.222998,-1.13452 2.911011,-1.728507 4.57049,-1.627033 z"
+     id="path4-9"
+     inkscape:connector-curvature="0" />
+  <path
+     style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389"
+     d="M 77.423771,6.027476 C 68.4178,6.0215786 62.699322,17.586698 68.092425,24.821462 72.741562,32.430976 85.242593,31.43365 88.760656,23.278383 92.827793,15.307844 86.322707,5.4104911 77.423771,6.027476 Z m 0.91844,5.729034 c 6.419372,-0.03931 8.128927,9.92938 2.114081,12.097799 -6.142636,3.055773 -11.978796,-6.142615 -6.684571,-10.470766 1.222998,-1.13452 2.911011,-1.728507 4.57049,-1.627033 z"
+     id="path4-8"
+     inkscape:connector-curvature="0" />
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/icons/breeze-light/sbDotsh96.svg	Mon Nov 15 19:50:39 2021 +0100
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 36 96"
+   version="1.1"
+   id="svg6"
+   sodipodi:docname="sbDotsh96.svg"
+   inkscape:version="0.92.0 r15299"
+   width="36"
+   height="96">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1638"
+     inkscape:window-height="1189"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="7.8997086"
+     inkscape:cx="42.108537"
+     inkscape:cy="41.16976"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg6" />
+  <defs
+     id="defs3051">
+    <style
+       type="text/css"
+       id="current-color-scheme">
+      .ColorScheme-Text {
+        color:#232629;
+      }
+      </style>
+  </defs>
+  <g
+     id="g44"
+     transform="rotate(-90,48,48)">
+    <path
+       inkscape:connector-curvature="0"
+       id="path4"
+       d="M 6.0274765,18.576229 C 6.0215775,27.5822 17.586699,33.300678 24.821463,27.907576 32.430977,23.258438 31.433651,10.757407 23.278384,7.2393439 15.307845,3.1722069 5.4104916,9.6772929 6.0274765,18.576229 Z m 5.7290345,-0.91844 c -0.03931,-6.419372 9.92938,-8.1289271 12.097799,-2.114081 3.055773,6.142636 -6.142615,11.978797 -10.470766,6.684571 -1.13452,-1.222997 -1.728507,-2.911011 -1.627033,-4.57049 z"
+       style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4-9"
+       d="M 36.027477,18.576229 C 36.021579,27.5822 47.586699,33.300678 54.821463,27.907575 62.430977,23.258438 61.433651,10.757407 53.278384,7.239344 45.307845,3.172207 35.410492,9.677293 36.027477,18.576229 Z m 5.729034,-0.91844 c -0.03931,-6.419372 9.92938,-8.128927 12.097799,-2.114081 3.055773,6.142636 -6.142615,11.978796 -10.470766,6.684571 -1.13452,-1.222998 -1.728507,-2.911011 -1.627033,-4.57049 z"
+       style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4-8"
+       d="M 66.027477,18.576229 C 66.021579,27.5822 77.586699,33.300678 84.821463,27.907575 92.430977,23.258438 91.433651,10.757407 83.278384,7.239344 75.307845,3.172207 65.410492,9.677293 66.027477,18.576229 Z m 5.729034,-0.91844 c -0.03931,-6.419372 9.92938,-8.128927 12.097799,-2.114081 3.055773,6.142636 -6.142615,11.978796 -10.470766,6.684571 -1.13452,-1.222998 -1.728507,-2.911011 -1.627033,-4.57049 z"
+       style="color:#232629;fill:#eff0f1;fill-opacity:1;stroke:none;stroke-width:2.28622389" />
+  </g>
+</svg>

eric ide

mercurial