eric7/EricWidgets/EricIconBar.py

branch
eric7
changeset 8768
09a4a3c5b161
parent 8725
842ba8a9dbbb
child 8772
70f9dfe7116a
equal deleted inserted replaced
8767:d82b6440eb61 8768:09a4a3c5b161
8 """ 8 """
9 9
10 import contextlib 10 import contextlib
11 11
12 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication 12 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication
13 from PyQt6.QtGui import QColor, QIcon 13 from PyQt6.QtGui import QColor, QIcon, QCursor, QPalette
14 from PyQt6.QtWidgets import QWidget, QBoxLayout, QWIDGETSIZE_MAX 14 from PyQt6.QtWidgets import QWidget, QBoxLayout, QWIDGETSIZE_MAX, QMenu
15
16 from EricWidgets.EricApplication import ericApp
15 17
16 from .EricClickableLabel import EricClickableLabel 18 from .EricClickableLabel import EricClickableLabel
19
20 import UI.PixmapCache
17 21
18 22
19 class EricIconBar(QWidget): 23 class EricIconBar(QWidget):
20 """ 24 """
21 Class implementing a bar widget showing just icons. 25 Class implementing a bar widget showing just icons.
52 QCoreApplication.translate("EricIconBar", "very large") 56 QCoreApplication.translate("EricIconBar", "very large")
53 ), 57 ),
54 } 58 }
55 DefaultBarSize = "md" 59 DefaultBarSize = "md"
56 60
61 MoreLabelAspect = 36 / 96
62
63 MenuStyleSheetTemplate = (
64 "QMenu {{ background-color: {0}; "
65 "selection-background-color: {1}; "
66 "border: 1px solid; }}"
67 )
57 WidgetStyleSheetTemplate = "QWidget {{ background-color: {0}; }}" 68 WidgetStyleSheetTemplate = "QWidget {{ background-color: {0}; }}"
58 LabelStyleSheetTemplate = "QLabel {{ background-color: {0}; }}" 69 LabelStyleSheetTemplate = "QLabel {{ background-color: {0}; }}"
59 70
60 currentChanged = pyqtSignal(int) 71 currentChanged = pyqtSignal(int)
61 currentClicked = pyqtSignal(int) 72 currentClicked = pyqtSignal(int)
83 self.__barSize, self.__borderSize = ( 94 self.__barSize, self.__borderSize = (
84 EricIconBar.BarSizes[EricIconBar.DefaultBarSize][:2]) 95 EricIconBar.BarSizes[EricIconBar.DefaultBarSize][:2])
85 self.__fixedHeightWidth = ( 96 self.__fixedHeightWidth = (
86 self.__barSize + 2 * self.__borderSize 97 self.__barSize + 2 * self.__borderSize
87 ) 98 )
99 self.__minimumHeightWidth = int(
100 self.__barSize * self.MoreLabelAspect) + 2 * self.__borderSize
88 101
89 # set initial values 102 # set initial values
90 self.__color = QColor("#008800") 103 self.__color = QColor("#008800")
91 self.__orientation = Qt.Orientation.Horizontal 104 self.__orientation = Qt.Orientation.Horizontal
92 self.__currentIndex = -1 105 self.__currentIndex = -1
93 self.__icons = [] 106 self.__icons = []
94 107
95 # initialize with horizontal layout and change later if needed 108 # initialize with horizontal layout and change later if needed
96 self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True) 109 self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
97 self.setFixedHeight(self.__fixedHeightWidth) 110 self.setFixedHeight(self.__fixedHeightWidth)
111 self.setMinimumWidth(self.__minimumHeightWidth)
98 112
99 self.__layout = QBoxLayout(QBoxLayout.Direction.LeftToRight) 113 self.__layout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
100 self.__layout.setContentsMargins( 114 self.__layout.setContentsMargins(
101 self.__borderSize, self.__borderSize, 115 self.__borderSize, self.__borderSize,
102 self.__borderSize, self.__borderSize) 116 self.__borderSize, self.__borderSize)
107 121
108 if orientation != self.__orientation: 122 if orientation != self.__orientation:
109 self.setOrientation(orientation) 123 self.setOrientation(orientation)
110 124
111 self.setColor(self.__color) 125 self.setColor(self.__color)
126
127 self.__createMoreLabel()
128 self.__layout.insertWidget(0, self.__moreLabel)
129
130 self.__adjustIconLabels()
112 131
113 def setOrientation(self, orientation): 132 def setOrientation(self, orientation):
114 """ 133 """
115 Public method to set the widget orientation. 134 Public method to set the widget orientation.
116 135
118 @type Qt.Orientation 137 @type Qt.Orientation
119 """ 138 """
120 # reset list widget size constraints 139 # reset list widget size constraints
121 self.setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) 140 self.setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
122 141
142 # remove the 'More' icon
143 itm = self.__layout.takeAt(self.__layout.count() - 2)
144 itm.widget().deleteLater()
145 del itm
146
123 if orientation == Qt.Orientation.Horizontal: 147 if orientation == Qt.Orientation.Horizontal:
124 self.setFixedHeight(self.__fixedHeightWidth) 148 self.setFixedHeight(self.__fixedHeightWidth)
149 self.setMinimumWidth(self.__minimumHeightWidth)
125 self.__layout.setDirection(QBoxLayout.Direction.LeftToRight) 150 self.__layout.setDirection(QBoxLayout.Direction.LeftToRight)
126 elif orientation == Qt.Orientation.Vertical: 151 elif orientation == Qt.Orientation.Vertical:
127 self.setFixedWidth(self.__fixedHeightWidth) 152 self.setFixedWidth(self.__fixedHeightWidth)
153 self.setMinimumHeight(self.__minimumHeightWidth)
128 self.__layout.setDirection(QBoxLayout.Direction.TopToBottom) 154 self.__layout.setDirection(QBoxLayout.Direction.TopToBottom)
129 155
130 self.__orientation = orientation 156 self.__orientation = orientation
157
158 self.__createMoreLabel()
159 self.__layout.insertWidget(self.__layout.count() - 1, self.__moreLabel)
160
161 self.__adjustIconLabels()
131 162
132 def orientation(self): 163 def orientation(self):
133 """ 164 """
134 Public method to get the orientation of the widget. 165 Public method to get the orientation of the widget.
135 166
144 175
145 @param barSize size category for the bar (one of 'xs', 'sm', 'md', 176 @param barSize size category for the bar (one of 'xs', 'sm', 'md',
146 'lg', 'xl', 'xxl') 177 'lg', 'xl', 'xxl')
147 @type str 178 @type str
148 """ 179 """
180 # remove the 'More' icon
181 itm = self.__layout.takeAt(self.__layout.count() - 2)
182 itm.widget().deleteLater()
183 del itm
184
149 self.__barSize, self.__borderSize = ( 185 self.__barSize, self.__borderSize = (
150 EricIconBar.BarSizes[barSize][:2]) 186 EricIconBar.BarSizes[barSize][:2])
151 self.__barSizeKey = barSize 187 self.__barSizeKey = barSize
152 self.__fixedHeightWidth = ( 188 self.__fixedHeightWidth = (
153 self.__barSize + 2 * self.__borderSize 189 self.__barSize + 2 * self.__borderSize
154 ) 190 )
191 self.__minimumHeightWidth = int(
192 self.__barSize * self.MoreLabelAspect) + 2 * self.__borderSize
155 193
156 if self.__orientation == Qt.Orientation.Horizontal: 194 if self.__orientation == Qt.Orientation.Horizontal:
157 self.setFixedHeight(self.__fixedHeightWidth) 195 self.setFixedHeight(self.__fixedHeightWidth)
196 self.setMinimumWidth(self.__minimumHeightWidth)
158 elif self.__orientation == Qt.Orientation.Vertical: 197 elif self.__orientation == Qt.Orientation.Vertical:
159 self.setFixedWidth(self.__fixedHeightWidth) 198 self.setFixedWidth(self.__fixedHeightWidth)
199 self.setMinimumHeight(self.__minimumHeightWidth)
160 200
161 self.__layout.setContentsMargins( 201 self.__layout.setContentsMargins(
162 self.__borderSize, self.__borderSize, 202 self.__borderSize, self.__borderSize,
163 self.__borderSize, self.__borderSize) 203 self.__borderSize, self.__borderSize)
164 204
167 if iconLabel: 207 if iconLabel:
168 widget = iconLabel.widget() 208 widget = iconLabel.widget()
169 widget.setFixedSize(self.__barSize, self.__barSize) 209 widget.setFixedSize(self.__barSize, self.__barSize)
170 widget.setPixmap( 210 widget.setPixmap(
171 icon.pixmap(self.__barSize, self.__barSize)) 211 icon.pixmap(self.__barSize, self.__barSize))
212
213 self.__createMoreLabel()
214 self.__layout.insertWidget(self.__layout.count() - 1, self.__moreLabel)
215
216 self.__adjustIconLabels()
172 217
173 def barSize(self): 218 def barSize(self):
174 """ 219 """
175 Public method to get the icon bar size. 220 Public method to get the icon bar size.
176 221
229 274
230 iconLabel.clicked.connect(lambda: self.__iconClicked(iconLabel)) 275 iconLabel.clicked.connect(lambda: self.__iconClicked(iconLabel))
231 276
232 return iconLabel 277 return iconLabel
233 278
279 def __createMoreLabel(self):
280 """
281 Private method to create the label to be shown for too many icons.
282 """
283 self.__moreLabel = EricClickableLabel(self)
284 self.__moreLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
285 if self.__orientation == Qt.Orientation.Horizontal:
286 self.__moreLabel.setFixedSize(
287 int(self.__barSize * self.MoreLabelAspect), self.__barSize)
288 self.__moreLabel.setPixmap(
289 UI.PixmapCache.getIcon("sbDotsH96").pixmap(
290 int(self.__barSize * self.MoreLabelAspect), self.__barSize
291 )
292 )
293 else:
294 self.__moreLabel.setFixedSize(
295 self.__barSize, int(self.__barSize * self.MoreLabelAspect))
296 self.__moreLabel.setPixmap(
297 UI.PixmapCache.getIcon("sbDotsV96").pixmap(
298 self.__barSize, int(self.__barSize * self.MoreLabelAspect)
299 )
300 )
301
302 self.__moreLabel.clicked.connect(self.__moreLabelClicked)
303
234 def addIcon(self, icon, label=""): 304 def addIcon(self, icon, label=""):
235 """ 305 """
236 Public method to add an icon to the bar. 306 Public method to add an icon to the bar.
237 307
238 @param icon reference to the icon 308 @param icon reference to the icon
260 330
261 if self.__currentIndex < 0: 331 if self.__currentIndex < 0:
262 self.setCurrentIndex(index) 332 self.setCurrentIndex(index)
263 elif index <= self.__currentIndex: 333 elif index <= self.__currentIndex:
264 self.setCurrentIndex(self.__currentIndex + 1) 334 self.setCurrentIndex(self.__currentIndex + 1)
335
336 self.__adjustIconLabels()
265 337
266 def removeIcon(self, index): 338 def removeIcon(self, index):
267 """ 339 """
268 Public method to remove an icon from the bar. 340 Public method to remove an icon from the bar.
269 341
280 352
281 if index == self.__currentIndex: 353 if index == self.__currentIndex:
282 self.setCurrentIndex(index) 354 self.setCurrentIndex(index)
283 elif index < self.__currentIndex: 355 elif index < self.__currentIndex:
284 self.setCurrentIndex(self.__currentIndex - 1) 356 self.setCurrentIndex(self.__currentIndex - 1)
357
358 self.__adjustIconLabels()
285 359
286 @pyqtSlot() 360 @pyqtSlot()
287 def __iconClicked(self, label): 361 def __iconClicked(self, label):
288 """ 362 """
289 Private slot to handle an icon been clicked. 363 Private slot to handle an icon been clicked.
341 Public method to get the number of icon labels. 415 Public method to get the number of icon labels.
342 416
343 @return number of icon labels 417 @return number of icon labels
344 @rtype int 418 @rtype int
345 """ 419 """
346 return self.__layout.count() - 1 420 return len(self.__icons)
347 421
348 def wheelEvent(self, evt): 422 def wheelEvent(self, evt):
349 """ 423 """
350 Protected method to handle a wheel event. 424 Protected method to handle a wheel event.
351 425
379 if index == self.count(): 453 if index == self.count():
380 # wrap around 454 # wrap around
381 index = 0 455 index = 0
382 456
383 self.setCurrentIndex(index) 457 self.setCurrentIndex(index)
458
459 @pyqtSlot()
460 def __moreLabelClicked(self):
461 """
462 Private slot to handle a click onto the 'More' label.
463 """
464 menu = QMenu(self)
465 baseColor = ericApp().palette().color(
466 QPalette.ColorRole.Base)
467 highlightColor = ericApp().palette().color(
468 QPalette.ColorRole.Highlight)
469 menu.setStyleSheet(
470 EricIconBar.MenuStyleSheetTemplate.format(
471 baseColor.name(), highlightColor.name()))
472
473 for index in range(self.__layout.count() - 2):
474 iconLabel = self.__layout.itemAt(index)
475 if iconLabel:
476 widget = iconLabel.widget()
477 if not widget.isVisible():
478 act = menu.addAction(widget.toolTip())
479 act.setData(index)
480
481 selectedAction = menu.exec(QCursor.pos())
482 if selectedAction is not None:
483 index = selectedAction.data()
484 if index >= 0:
485 if index == self.__currentIndex:
486 self.currentClicked.emit(self.__currentIndex)
487 else:
488 self.setCurrentIndex(index)
489
490 def resizeEvent(self, evt):
491 """
492 Protected method to handle resizing of the icon bar.
493
494 @param evt reference to the event object
495 @type QResizeEvent
496 """
497 self.__adjustIconLabels()
498
499 def __adjustIconLabels(self):
500 """
501 Private method to adjust the visibility of the icon labels.
502 """
503 size = (
504 self.width()
505 if self.orientation() == Qt.Orientation.Horizontal else
506 self.height()
507 ) - 2 * self.__borderSize
508
509 iconsSize = (
510 self.count() * self.__barSize +
511 (self.count() - 1) * self.__layout.spacing()
512 )
513
514 if size < iconsSize:
515 self.__moreLabel.show()
516 iconsSize += int(self.__barSize * self.MoreLabelAspect)
517 for index in range(self.count() - 1, -1, -1):
518 iconLabel = self.__layout.itemAt(index)
519 if iconLabel:
520 if size < iconsSize:
521 iconLabel.widget().hide()
522 iconsSize -= self.__barSize - self.__layout.spacing()
523 else:
524 iconLabel.widget().show()
525 else:
526 self.__moreLabel.hide()
527 for index in range(self.__layout.count() - 2):
528 iconLabel = self.__layout.itemAt(index)
529 if iconLabel:
530 iconLabel.widget().show()

eric ide

mercurial