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.
- fastuiwidgets/__init__.py +12 -0
- fastuiwidgets/_rc/__init__.py +0 -0
- fastuiwidgets/_rc/resource.py +98835 -0
- fastuiwidgets/common/__init__.py +12 -0
- fastuiwidgets/common/animation.py +530 -0
- fastuiwidgets/common/auto_wrap.py +164 -0
- fastuiwidgets/common/color.py +95 -0
- fastuiwidgets/common/config.py +423 -0
- fastuiwidgets/common/exception_handler.py +31 -0
- fastuiwidgets/common/font.py +38 -0
- fastuiwidgets/common/icon.py +703 -0
- fastuiwidgets/common/image_utils.py +198 -0
- fastuiwidgets/common/overload.py +47 -0
- fastuiwidgets/common/router.py +133 -0
- fastuiwidgets/common/screen.py +25 -0
- fastuiwidgets/common/smooth_scroll.py +141 -0
- fastuiwidgets/common/style_sheet.py +512 -0
- fastuiwidgets/common/theme_listener.py +27 -0
- fastuiwidgets/common/translator.py +14 -0
- fastuiwidgets/components/__init__.py +6 -0
- fastuiwidgets/components/date_time/__init__.py +4 -0
- fastuiwidgets/components/date_time/calendar_picker.py +121 -0
- fastuiwidgets/components/date_time/calendar_view.py +671 -0
- fastuiwidgets/components/date_time/date_picker.py +245 -0
- fastuiwidgets/components/date_time/fast_calendar_view.py +487 -0
- fastuiwidgets/components/date_time/picker_base.py +632 -0
- fastuiwidgets/components/date_time/time_picker.py +223 -0
- fastuiwidgets/components/dialog_box/__init__.py +6 -0
- fastuiwidgets/components/dialog_box/color_dialog.py +414 -0
- fastuiwidgets/components/dialog_box/dialog.py +167 -0
- fastuiwidgets/components/dialog_box/folder_list_dialog.py +307 -0
- fastuiwidgets/components/dialog_box/mask_dialog_base.py +120 -0
- fastuiwidgets/components/dialog_box/message_box_base.py +92 -0
- fastuiwidgets/components/dialog_box/message_dialog.py +65 -0
- fastuiwidgets/components/layout/__init__.py +3 -0
- fastuiwidgets/components/layout/expand_layout.py +96 -0
- fastuiwidgets/components/layout/flow_layout.py +236 -0
- fastuiwidgets/components/layout/v_box_layout.py +41 -0
- fastuiwidgets/components/material/__init__.py +6 -0
- fastuiwidgets/components/material/acrylic_combo_box.py +96 -0
- fastuiwidgets/components/material/acrylic_flyout.py +105 -0
- fastuiwidgets/components/material/acrylic_line_edit.py +27 -0
- fastuiwidgets/components/material/acrylic_menu.py +204 -0
- fastuiwidgets/components/material/acrylic_tool_tip.py +39 -0
- fastuiwidgets/components/material/acrylic_widget.py +42 -0
- fastuiwidgets/components/navigation/__init__.py +9 -0
- fastuiwidgets/components/navigation/breadcrumb.py +350 -0
- fastuiwidgets/components/navigation/navigation_bar.py +416 -0
- fastuiwidgets/components/navigation/navigation_interface.py +268 -0
- fastuiwidgets/components/navigation/navigation_panel.py +657 -0
- fastuiwidgets/components/navigation/navigation_widget.py +686 -0
- fastuiwidgets/components/navigation/pivot.py +272 -0
- fastuiwidgets/components/navigation/segmented_widget.py +174 -0
- fastuiwidgets/components/settings/__init__.py +8 -0
- fastuiwidgets/components/settings/custom_color_setting_card.py +139 -0
- fastuiwidgets/components/settings/expand_setting_card.py +390 -0
- fastuiwidgets/components/settings/folder_list_setting_card.py +134 -0
- fastuiwidgets/components/settings/options_setting_card.py +86 -0
- fastuiwidgets/components/settings/setting_card.py +449 -0
- fastuiwidgets/components/settings/setting_card_group.py +48 -0
- fastuiwidgets/components/widgets/__init__.py +41 -0
- fastuiwidgets/components/widgets/acrylic_label.py +261 -0
- fastuiwidgets/components/widgets/button.py +1059 -0
- fastuiwidgets/components/widgets/card_widget.py +369 -0
- fastuiwidgets/components/widgets/check_box.py +203 -0
- fastuiwidgets/components/widgets/combo_box.py +556 -0
- fastuiwidgets/components/widgets/command_bar.py +636 -0
- fastuiwidgets/components/widgets/cycle_list_widget.py +251 -0
- fastuiwidgets/components/widgets/flip_view.py +430 -0
- fastuiwidgets/components/widgets/flyout.py +521 -0
- fastuiwidgets/components/widgets/frameless_window.py +49 -0
- fastuiwidgets/components/widgets/icon_widget.py +53 -0
- fastuiwidgets/components/widgets/info_badge.py +483 -0
- fastuiwidgets/components/widgets/info_bar.py +596 -0
- fastuiwidgets/components/widgets/label.py +553 -0
- fastuiwidgets/components/widgets/line_edit.py +551 -0
- fastuiwidgets/components/widgets/list_view.py +158 -0
- fastuiwidgets/components/widgets/menu.py +1318 -0
- fastuiwidgets/components/widgets/pips_pager.py +331 -0
- fastuiwidgets/components/widgets/progress_bar.py +311 -0
- fastuiwidgets/components/widgets/progress_ring.py +212 -0
- fastuiwidgets/components/widgets/scroll_area.py +125 -0
- fastuiwidgets/components/widgets/scroll_bar.py +673 -0
- fastuiwidgets/components/widgets/separator.py +43 -0
- fastuiwidgets/components/widgets/slider.py +307 -0
- fastuiwidgets/components/widgets/spin_box.py +306 -0
- fastuiwidgets/components/widgets/stacked_widget.py +211 -0
- fastuiwidgets/components/widgets/state_tool_tip.py +188 -0
- fastuiwidgets/components/widgets/switch_button.py +312 -0
- fastuiwidgets/components/widgets/tab_view.py +804 -0
- fastuiwidgets/components/widgets/table_view.py +360 -0
- fastuiwidgets/components/widgets/teaching_tip.py +657 -0
- fastuiwidgets/components/widgets/tool_tip.py +460 -0
- fastuiwidgets/components/widgets/tree_view.py +216 -0
- fastuiwidgets/multimedia/__init__.py +3 -0
- fastuiwidgets/multimedia/media_play_bar.py +319 -0
- fastuiwidgets/multimedia/media_player.py +124 -0
- fastuiwidgets/multimedia/video_widget.py +93 -0
- fastuiwidgets/window/__init__.py +2 -0
- fastuiwidgets/window/fluent_window.py +413 -0
- fastuiwidgets/window/splash_screen.py +92 -0
- fastuiwidgets/window/stacked_widget.py +66 -0
- python_fastui_widgets-1.0.0.dist-info/METADATA +30 -0
- python_fastui_widgets-1.0.0.dist-info/RECORD +107 -0
- python_fastui_widgets-1.0.0.dist-info/WHEEL +5 -0
- python_fastui_widgets-1.0.0.dist-info/licenses/LICENSE +674 -0
- 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())
|