Python-FastUI-Widgets 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. fastuiwidgets/__init__.py +12 -0
  2. fastuiwidgets/_rc/__init__.py +0 -0
  3. fastuiwidgets/_rc/resource.py +98835 -0
  4. fastuiwidgets/common/__init__.py +12 -0
  5. fastuiwidgets/common/animation.py +530 -0
  6. fastuiwidgets/common/auto_wrap.py +164 -0
  7. fastuiwidgets/common/color.py +95 -0
  8. fastuiwidgets/common/config.py +423 -0
  9. fastuiwidgets/common/exception_handler.py +31 -0
  10. fastuiwidgets/common/font.py +38 -0
  11. fastuiwidgets/common/icon.py +703 -0
  12. fastuiwidgets/common/image_utils.py +198 -0
  13. fastuiwidgets/common/overload.py +47 -0
  14. fastuiwidgets/common/router.py +133 -0
  15. fastuiwidgets/common/screen.py +25 -0
  16. fastuiwidgets/common/smooth_scroll.py +141 -0
  17. fastuiwidgets/common/style_sheet.py +512 -0
  18. fastuiwidgets/common/theme_listener.py +27 -0
  19. fastuiwidgets/common/translator.py +14 -0
  20. fastuiwidgets/components/__init__.py +6 -0
  21. fastuiwidgets/components/date_time/__init__.py +4 -0
  22. fastuiwidgets/components/date_time/calendar_picker.py +121 -0
  23. fastuiwidgets/components/date_time/calendar_view.py +671 -0
  24. fastuiwidgets/components/date_time/date_picker.py +245 -0
  25. fastuiwidgets/components/date_time/fast_calendar_view.py +487 -0
  26. fastuiwidgets/components/date_time/picker_base.py +632 -0
  27. fastuiwidgets/components/date_time/time_picker.py +223 -0
  28. fastuiwidgets/components/dialog_box/__init__.py +6 -0
  29. fastuiwidgets/components/dialog_box/color_dialog.py +414 -0
  30. fastuiwidgets/components/dialog_box/dialog.py +167 -0
  31. fastuiwidgets/components/dialog_box/folder_list_dialog.py +307 -0
  32. fastuiwidgets/components/dialog_box/mask_dialog_base.py +120 -0
  33. fastuiwidgets/components/dialog_box/message_box_base.py +92 -0
  34. fastuiwidgets/components/dialog_box/message_dialog.py +65 -0
  35. fastuiwidgets/components/layout/__init__.py +3 -0
  36. fastuiwidgets/components/layout/expand_layout.py +96 -0
  37. fastuiwidgets/components/layout/flow_layout.py +236 -0
  38. fastuiwidgets/components/layout/v_box_layout.py +41 -0
  39. fastuiwidgets/components/material/__init__.py +6 -0
  40. fastuiwidgets/components/material/acrylic_combo_box.py +96 -0
  41. fastuiwidgets/components/material/acrylic_flyout.py +105 -0
  42. fastuiwidgets/components/material/acrylic_line_edit.py +27 -0
  43. fastuiwidgets/components/material/acrylic_menu.py +204 -0
  44. fastuiwidgets/components/material/acrylic_tool_tip.py +39 -0
  45. fastuiwidgets/components/material/acrylic_widget.py +42 -0
  46. fastuiwidgets/components/navigation/__init__.py +9 -0
  47. fastuiwidgets/components/navigation/breadcrumb.py +350 -0
  48. fastuiwidgets/components/navigation/navigation_bar.py +416 -0
  49. fastuiwidgets/components/navigation/navigation_interface.py +268 -0
  50. fastuiwidgets/components/navigation/navigation_panel.py +657 -0
  51. fastuiwidgets/components/navigation/navigation_widget.py +686 -0
  52. fastuiwidgets/components/navigation/pivot.py +272 -0
  53. fastuiwidgets/components/navigation/segmented_widget.py +174 -0
  54. fastuiwidgets/components/settings/__init__.py +8 -0
  55. fastuiwidgets/components/settings/custom_color_setting_card.py +139 -0
  56. fastuiwidgets/components/settings/expand_setting_card.py +390 -0
  57. fastuiwidgets/components/settings/folder_list_setting_card.py +134 -0
  58. fastuiwidgets/components/settings/options_setting_card.py +86 -0
  59. fastuiwidgets/components/settings/setting_card.py +449 -0
  60. fastuiwidgets/components/settings/setting_card_group.py +48 -0
  61. fastuiwidgets/components/widgets/__init__.py +41 -0
  62. fastuiwidgets/components/widgets/acrylic_label.py +261 -0
  63. fastuiwidgets/components/widgets/button.py +1059 -0
  64. fastuiwidgets/components/widgets/card_widget.py +369 -0
  65. fastuiwidgets/components/widgets/check_box.py +203 -0
  66. fastuiwidgets/components/widgets/combo_box.py +556 -0
  67. fastuiwidgets/components/widgets/command_bar.py +636 -0
  68. fastuiwidgets/components/widgets/cycle_list_widget.py +251 -0
  69. fastuiwidgets/components/widgets/flip_view.py +430 -0
  70. fastuiwidgets/components/widgets/flyout.py +521 -0
  71. fastuiwidgets/components/widgets/frameless_window.py +49 -0
  72. fastuiwidgets/components/widgets/icon_widget.py +53 -0
  73. fastuiwidgets/components/widgets/info_badge.py +483 -0
  74. fastuiwidgets/components/widgets/info_bar.py +596 -0
  75. fastuiwidgets/components/widgets/label.py +553 -0
  76. fastuiwidgets/components/widgets/line_edit.py +551 -0
  77. fastuiwidgets/components/widgets/list_view.py +158 -0
  78. fastuiwidgets/components/widgets/menu.py +1318 -0
  79. fastuiwidgets/components/widgets/pips_pager.py +331 -0
  80. fastuiwidgets/components/widgets/progress_bar.py +311 -0
  81. fastuiwidgets/components/widgets/progress_ring.py +212 -0
  82. fastuiwidgets/components/widgets/scroll_area.py +125 -0
  83. fastuiwidgets/components/widgets/scroll_bar.py +673 -0
  84. fastuiwidgets/components/widgets/separator.py +43 -0
  85. fastuiwidgets/components/widgets/slider.py +307 -0
  86. fastuiwidgets/components/widgets/spin_box.py +306 -0
  87. fastuiwidgets/components/widgets/stacked_widget.py +211 -0
  88. fastuiwidgets/components/widgets/state_tool_tip.py +188 -0
  89. fastuiwidgets/components/widgets/switch_button.py +312 -0
  90. fastuiwidgets/components/widgets/tab_view.py +804 -0
  91. fastuiwidgets/components/widgets/table_view.py +360 -0
  92. fastuiwidgets/components/widgets/teaching_tip.py +657 -0
  93. fastuiwidgets/components/widgets/tool_tip.py +460 -0
  94. fastuiwidgets/components/widgets/tree_view.py +216 -0
  95. fastuiwidgets/multimedia/__init__.py +3 -0
  96. fastuiwidgets/multimedia/media_play_bar.py +319 -0
  97. fastuiwidgets/multimedia/media_player.py +124 -0
  98. fastuiwidgets/multimedia/video_widget.py +93 -0
  99. fastuiwidgets/window/__init__.py +2 -0
  100. fastuiwidgets/window/fluent_window.py +413 -0
  101. fastuiwidgets/window/splash_screen.py +92 -0
  102. fastuiwidgets/window/stacked_widget.py +66 -0
  103. python_fastui_widgets-1.0.0.dist-info/METADATA +30 -0
  104. python_fastui_widgets-1.0.0.dist-info/RECORD +107 -0
  105. python_fastui_widgets-1.0.0.dist-info/WHEEL +5 -0
  106. python_fastui_widgets-1.0.0.dist-info/licenses/LICENSE +674 -0
  107. python_fastui_widgets-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,636 @@
1
+ # coding:utf-8
2
+ from typing import Iterable, List, Tuple, Union
3
+
4
+ from PySide6.QtCore import Qt, QSize, QRectF, QRect, QPoint, QEvent
5
+ from PySide6.QtGui import QAction, QPainter, QColor, QFont, QHoverEvent, QPainterPath
6
+ from PySide6.QtWidgets import QLayoutItem, QWidget, QFrame, QHBoxLayout, QApplication
7
+
8
+ from ...common.font import setFont
9
+ from ...common.icon import FluentIcon, Icon, Action
10
+ from ...common.style_sheet import isDarkTheme
11
+ from .menu import RoundMenu, MenuAnimationType
12
+ from .button import TransparentToggleToolButton
13
+ from .tool_tip import ToolTipFilter
14
+ from .flyout import FlyoutViewBase, Flyout
15
+
16
+
17
+ class CommandButton(TransparentToggleToolButton):
18
+ """ Command button
19
+
20
+ Constructors
21
+ ------------
22
+ * CommandButton(`parent`: QWidget = None)
23
+ * CommandButton(`icon`: QIcon | str | FluentIconBase = None, `parent`: QWidget = None)
24
+ """
25
+
26
+ def _postInit(self):
27
+ super()._postInit()
28
+ self.setCheckable(False)
29
+ self.setToolButtonStyle(Qt.ToolButtonIconOnly)
30
+ setFont(self, 12)
31
+
32
+ self._text = ''
33
+ self._action = None
34
+ self._isTight = False
35
+
36
+ def setTight(self, isTight: bool):
37
+ self._isTight = isTight
38
+ self.update()
39
+
40
+ def isTight(self):
41
+ return self._isTight
42
+
43
+ def sizeHint(self) -> QSize:
44
+ if self.isIconOnly():
45
+ return QSize(36, 34) if self.isTight() else QSize(48, 34)
46
+
47
+ # get the width of text
48
+ tw = self.fontMetrics().boundingRect(self.text()).width()
49
+
50
+ style = self.toolButtonStyle()
51
+ if style == Qt.ToolButtonTextBesideIcon:
52
+ return QSize(tw + 47, 34)
53
+ if style == Qt.ToolButtonTextOnly:
54
+ return QSize(tw + 32, 34)
55
+
56
+ return QSize(tw + 32, 50)
57
+
58
+ def isIconOnly(self):
59
+ if not self.text():
60
+ return True
61
+
62
+ return self.toolButtonStyle() in [Qt.ToolButtonIconOnly, Qt.ToolButtonFollowStyle]
63
+
64
+ def _drawIcon(self, icon, painter, rect):
65
+ pass
66
+
67
+ def text(self):
68
+ return self._text
69
+
70
+ def setText(self, text: str):
71
+ self._text = text
72
+ self.update()
73
+
74
+ def setAction(self, action: QAction):
75
+ self._action = action
76
+ self._onActionChanged()
77
+
78
+ self.clicked.connect(action.trigger)
79
+ action.toggled.connect(self.setChecked)
80
+ action.changed.connect(self._onActionChanged)
81
+
82
+ self.installEventFilter(CommandToolTipFilter(self, 700))
83
+
84
+ def _onActionChanged(self):
85
+ action = self.action()
86
+ self.setIcon(action.icon())
87
+ self.setText(action.text())
88
+ self.setToolTip(action.toolTip())
89
+ self.setEnabled(action.isEnabled())
90
+ self.setCheckable(action.isCheckable())
91
+ self.setChecked(action.isChecked())
92
+
93
+ def action(self):
94
+ return self._action
95
+
96
+ def paintEvent(self, e):
97
+ super().paintEvent(e)
98
+
99
+ painter = QPainter(self)
100
+ painter.setRenderHints(QPainter.Antialiasing |
101
+ QPainter.SmoothPixmapTransform)
102
+
103
+ if not self.isChecked():
104
+ painter.setPen(Qt.white if isDarkTheme() else Qt.black)
105
+ else:
106
+ painter.setPen(Qt.black if isDarkTheme() else Qt.white)
107
+
108
+ if not self.isEnabled():
109
+ painter.setOpacity(0.43)
110
+ elif self.isPressed:
111
+ painter.setOpacity(0.63)
112
+
113
+ # draw icon and text
114
+ style = self.toolButtonStyle()
115
+ iw, ih = self.iconSize().width(), self.iconSize().height()
116
+
117
+ if self.isIconOnly():
118
+ y = (self.height() - ih) / 2
119
+ x = (self.width() - iw) / 2
120
+ super()._drawIcon(self._icon, painter, QRectF(x, y, iw, ih))
121
+ elif style == Qt.ToolButtonTextOnly:
122
+ painter.drawText(self.rect(), Qt.AlignCenter, self.text())
123
+ elif style == Qt.ToolButtonTextBesideIcon:
124
+ y = (self.height() - ih) / 2
125
+ super()._drawIcon(self._icon, painter, QRectF(11, y, iw, ih))
126
+
127
+ rect = QRectF(26, 0, self.width() - 26, self.height())
128
+ painter.drawText(rect, Qt.AlignCenter, self.text())
129
+ elif style == Qt.ToolButtonTextUnderIcon:
130
+ x = (self.width() - iw) / 2
131
+ super()._drawIcon(self._icon, painter, QRectF(x, 9, iw, ih))
132
+
133
+ rect = QRectF(0, ih + 13, self.width(), self.height() - ih - 13)
134
+ painter.drawText(rect, Qt.AlignHCenter | Qt.AlignTop, self.text())
135
+
136
+
137
+ class CommandToolTipFilter(ToolTipFilter):
138
+ """ Command tool tip filter """
139
+
140
+ def _canShowToolTip(self) -> bool:
141
+ return super()._canShowToolTip() and self.parent().isIconOnly()
142
+
143
+
144
+ class MoreActionsButton(CommandButton):
145
+ """ More action button """
146
+
147
+ def _postInit(self):
148
+ super()._postInit()
149
+ self.setIcon(FluentIcon.MORE)
150
+
151
+ def sizeHint(self):
152
+ return QSize(40, 34)
153
+
154
+ def clearState(self):
155
+ self.setAttribute(Qt.WA_UnderMouse, False)
156
+ e = QHoverEvent(QEvent.HoverLeave, QPoint(-1, -1), QPoint())
157
+ QApplication.sendEvent(self, e)
158
+
159
+
160
+ class CommandSeparator(QWidget):
161
+ """ Command separator """
162
+
163
+ def __init__(self, parent=None):
164
+ super().__init__(parent)
165
+ self.setFixedSize(9, 34)
166
+
167
+ def paintEvent(self, e):
168
+ painter = QPainter(self)
169
+ painter.setPen(QColor(255, 255, 255, 21)
170
+ if isDarkTheme() else QColor(0, 0, 0, 15))
171
+ painter.drawLine(5, 2, 5, self.height() - 2)
172
+
173
+
174
+ class CommandMenu(RoundMenu):
175
+ """ Command menu """
176
+
177
+ def __init__(self, parent=None):
178
+ super().__init__("", parent)
179
+ self.setItemHeight(32)
180
+ self.view.setIconSize(QSize(16, 16))
181
+
182
+ def exec(self, pos, ani=True, aniType=MenuAnimationType.DROP_DOWN):
183
+ return super().exec(pos, ani, aniType)
184
+
185
+
186
+ class CommandBar(QFrame):
187
+ """ Command bar """
188
+
189
+ def __init__(self, parent=None):
190
+ super().__init__(parent=parent)
191
+ self._widgets = [] # type: List[QWidget]
192
+ self._hiddenWidgets = [] # type: List[QWidget]
193
+ self._hiddenActions = [] # type: List[QAction]
194
+
195
+ self._menuAnimation = MenuAnimationType.DROP_DOWN
196
+ self._toolButtonStyle = Qt.ToolButtonIconOnly
197
+ self._iconSize = QSize(16, 16)
198
+ self._isButtonTight = False
199
+ self._spacing = 4
200
+
201
+ self.moreButton = MoreActionsButton(self)
202
+ self.moreButton.clicked.connect(self._showMoreActionsMenu)
203
+ self.moreButton.hide()
204
+
205
+ setFont(self, 12)
206
+ self.setAttribute(Qt.WA_TranslucentBackground)
207
+
208
+ def setSpaing(self, spacing: int):
209
+ if spacing == self._spacing:
210
+ return
211
+
212
+ self._spacing = spacing
213
+ self.updateGeometry()
214
+
215
+ def spacing(self):
216
+ return self._spacing
217
+
218
+ def addAction(self, action: QAction):
219
+ """ add action
220
+
221
+ Parameters
222
+ ----------
223
+ action: QAction
224
+ the action to add
225
+ """
226
+ if action in self.actions():
227
+ return
228
+
229
+ button = self._createButton(action)
230
+ self._insertWidgetToLayout(-1, button)
231
+ super().addAction(action)
232
+ return button
233
+
234
+ def addActions(self, actions: Iterable[QAction]):
235
+ for action in actions:
236
+ self.addAction(action)
237
+
238
+ def addHiddenAction(self, action: QAction):
239
+ """ add hidden action """
240
+ if action in self.actions():
241
+ return
242
+
243
+ self._hiddenActions.append(action)
244
+ self.updateGeometry()
245
+ super().addAction(action)
246
+
247
+ def addHiddenActions(self, actions: List[QAction]):
248
+ """ add hidden action """
249
+ for action in actions:
250
+ self.addHiddenAction(action)
251
+
252
+ def insertAction(self, before: QAction, action: QAction):
253
+ if before not in self.actions():
254
+ return
255
+
256
+ index = self.actions().index(before)
257
+ button = self._createButton(action)
258
+ self._insertWidgetToLayout(index, button)
259
+ super().insertAction(before, action)
260
+ return button
261
+
262
+ def addSeparator(self):
263
+ self.insertSeparator(-1)
264
+
265
+ def insertSeparator(self, index: int):
266
+ self._insertWidgetToLayout(index, CommandSeparator(self))
267
+
268
+ def addWidget(self, widget: QWidget):
269
+ """ add widget to command bar """
270
+ self._insertWidgetToLayout(-1, widget)
271
+
272
+ def removeAction(self, action: QAction):
273
+ if action not in self.actions():
274
+ return
275
+
276
+ for w in self.commandButtons:
277
+ if w.action() is action:
278
+ self._widgets.remove(w)
279
+ w.hide()
280
+ w.deleteLater()
281
+ break
282
+
283
+ self.updateGeometry()
284
+
285
+ def removeWidget(self, widget: QWidget):
286
+ if widget not in self._widgets:
287
+ return
288
+
289
+ self._widgets.remove(widget)
290
+ self.updateGeometry()
291
+
292
+ def removeHiddenAction(self, action: QAction):
293
+ if action in self._hiddenActions:
294
+ self._hiddenActions.remove(action)
295
+
296
+ def setToolButtonStyle(self, style: Qt.ToolButtonStyle):
297
+ """ set the style of tool button """
298
+ if self.toolButtonStyle() == style:
299
+ return
300
+
301
+ self._toolButtonStyle = style
302
+ for w in self.commandButtons:
303
+ w.setToolButtonStyle(style)
304
+
305
+ def toolButtonStyle(self):
306
+ return self._toolButtonStyle
307
+
308
+ def setButtonTight(self, isTight: bool):
309
+ if self.isButtonTight() == isTight:
310
+ return
311
+
312
+ self._isButtonTight = isTight
313
+
314
+ for w in self.commandButtons:
315
+ w.setTight(isTight)
316
+
317
+ self.updateGeometry()
318
+
319
+ def isButtonTight(self):
320
+ return self._isButtonTight
321
+
322
+ def setIconSize(self, size: QSize):
323
+ if size == self._iconSize:
324
+ return
325
+
326
+ self._iconSize = size
327
+ for w in self.commandButtons:
328
+ w.setIconSize(size)
329
+
330
+ def iconSize(self):
331
+ return self._iconSize
332
+
333
+ def resizeEvent(self, e):
334
+ self.updateGeometry()
335
+
336
+ def _createButton(self, action: QAction):
337
+ """ create command button """
338
+ button = CommandButton(self)
339
+ button.setAction(action)
340
+ button.setToolButtonStyle(self.toolButtonStyle())
341
+ button.setTight(self.isButtonTight())
342
+ button.setIconSize(self.iconSize())
343
+ button.setFont(self.font())
344
+ return button
345
+
346
+ def _insertWidgetToLayout(self, index: int, widget: QWidget):
347
+ """ add widget to layout """
348
+ widget.setParent(self)
349
+ widget.show()
350
+
351
+ if index < 0:
352
+ self._widgets.append(widget)
353
+ else:
354
+ self._widgets.insert(index, widget)
355
+
356
+ self.setFixedHeight(max(w.height() for w in self._widgets))
357
+ self.updateGeometry()
358
+
359
+ def minimumSizeHint(self) -> QSize:
360
+ return self.moreButton.size()
361
+
362
+ def updateGeometry(self):
363
+ self._hiddenWidgets.clear()
364
+ self.moreButton.hide()
365
+
366
+ visibles = self._visibleWidgets()
367
+ x = self.contentsMargins().left()
368
+ h = self.height()
369
+
370
+ for widget in visibles:
371
+ widget.show()
372
+ widget.move(x, (h - widget.height()) // 2)
373
+ x += (widget.width() + self.spacing())
374
+
375
+ # show more actions button
376
+ if self._hiddenActions or len(visibles) < len(self._widgets):
377
+ self.moreButton.show()
378
+ self.moreButton.move(x, (h - self.moreButton.height()) // 2)
379
+
380
+ for widget in self._widgets[len(visibles):]:
381
+ widget.hide()
382
+ self._hiddenWidgets.append(widget)
383
+
384
+ def _visibleWidgets(self) -> List[QWidget]:
385
+ """ return the visible widgets in layout """
386
+ # have enough spacing to show all widgets
387
+ if self.suitableWidth() <= self.width():
388
+ return self._widgets
389
+
390
+ w = self.moreButton.width()
391
+ for index, widget in enumerate(self._widgets):
392
+ w += widget.width()
393
+ if index > 0:
394
+ w += self.spacing()
395
+
396
+ if w > self.width():
397
+ break
398
+
399
+ return self._widgets[:index]
400
+
401
+ def suitableWidth(self):
402
+ widths = [w.width() for w in self._widgets]
403
+ if self._hiddenActions:
404
+ widths.append(self.moreButton.width())
405
+
406
+ return sum(widths) + self.spacing() * max(len(widths) - 1, 0)
407
+
408
+ def resizeToSuitableWidth(self):
409
+ self.setFixedWidth(self.suitableWidth())
410
+
411
+ def setFont(self, font: QFont):
412
+ super().setFont(font)
413
+ for button in self.commandButtons:
414
+ button.setFont(font)
415
+
416
+ @property
417
+ def commandButtons(self):
418
+ return [w for w in self._widgets if isinstance(w, CommandButton)]
419
+
420
+ def setMenuDropDown(self, down: bool):
421
+ """ set the animation direction of more actions menu """
422
+ if down:
423
+ self._menuAnimation = MenuAnimationType.DROP_DOWN
424
+ else:
425
+ self._menuAnimation = MenuAnimationType.PULL_UP
426
+
427
+ def isMenuDropDown(self):
428
+ return self._menuAnimation == MenuAnimationType.DROP_DOWN
429
+
430
+ def _showMoreActionsMenu(self):
431
+ """ show more actions menu """
432
+ self.moreButton.clearState()
433
+
434
+ actions = self._hiddenActions.copy()
435
+
436
+ for w in reversed(self._hiddenWidgets):
437
+ if isinstance(w, CommandButton):
438
+ actions.insert(0, w.action())
439
+
440
+ menu = CommandMenu(self)
441
+ menu.addActions(actions)
442
+
443
+ x = -menu.width() + menu.layout().contentsMargins().right() + \
444
+ self.moreButton.width() + 18
445
+ if self._menuAnimation == MenuAnimationType.DROP_DOWN:
446
+ y = self.moreButton.height()
447
+ else:
448
+ y = -5
449
+
450
+ pos = self.moreButton.mapToGlobal(QPoint(x, y))
451
+ menu.exec(pos, aniType=self._menuAnimation)
452
+
453
+
454
+ class CommandViewMenu(CommandMenu):
455
+ """ Command view menu """
456
+
457
+ def __init__(self, parent=None):
458
+ super().__init__(parent)
459
+ self.view.setObjectName('commandListWidget')
460
+
461
+ def setDropDown(self, down: bool, long=False):
462
+ self.view.setProperty('dropDown', down)
463
+ self.view.setProperty('long', long)
464
+ self.view.setStyle(QApplication.style())
465
+
466
+ def exec(self, pos, ani=True, aniType=MenuAnimationType.DROP_DOWN):
467
+ return super().exec(pos, ani, aniType)
468
+
469
+
470
+ class CommandViewBar(CommandBar):
471
+ """ Command view bar """
472
+
473
+ def __init__(self, parent=None):
474
+ super().__init__(parent)
475
+ self.setMenuDropDown(True)
476
+
477
+ def setMenuDropDown(self, down: bool):
478
+ """ set the animation direction of more actions menu """
479
+ if down:
480
+ self._menuAnimation = MenuAnimationType.FADE_IN_DROP_DOWN
481
+ else:
482
+ self._menuAnimation = MenuAnimationType.FADE_IN_PULL_UP
483
+
484
+ def isMenuDropDown(self):
485
+ return self._menuAnimation == MenuAnimationType.FADE_IN_DROP_DOWN
486
+
487
+ def _showMoreActionsMenu(self):
488
+ self.moreButton.clearState()
489
+
490
+ actions = self._hiddenActions.copy()
491
+
492
+ for w in reversed(self._hiddenWidgets):
493
+ if isinstance(w, CommandButton):
494
+ actions.insert(0, w.action())
495
+
496
+ menu = CommandViewMenu(self)
497
+ menu.addActions(actions)
498
+
499
+ # adjust the shape of view
500
+ view = self.parent() # type: CommandBarView
501
+ view.setMenuVisible(True)
502
+
503
+ # adjust the shape of menu
504
+ menu.closedSignal.connect(lambda: view.setMenuVisible(False))
505
+ menu.setDropDown(self.isMenuDropDown(), menu.view.width() > view.width()+5)
506
+
507
+ # adjust menu size
508
+ if menu.view.width() < view.width():
509
+ menu.view.setFixedWidth(view.width())
510
+ menu.adjustSize()
511
+
512
+ x = -menu.width() + menu.layout().contentsMargins().right() + \
513
+ self.moreButton.width() + 18
514
+ if self.isMenuDropDown():
515
+ y = self.moreButton.height()
516
+ else:
517
+ y = -13
518
+ menu.setShadowEffect(0, (0, 0), QColor(0, 0, 0, 0))
519
+ menu.layout().setContentsMargins(12, 20, 12, 8)
520
+
521
+ pos = self.moreButton.mapToGlobal(QPoint(x, y))
522
+ menu.exec(pos, aniType=self._menuAnimation)
523
+
524
+
525
+ class CommandBarView(FlyoutViewBase):
526
+ """ Command bar view """
527
+
528
+ def __init__(self, parent=None):
529
+ super().__init__(parent=parent)
530
+ self.bar = CommandViewBar(self)
531
+ self.hBoxLayout = QHBoxLayout(self)
532
+
533
+ self.hBoxLayout.setContentsMargins(6, 6, 6, 6)
534
+ self.hBoxLayout.addWidget(self.bar)
535
+ self.hBoxLayout.setSizeConstraint(QHBoxLayout.SetMinAndMaxSize)
536
+
537
+ self.setButtonTight(True)
538
+ self.setIconSize(QSize(14, 14))
539
+
540
+ self._isMenuVisible = False
541
+
542
+ def setMenuVisible(self, isVisible):
543
+ self._isMenuVisible = isVisible
544
+ self.update()
545
+
546
+ def addWidget(self, widget: QWidget):
547
+ self.bar.addWidget(widget)
548
+
549
+ def setSpaing(self, spacing: int):
550
+ self.bar.setSpaing(spacing)
551
+
552
+ def spacing(self):
553
+ return self.bar.spacing()
554
+
555
+ def addAction(self, action: QAction):
556
+ return self.bar.addAction(action)
557
+
558
+ def addActions(self, actions: Iterable[QAction]):
559
+ self.bar.addActions(actions)
560
+
561
+ def addHiddenAction(self, action: QAction):
562
+ self.bar.addHiddenAction(action)
563
+
564
+ def addHiddenActions(self, actions: List[QAction]):
565
+ self.bar.addHiddenActions(actions)
566
+
567
+ def insertAction(self, before: QAction, action: QAction):
568
+ return self.bar.insertAction(before, action)
569
+
570
+ def addSeparator(self):
571
+ self.bar.addSeparator()
572
+
573
+ def insertSeparator(self, index: int):
574
+ self.bar.insertSeparator(index)
575
+
576
+ def removeAction(self, action: QAction):
577
+ self.bar.removeAction(action)
578
+
579
+ def removeWidget(self, widget: QWidget):
580
+ self.bar.removeWidget(widget)
581
+
582
+ def removeHiddenAction(self, action: QAction):
583
+ self.bar.removeAction(action)
584
+
585
+ def setToolButtonStyle(self, style: Qt.ToolButtonStyle):
586
+ self.bar.setToolButtonStyle(style)
587
+
588
+ def toolButtonStyle(self):
589
+ return self.bar.toolButtonStyle()
590
+
591
+ def setButtonTight(self, isTight: bool):
592
+ self.bar.setButtonTight(isTight)
593
+
594
+ def isButtonTight(self):
595
+ return self.bar.isButtonTight()
596
+
597
+ def setIconSize(self, size: QSize):
598
+ self.bar.setIconSize(size)
599
+
600
+ def iconSize(self):
601
+ return self.bar.iconSize()
602
+
603
+ def setFont(self, font: QFont):
604
+ self.bar.setFont(font)
605
+
606
+ def setMenuDropDown(self, down: bool):
607
+ self.bar.setMenuDropDown(down)
608
+
609
+ def suitableWidth(self):
610
+ m = self.contentsMargins()
611
+ return m.left() + m.right() + self.bar.suitableWidth()
612
+
613
+ def resizeToSuitableWidth(self):
614
+ self.bar.resizeToSuitableWidth()
615
+ self.setFixedWidth(self.suitableWidth())
616
+
617
+ def actions(self):
618
+ return self.bar.actions()
619
+
620
+ def paintEvent(self, e):
621
+ painter = QPainter(self)
622
+ painter.setRenderHints(QPainter.Antialiasing)
623
+
624
+ path = QPainterPath()
625
+ path.setFillRule(Qt.WindingFill)
626
+ path.addRoundedRect(QRectF(self.rect().adjusted(1, 1, -1, -1)), 8, 8)
627
+
628
+ if self._isMenuVisible:
629
+ y = self.height() - 10 if self.bar.isMenuDropDown() else 1
630
+ path.addRect(1, y, self.width() - 2, 9)
631
+
632
+ painter.setBrush(
633
+ QColor(40, 40, 40) if isDarkTheme() else QColor(248, 248, 248))
634
+ painter.setPen(
635
+ QColor(56, 56, 56) if isDarkTheme() else QColor(233, 233, 233))
636
+ painter.drawPath(path.simplified())