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,657 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
from enum import Enum
|
3
|
+
from typing import Union
|
4
|
+
|
5
|
+
from PySide6.QtCore import Qt, QPoint, QObject, QPointF, QTimer, QPropertyAnimation, QEvent
|
6
|
+
from PySide6.QtGui import QPainter, QColor, QPainterPath, QIcon, QCursor, QPolygonF, QPixmap, QImage
|
7
|
+
from PySide6.QtWidgets import QWidget, QHBoxLayout, QApplication, QGraphicsDropShadowEffect
|
8
|
+
|
9
|
+
from ...common.icon import FluentIconBase
|
10
|
+
from ...common.screen import getCurrentScreenGeometry
|
11
|
+
from ...common.style_sheet import isDarkTheme
|
12
|
+
from .flyout import FlyoutView, FlyoutViewBase
|
13
|
+
|
14
|
+
|
15
|
+
class TeachingTipTailPosition(Enum):
|
16
|
+
""" Teaching tip tail position """
|
17
|
+
TOP = 0
|
18
|
+
BOTTOM = 1
|
19
|
+
LEFT = 2
|
20
|
+
RIGHT = 3
|
21
|
+
TOP_LEFT = 4
|
22
|
+
TOP_RIGHT = 5
|
23
|
+
BOTTOM_LEFT = 6
|
24
|
+
BOTTOM_RIGHT = 7
|
25
|
+
LEFT_TOP = 8
|
26
|
+
LEFT_BOTTOM = 9
|
27
|
+
RIGHT_TOP = 10
|
28
|
+
RIGHT_BOTTOM = 11
|
29
|
+
NONE = 12
|
30
|
+
|
31
|
+
|
32
|
+
class ImagePosition(Enum):
|
33
|
+
TOP = 0
|
34
|
+
BOTTOM = 1
|
35
|
+
LEFT = 2
|
36
|
+
RIGHT = 3
|
37
|
+
|
38
|
+
|
39
|
+
class TeachingTipView(FlyoutView):
|
40
|
+
""" Teaching tip view """
|
41
|
+
|
42
|
+
def __init__(self, title: str, content: str, icon: Union[FluentIconBase, QIcon, str] = None,
|
43
|
+
image: Union[str, QPixmap, QImage] = None, isClosable=True, tailPosition=TeachingTipTailPosition.BOTTOM,
|
44
|
+
parent=None):
|
45
|
+
self.manager = TeachingTipManager.make(tailPosition)
|
46
|
+
self.hBoxLayout = QHBoxLayout()
|
47
|
+
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
|
48
|
+
super().__init__(title, content, icon, image, isClosable, parent)
|
49
|
+
|
50
|
+
def _adjustImage(self):
|
51
|
+
if self.manager.imagePosition() in [ImagePosition.TOP, ImagePosition.BOTTOM]:
|
52
|
+
return super()._adjustImage()
|
53
|
+
|
54
|
+
h = self.vBoxLayout.sizeHint().height() - 2
|
55
|
+
self.imageLabel.scaledToHeight(h)
|
56
|
+
|
57
|
+
def _addImageToLayout(self):
|
58
|
+
self.imageLabel.setHidden(self.imageLabel.isNull())
|
59
|
+
pos = self.manager.imagePosition()
|
60
|
+
|
61
|
+
if pos == ImagePosition.TOP:
|
62
|
+
self.imageLabel.setBorderRadius(8, 8, 0, 0)
|
63
|
+
self.vBoxLayout.insertWidget(0, self.imageLabel)
|
64
|
+
elif pos == ImagePosition.BOTTOM:
|
65
|
+
self.imageLabel.setBorderRadius(0, 0, 8, 8)
|
66
|
+
self.vBoxLayout.addWidget(self.imageLabel)
|
67
|
+
elif pos == ImagePosition.LEFT:
|
68
|
+
self.vBoxLayout.removeItem(self.vBoxLayout.itemAt(0))
|
69
|
+
self.hBoxLayout.addLayout(self.viewLayout)
|
70
|
+
self.vBoxLayout.addLayout(self.hBoxLayout)
|
71
|
+
|
72
|
+
self.imageLabel.setBorderRadius(8, 0, 8, 0)
|
73
|
+
self.hBoxLayout.insertWidget(0, self.imageLabel)
|
74
|
+
elif pos == ImagePosition.RIGHT:
|
75
|
+
self.vBoxLayout.removeItem(self.vBoxLayout.itemAt(0))
|
76
|
+
self.hBoxLayout.addLayout(self.viewLayout)
|
77
|
+
self.vBoxLayout.addLayout(self.hBoxLayout)
|
78
|
+
|
79
|
+
self.imageLabel.setBorderRadius(0, 8, 0, 8)
|
80
|
+
self.hBoxLayout.addWidget(self.imageLabel)
|
81
|
+
|
82
|
+
def paintEvent(self, e):
|
83
|
+
pass
|
84
|
+
|
85
|
+
|
86
|
+
class TeachTipBubble(QWidget):
|
87
|
+
""" Teaching tip bubble """
|
88
|
+
|
89
|
+
def __init__(self, view: FlyoutViewBase, tailPosition=TeachingTipTailPosition.BOTTOM, parent=None):
|
90
|
+
super().__init__(parent=parent)
|
91
|
+
self.manager = TeachingTipManager.make(tailPosition)
|
92
|
+
self.hBoxLayout = QHBoxLayout(self)
|
93
|
+
self.view = view
|
94
|
+
|
95
|
+
self.manager.doLayout(self)
|
96
|
+
self.hBoxLayout.addWidget(self.view)
|
97
|
+
|
98
|
+
def setView(self, view: QWidget):
|
99
|
+
self.hBoxLayout.removeWidget(self.view)
|
100
|
+
self.view.deleteLater()
|
101
|
+
self.view = view
|
102
|
+
self.hBoxLayout.addWidget(view)
|
103
|
+
|
104
|
+
def paintEvent(self, e):
|
105
|
+
painter = QPainter(self)
|
106
|
+
painter.setRenderHints(QPainter.Antialiasing)
|
107
|
+
|
108
|
+
painter.setBrush(
|
109
|
+
QColor(40, 40, 40) if isDarkTheme() else QColor(248, 248, 248))
|
110
|
+
painter.setPen(
|
111
|
+
QColor(23, 23, 23) if isDarkTheme() else QColor(0, 0, 0, 17))
|
112
|
+
|
113
|
+
self.manager.draw(self, painter)
|
114
|
+
|
115
|
+
|
116
|
+
class TeachingTip(QWidget):
|
117
|
+
""" Teaching tip """
|
118
|
+
|
119
|
+
def __init__(self, view: FlyoutViewBase, target: QWidget, duration=1000,
|
120
|
+
tailPosition=TeachingTipTailPosition.BOTTOM, parent=None, isDeleteOnClose=True):
|
121
|
+
"""
|
122
|
+
Parameters
|
123
|
+
----------
|
124
|
+
target: QWidget
|
125
|
+
the target widget to show tip
|
126
|
+
|
127
|
+
view: FlyoutViewBase
|
128
|
+
teaching tip view
|
129
|
+
|
130
|
+
duration: int
|
131
|
+
the time for teaching tip to display in milliseconds. If duration is less than zero,
|
132
|
+
teaching tip will never disappear.
|
133
|
+
|
134
|
+
tailPosition: TeachingTipTailPosition
|
135
|
+
the position of bubble tail
|
136
|
+
|
137
|
+
parent: QWidget
|
138
|
+
parent widget
|
139
|
+
|
140
|
+
isDeleteOnClose: bool
|
141
|
+
whether delete flyout automatically when flyout is closed
|
142
|
+
"""
|
143
|
+
super().__init__(parent=parent)
|
144
|
+
self.target = target
|
145
|
+
self.duration = duration
|
146
|
+
self.isDeleteOnClose = isDeleteOnClose
|
147
|
+
self.manager = TeachingTipManager.make(tailPosition)
|
148
|
+
|
149
|
+
self.hBoxLayout = QHBoxLayout(self)
|
150
|
+
self.opacityAni = QPropertyAnimation(self, b'windowOpacity', self)
|
151
|
+
|
152
|
+
self.bubble = TeachTipBubble(view, tailPosition, self)
|
153
|
+
|
154
|
+
self.hBoxLayout.setContentsMargins(15, 8, 15, 20)
|
155
|
+
self.hBoxLayout.addWidget(self.bubble)
|
156
|
+
self.setShadowEffect()
|
157
|
+
|
158
|
+
# set style
|
159
|
+
self.setAttribute(Qt.WA_TranslucentBackground)
|
160
|
+
self.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint)
|
161
|
+
|
162
|
+
if parent and parent.window():
|
163
|
+
parent.window().installEventFilter(self)
|
164
|
+
|
165
|
+
def setShadowEffect(self, blurRadius=35, offset=(0, 8)):
|
166
|
+
""" add shadow to dialog """
|
167
|
+
color = QColor(0, 0, 0, 80 if isDarkTheme() else 30)
|
168
|
+
self.shadowEffect = QGraphicsDropShadowEffect(self.bubble)
|
169
|
+
self.shadowEffect.setBlurRadius(blurRadius)
|
170
|
+
self.shadowEffect.setOffset(*offset)
|
171
|
+
self.shadowEffect.setColor(color)
|
172
|
+
self.bubble.setGraphicsEffect(None)
|
173
|
+
self.bubble.setGraphicsEffect(self.shadowEffect)
|
174
|
+
|
175
|
+
def _fadeOut(self):
|
176
|
+
""" fade out """
|
177
|
+
self.opacityAni.setDuration(167)
|
178
|
+
self.opacityAni.setStartValue(1)
|
179
|
+
self.opacityAni.setEndValue(0)
|
180
|
+
self.opacityAni.finished.connect(self.close)
|
181
|
+
self.opacityAni.start()
|
182
|
+
|
183
|
+
def showEvent(self, e):
|
184
|
+
if self.duration >= 0:
|
185
|
+
QTimer.singleShot(self.duration, self._fadeOut)
|
186
|
+
|
187
|
+
self.move(self.manager.position(self))
|
188
|
+
self.adjustSize()
|
189
|
+
self.opacityAni.setDuration(167)
|
190
|
+
self.opacityAni.setStartValue(0)
|
191
|
+
self.opacityAni.setEndValue(1)
|
192
|
+
self.opacityAni.start()
|
193
|
+
super().showEvent(e)
|
194
|
+
|
195
|
+
def closeEvent(self, e):
|
196
|
+
if self.isDeleteOnClose:
|
197
|
+
self.deleteLater()
|
198
|
+
|
199
|
+
super().closeEvent(e)
|
200
|
+
|
201
|
+
def eventFilter(self, obj, e: QEvent):
|
202
|
+
if self.parent() and obj is self.parent().window():
|
203
|
+
if e.type() in [QEvent.Resize, QEvent.WindowStateChange, QEvent.Move]:
|
204
|
+
self.move(self.manager.position(self))
|
205
|
+
|
206
|
+
return super().eventFilter(obj, e)
|
207
|
+
|
208
|
+
def addWidget(self, widget: QWidget, stretch=0, align=Qt.AlignLeft):
|
209
|
+
""" add widget to teaching tip """
|
210
|
+
self.view.addSpacing(8)
|
211
|
+
self.view.addWidget(widget, stretch, align)
|
212
|
+
|
213
|
+
@property
|
214
|
+
def view(self):
|
215
|
+
return self.bubble.view
|
216
|
+
|
217
|
+
def setView(self, view):
|
218
|
+
self.bubble.setView(view)
|
219
|
+
|
220
|
+
@classmethod
|
221
|
+
def make(cls, view: FlyoutViewBase, target: QWidget, duration=1000, tailPosition=TeachingTipTailPosition.BOTTOM,
|
222
|
+
parent=None, isDeleteOnClose=True):
|
223
|
+
"""
|
224
|
+
Parameters
|
225
|
+
----------
|
226
|
+
view: FlyoutViewBase
|
227
|
+
teaching tip view
|
228
|
+
|
229
|
+
target: QWidget
|
230
|
+
the target widget to show tip
|
231
|
+
|
232
|
+
duration: int
|
233
|
+
the time for teaching tip to display in milliseconds. If duration is less than zero,
|
234
|
+
teaching tip will never disappear.
|
235
|
+
|
236
|
+
tailPosition: TeachingTipTailPosition
|
237
|
+
the position of bubble tail
|
238
|
+
|
239
|
+
parent: QWidget
|
240
|
+
parent widget
|
241
|
+
|
242
|
+
isDeleteOnClose: bool
|
243
|
+
whether delete flyout automatically when flyout is closed
|
244
|
+
"""
|
245
|
+
w = cls(view, target, duration, tailPosition, parent, isDeleteOnClose)
|
246
|
+
w.show()
|
247
|
+
return w
|
248
|
+
|
249
|
+
@classmethod
|
250
|
+
def create(cls, target: QWidget, title: str, content: str, icon: Union[FluentIconBase, QIcon, str] = None,
|
251
|
+
image: Union[str, QPixmap, QImage] = None, isClosable=True, duration=1000,
|
252
|
+
tailPosition=TeachingTipTailPosition.BOTTOM, parent=None, isDeleteOnClose=True):
|
253
|
+
"""
|
254
|
+
Parameters
|
255
|
+
----------
|
256
|
+
target: QWidget
|
257
|
+
the target widget to show tip
|
258
|
+
|
259
|
+
title: str
|
260
|
+
the title of teaching tip
|
261
|
+
|
262
|
+
content: str
|
263
|
+
the content of teaching tip
|
264
|
+
|
265
|
+
icon: InfoBarIcon | FluentIconBase | QIcon | str
|
266
|
+
the icon of teaching tip
|
267
|
+
|
268
|
+
image: str | QPixmap | QImage
|
269
|
+
the image of teaching tip
|
270
|
+
|
271
|
+
isClosable: bool
|
272
|
+
whether to show the close button
|
273
|
+
|
274
|
+
duraction: int
|
275
|
+
the time for teaching tip to display in milliseconds. If duration is less than zero,
|
276
|
+
teaching tip will never disappear.
|
277
|
+
|
278
|
+
parent: QWidget
|
279
|
+
parent widget
|
280
|
+
|
281
|
+
isDeleteOnClose: bool
|
282
|
+
whether delete flyout automatically when flyout is closed
|
283
|
+
"""
|
284
|
+
view = TeachingTipView(title, content, icon, image, isClosable, tailPosition)
|
285
|
+
w = cls.make(view, target, duration, tailPosition, parent, isDeleteOnClose)
|
286
|
+
view.closed.connect(w.close)
|
287
|
+
return w
|
288
|
+
|
289
|
+
|
290
|
+
class PopupTeachingTip(TeachingTip):
|
291
|
+
""" Pop up teaching tip """
|
292
|
+
|
293
|
+
def __init__(self, view: FlyoutViewBase, target: QWidget, duration=1000,
|
294
|
+
tailPosition=TeachingTipTailPosition.BOTTOM, parent=None, isDeleteOnClose=True):
|
295
|
+
super().__init__(view, target, duration, tailPosition, parent, isDeleteOnClose)
|
296
|
+
self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
|
297
|
+
|
298
|
+
|
299
|
+
class TeachingTipManager(QObject):
|
300
|
+
""" Teaching tip manager """
|
301
|
+
|
302
|
+
def __init__(self):
|
303
|
+
super().__init__()
|
304
|
+
|
305
|
+
def doLayout(self, tip: TeachTipBubble):
|
306
|
+
""" manage the layout of tip """
|
307
|
+
tip.hBoxLayout.setContentsMargins(0, 0, 0, 0)
|
308
|
+
|
309
|
+
def imagePosition(self):
|
310
|
+
return ImagePosition.TOP
|
311
|
+
|
312
|
+
def position(self, tip: TeachingTip) -> QPoint:
|
313
|
+
pos = self._pos(tip)
|
314
|
+
x, y = pos.x(), pos.y()
|
315
|
+
|
316
|
+
rect = getCurrentScreenGeometry()
|
317
|
+
x = max(rect.left(), min(pos.x(), rect.right() - tip.width() - 4))
|
318
|
+
y = max(rect.top(), min(pos.y(), rect.bottom() - tip.height() - 4))
|
319
|
+
|
320
|
+
return QPoint(x, y)
|
321
|
+
|
322
|
+
def draw(self, tip: TeachTipBubble, painter: QPainter):
|
323
|
+
""" draw the shape of bubble """
|
324
|
+
rect = tip.rect().adjusted(1, 1, -1, -1)
|
325
|
+
painter.drawRoundedRect(rect, 8, 8)
|
326
|
+
|
327
|
+
def _pos(self, tip: TeachingTip):
|
328
|
+
""" return the poisition of tip """
|
329
|
+
return tip.pos()
|
330
|
+
|
331
|
+
@staticmethod
|
332
|
+
def make(position: TeachingTipTailPosition):
|
333
|
+
""" mask teaching tip manager according to the display position """
|
334
|
+
managers = {
|
335
|
+
TeachingTipTailPosition.TOP: TopTailTeachingTipManager,
|
336
|
+
TeachingTipTailPosition.BOTTOM: BottomTailTeachingTipManager,
|
337
|
+
TeachingTipTailPosition.LEFT: LeftTailTeachingTipManager,
|
338
|
+
TeachingTipTailPosition.RIGHT: RightTailTeachingTipManager,
|
339
|
+
TeachingTipTailPosition.TOP_RIGHT: TopRightTailTeachingTipManager,
|
340
|
+
TeachingTipTailPosition.BOTTOM_RIGHT: BottomRightTailTeachingTipManager,
|
341
|
+
TeachingTipTailPosition.TOP_LEFT: TopLeftTailTeachingTipManager,
|
342
|
+
TeachingTipTailPosition.BOTTOM_LEFT: BottomLeftTailTeachingTipManager,
|
343
|
+
TeachingTipTailPosition.LEFT_TOP: LeftTopTailTeachingTipManager,
|
344
|
+
TeachingTipTailPosition.LEFT_BOTTOM: LeftBottomTailTeachingTipManager,
|
345
|
+
TeachingTipTailPosition.RIGHT_TOP: RightTopTailTeachingTipManager,
|
346
|
+
TeachingTipTailPosition.RIGHT_BOTTOM: RightBottomTailTeachingTipManager,
|
347
|
+
TeachingTipTailPosition.NONE: TeachingTipManager,
|
348
|
+
}
|
349
|
+
|
350
|
+
if position not in managers:
|
351
|
+
raise ValueError(
|
352
|
+
f'`{position}` is an invalid teaching tip position.')
|
353
|
+
|
354
|
+
return managers[position]()
|
355
|
+
|
356
|
+
|
357
|
+
class TopTailTeachingTipManager(TeachingTipManager):
|
358
|
+
""" Top tail teaching tip manager """
|
359
|
+
|
360
|
+
def doLayout(self, tip):
|
361
|
+
tip.hBoxLayout.setContentsMargins(0, 8, 0, 0)
|
362
|
+
|
363
|
+
def imagePosition(self):
|
364
|
+
return ImagePosition.BOTTOM
|
365
|
+
|
366
|
+
def draw(self, tip, painter):
|
367
|
+
w, h = tip.width(), tip.height()
|
368
|
+
pt = tip.hBoxLayout.contentsMargins().top()
|
369
|
+
|
370
|
+
path = QPainterPath()
|
371
|
+
path.addRoundedRect(1, pt, w - 2, h - pt - 1, 8, 8)
|
372
|
+
path.addPolygon(
|
373
|
+
QPolygonF([QPointF(w/2 - 7, pt), QPointF(w/2, 1), QPointF(w/2 + 7, pt)]))
|
374
|
+
|
375
|
+
painter.drawPath(path.simplified())
|
376
|
+
|
377
|
+
def _pos(self, tip: TeachingTip):
|
378
|
+
target = tip.target
|
379
|
+
pos = target.mapToGlobal(QPoint(0, target.height()))
|
380
|
+
x = pos.x() + target.width()//2 - tip.sizeHint().width()//2
|
381
|
+
y = pos.y() - tip.layout().contentsMargins().top()
|
382
|
+
return QPoint(x, y)
|
383
|
+
|
384
|
+
|
385
|
+
class BottomTailTeachingTipManager(TeachingTipManager):
|
386
|
+
""" Bottom tail teaching tip manager """
|
387
|
+
|
388
|
+
def doLayout(self, tip):
|
389
|
+
tip.hBoxLayout.setContentsMargins(0, 0, 0, 8)
|
390
|
+
|
391
|
+
def draw(self, tip, painter):
|
392
|
+
w, h = tip.width(), tip.height()
|
393
|
+
pb = tip.hBoxLayout.contentsMargins().bottom()
|
394
|
+
|
395
|
+
path = QPainterPath()
|
396
|
+
path.addRoundedRect(1, 1, w - 2, h - pb - 1, 8, 8)
|
397
|
+
path.addPolygon(
|
398
|
+
QPolygonF([QPointF(w/2 - 7, h - pb), QPointF(w/2, h - 1), QPointF(w/2 + 7, h - pb)]))
|
399
|
+
|
400
|
+
painter.drawPath(path.simplified())
|
401
|
+
|
402
|
+
def _pos(self, tip: TeachingTip):
|
403
|
+
target = tip.target
|
404
|
+
pos = target.mapToGlobal(QPoint())
|
405
|
+
x = pos.x() + target.width()//2 - tip.sizeHint().width()//2
|
406
|
+
y = pos.y() - tip.sizeHint().height() + tip.layout().contentsMargins().bottom()
|
407
|
+
return QPoint(x, y)
|
408
|
+
|
409
|
+
|
410
|
+
class LeftTailTeachingTipManager(TeachingTipManager):
|
411
|
+
""" Left tail teaching tip manager """
|
412
|
+
|
413
|
+
def doLayout(self, tip):
|
414
|
+
tip.hBoxLayout.setContentsMargins(8, 0, 0, 0)
|
415
|
+
|
416
|
+
def imagePosition(self):
|
417
|
+
return ImagePosition.RIGHT
|
418
|
+
|
419
|
+
def draw(self, tip, painter):
|
420
|
+
w, h = tip.width(), tip.height()
|
421
|
+
pl = 8
|
422
|
+
|
423
|
+
path = QPainterPath()
|
424
|
+
path.addRoundedRect(pl, 1, w - pl - 2, h - 2, 8, 8)
|
425
|
+
path.addPolygon(
|
426
|
+
QPolygonF([QPointF(pl, h/2 - 7), QPointF(1, h/2), QPointF(pl, h/2 + 7)]))
|
427
|
+
|
428
|
+
painter.drawPath(path.simplified())
|
429
|
+
|
430
|
+
def _pos(self, tip: TeachingTip):
|
431
|
+
target = tip.target
|
432
|
+
m = tip.layout().contentsMargins()
|
433
|
+
pos = target.mapToGlobal(QPoint(target.width(), 0))
|
434
|
+
x = pos.x() - m.left()
|
435
|
+
y = pos.y() - tip.view.sizeHint().height()//2 + target.height()//2 - m.top()
|
436
|
+
return QPoint(x, y)
|
437
|
+
|
438
|
+
|
439
|
+
class RightTailTeachingTipManager(TeachingTipManager):
|
440
|
+
""" Left tail teaching tip manager """
|
441
|
+
|
442
|
+
def doLayout(self, tip):
|
443
|
+
tip.hBoxLayout.setContentsMargins(0, 0, 8, 0)
|
444
|
+
|
445
|
+
def imagePosition(self):
|
446
|
+
return ImagePosition.LEFT
|
447
|
+
|
448
|
+
def draw(self, tip, painter):
|
449
|
+
w, h = tip.width(), tip.height()
|
450
|
+
pr = 8
|
451
|
+
|
452
|
+
path = QPainterPath()
|
453
|
+
path.addRoundedRect(1, 1, w - pr - 1, h - 2, 8, 8)
|
454
|
+
path.addPolygon(
|
455
|
+
QPolygonF([QPointF(w - pr, h/2 - 7), QPointF(w - 1, h/2), QPointF(w - pr, h/2 + 7)]))
|
456
|
+
|
457
|
+
painter.drawPath(path.simplified())
|
458
|
+
|
459
|
+
def _pos(self, tip: TeachingTip):
|
460
|
+
target = tip.target
|
461
|
+
m = tip.layout().contentsMargins()
|
462
|
+
pos = target.mapToGlobal(QPoint(0, 0))
|
463
|
+
x = pos.x() - tip.sizeHint().width() + m.right()
|
464
|
+
y = pos.y() - tip.view.sizeHint().height()//2 + target.height()//2 - m.top()
|
465
|
+
return QPoint(x, y)
|
466
|
+
|
467
|
+
|
468
|
+
class TopLeftTailTeachingTipManager(TopTailTeachingTipManager):
|
469
|
+
""" Top left tail teaching tip manager """
|
470
|
+
|
471
|
+
def draw(self, tip, painter):
|
472
|
+
w, h = tip.width(), tip.height()
|
473
|
+
pt = tip.hBoxLayout.contentsMargins().top()
|
474
|
+
|
475
|
+
path = QPainterPath()
|
476
|
+
path.addRoundedRect(1, pt, w - 2, h - pt - 1, 8, 8)
|
477
|
+
path.addPolygon(
|
478
|
+
QPolygonF([QPointF(20, pt), QPointF(27, 1), QPointF(34, pt)]))
|
479
|
+
|
480
|
+
painter.drawPath(path.simplified())
|
481
|
+
|
482
|
+
def _pos(self, tip: TeachingTip):
|
483
|
+
target = tip.target
|
484
|
+
pos = target.mapToGlobal(QPoint(0, target.height()))
|
485
|
+
x = pos.x() - tip.layout().contentsMargins().left()
|
486
|
+
y = pos.y() - tip.layout().contentsMargins().top()
|
487
|
+
return QPoint(x, y)
|
488
|
+
|
489
|
+
|
490
|
+
class TopRightTailTeachingTipManager(TopTailTeachingTipManager):
|
491
|
+
""" Top right tail teaching tip manager """
|
492
|
+
|
493
|
+
def draw(self, tip, painter):
|
494
|
+
w, h = tip.width(), tip.height()
|
495
|
+
pt = tip.hBoxLayout.contentsMargins().top()
|
496
|
+
|
497
|
+
path = QPainterPath()
|
498
|
+
path.addRoundedRect(1, pt, w - 2, h - pt - 1, 8, 8)
|
499
|
+
path.addPolygon(
|
500
|
+
QPolygonF([QPointF(w - 20, pt), QPointF(w - 27, 1), QPointF(w - 34, pt)]))
|
501
|
+
|
502
|
+
painter.drawPath(path.simplified())
|
503
|
+
|
504
|
+
def _pos(self, tip: TeachingTip):
|
505
|
+
target = tip.target
|
506
|
+
pos = target.mapToGlobal(QPoint(target.width(), target.height()))
|
507
|
+
x = pos.x() - tip.sizeHint().width() + tip.layout().contentsMargins().left()
|
508
|
+
y = pos.y() - tip.layout().contentsMargins().top()
|
509
|
+
return QPoint(x, y)
|
510
|
+
|
511
|
+
|
512
|
+
class BottomLeftTailTeachingTipManager(BottomTailTeachingTipManager):
|
513
|
+
""" Bottom left tail teaching tip manager """
|
514
|
+
|
515
|
+
def draw(self, tip, painter):
|
516
|
+
w, h = tip.width(), tip.height()
|
517
|
+
pb = tip.hBoxLayout.contentsMargins().bottom()
|
518
|
+
|
519
|
+
path = QPainterPath()
|
520
|
+
path.addRoundedRect(1, 1, w - 2, h - pb - 1, 8, 8)
|
521
|
+
path.addPolygon(
|
522
|
+
QPolygonF([QPointF(20, h - pb), QPointF(27, h - 1), QPointF(34, h - pb)]))
|
523
|
+
|
524
|
+
painter.drawPath(path.simplified())
|
525
|
+
|
526
|
+
def _pos(self, tip: TeachingTip):
|
527
|
+
target = tip.target
|
528
|
+
pos = target.mapToGlobal(QPoint())
|
529
|
+
x = pos.x() - tip.layout().contentsMargins().left()
|
530
|
+
y = pos.y() - tip.sizeHint().height() + tip.layout().contentsMargins().bottom()
|
531
|
+
return QPoint(x, y)
|
532
|
+
|
533
|
+
|
534
|
+
class BottomRightTailTeachingTipManager(BottomTailTeachingTipManager):
|
535
|
+
""" Bottom right tail teaching tip manager """
|
536
|
+
|
537
|
+
def draw(self, tip, painter):
|
538
|
+
w, h = tip.width(), tip.height()
|
539
|
+
pb = tip.hBoxLayout.contentsMargins().bottom()
|
540
|
+
|
541
|
+
path = QPainterPath()
|
542
|
+
path.addRoundedRect(1, 1, w - 2, h - pb - 1, 8, 8)
|
543
|
+
path.addPolygon(
|
544
|
+
QPolygonF([QPointF(w - 20, h - pb), QPointF(w - 27, h - 1), QPointF(w - 34, h - pb)]))
|
545
|
+
|
546
|
+
painter.drawPath(path.simplified())
|
547
|
+
|
548
|
+
def _pos(self, tip: TeachingTip):
|
549
|
+
target = tip.target
|
550
|
+
pos = target.mapToGlobal(QPoint(target.width(), 0))
|
551
|
+
x = pos.x() - tip.sizeHint().width() + tip.layout().contentsMargins().left()
|
552
|
+
y = pos.y() - tip.sizeHint().height() + tip.layout().contentsMargins().bottom()
|
553
|
+
return QPoint(x, y)
|
554
|
+
|
555
|
+
|
556
|
+
class LeftTopTailTeachingTipManager(LeftTailTeachingTipManager):
|
557
|
+
""" Left top tail teaching tip manager """
|
558
|
+
|
559
|
+
def imagePosition(self):
|
560
|
+
return ImagePosition.BOTTOM
|
561
|
+
|
562
|
+
def draw(self, tip, painter):
|
563
|
+
w, h = tip.width(), tip.height()
|
564
|
+
pl = 8
|
565
|
+
|
566
|
+
path = QPainterPath()
|
567
|
+
path.addRoundedRect(pl, 1, w - pl - 2, h - 2, 8, 8)
|
568
|
+
path.addPolygon(
|
569
|
+
QPolygonF([QPointF(pl, 10), QPointF(1, 17), QPointF(pl, 24)]))
|
570
|
+
|
571
|
+
painter.drawPath(path.simplified())
|
572
|
+
|
573
|
+
def _pos(self, tip: TeachingTip):
|
574
|
+
target = tip.target
|
575
|
+
m = tip.layout().contentsMargins()
|
576
|
+
pos = target.mapToGlobal(QPoint(target.width(), 0))
|
577
|
+
x = pos.x() - m.left()
|
578
|
+
y = pos.y() - m.top()
|
579
|
+
return QPoint(x, y)
|
580
|
+
|
581
|
+
|
582
|
+
class LeftBottomTailTeachingTipManager(LeftTailTeachingTipManager):
|
583
|
+
""" Left bottom tail teaching tip manager """
|
584
|
+
|
585
|
+
def imagePosition(self):
|
586
|
+
return ImagePosition.TOP
|
587
|
+
|
588
|
+
def draw(self, tip, painter):
|
589
|
+
w, h = tip.width(), tip.height()
|
590
|
+
pl = 9
|
591
|
+
|
592
|
+
path = QPainterPath()
|
593
|
+
path.addRoundedRect(pl, 1, w - pl - 1, h - 2, 8, 8)
|
594
|
+
path.addPolygon(
|
595
|
+
QPolygonF([QPointF(pl, h - 10), QPointF(1, h - 17), QPointF(pl, h - 24)]))
|
596
|
+
|
597
|
+
painter.drawPath(path.simplified())
|
598
|
+
|
599
|
+
def _pos(self, tip: TeachingTip):
|
600
|
+
target = tip.target
|
601
|
+
m = tip.layout().contentsMargins()
|
602
|
+
pos = target.mapToGlobal(QPoint(target.width(), target.height()))
|
603
|
+
x = pos.x() - m.left()
|
604
|
+
y = pos.y() - tip.sizeHint().height() + m.bottom()
|
605
|
+
return QPoint(x, y)
|
606
|
+
|
607
|
+
|
608
|
+
class RightTopTailTeachingTipManager(RightTailTeachingTipManager):
|
609
|
+
""" Right top tail teaching tip manager """
|
610
|
+
|
611
|
+
def imagePosition(self):
|
612
|
+
return ImagePosition.BOTTOM
|
613
|
+
|
614
|
+
def draw(self, tip, painter):
|
615
|
+
w, h = tip.width(), tip.height()
|
616
|
+
pr = 8
|
617
|
+
|
618
|
+
path = QPainterPath()
|
619
|
+
path.addRoundedRect(1, 1, w - pr - 1, h - 2, 8, 8)
|
620
|
+
path.addPolygon(
|
621
|
+
QPolygonF([QPointF(w - pr, 10), QPointF(w - 1, 17), QPointF(w - pr, 24)]))
|
622
|
+
|
623
|
+
painter.drawPath(path.simplified())
|
624
|
+
|
625
|
+
def _pos(self, tip: TeachingTip):
|
626
|
+
target = tip.target
|
627
|
+
m = tip.layout().contentsMargins()
|
628
|
+
pos = target.mapToGlobal(QPoint(0, 0))
|
629
|
+
x = pos.x() - tip.sizeHint().width() + m.right()
|
630
|
+
y = pos.y() - m.top()
|
631
|
+
return QPoint(x, y)
|
632
|
+
|
633
|
+
|
634
|
+
class RightBottomTailTeachingTipManager(RightTailTeachingTipManager):
|
635
|
+
""" Right bottom tail teaching tip manager """
|
636
|
+
|
637
|
+
def imagePosition(self):
|
638
|
+
return ImagePosition.TOP
|
639
|
+
|
640
|
+
def draw(self, tip, painter):
|
641
|
+
w, h = tip.width(), tip.height()
|
642
|
+
pr = 8
|
643
|
+
|
644
|
+
path = QPainterPath()
|
645
|
+
path.addRoundedRect(1, 1, w - pr - 1, h - 2, 8, 8)
|
646
|
+
path.addPolygon(
|
647
|
+
QPolygonF([QPointF(w - pr, h-10), QPointF(w - 1, h-17), QPointF(w - pr, h-24)]))
|
648
|
+
|
649
|
+
painter.drawPath(path.simplified())
|
650
|
+
|
651
|
+
def _pos(self, tip: TeachingTip):
|
652
|
+
target = tip.target
|
653
|
+
m = tip.layout().contentsMargins()
|
654
|
+
pos = target.mapToGlobal(QPoint(0, target.height()))
|
655
|
+
x = pos.x() - tip.sizeHint().width() + m.right()
|
656
|
+
y = pos.y() - tip.sizeHint().height() + m.bottom()
|
657
|
+
return QPoint(x, y)
|