Mon, 15 Nov 2021 19:50:39 +0100
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.
--- 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>