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,553 @@
1
+ # coding:utf-8
2
+
3
+ from typing import List, Union
4
+
5
+ from PySide6.QtCore import Qt, Property, QPoint, Signal, QSize, QRectF, QUrl
6
+ from PySide6.QtGui import (QPainter, QPixmap, QPalette, QColor, QFont, QImage, QPainterPath,
7
+ QImageReader, QBrush, QMovie, QDesktopServices)
8
+ from PySide6.QtWidgets import QLabel, QWidget, QPushButton, QApplication
9
+
10
+ from ...common.exception_handler import exceptionHandler
11
+ from ...common.overload import singledispatchmethod
12
+ from ...common.font import setFont, getFont
13
+ from ...common.style_sheet import FluentStyleSheet, setCustomStyleSheet, setCustomStyleSheet
14
+ from ...common.config import qconfig, isDarkTheme
15
+ from .menu import LabelContextMenu
16
+
17
+
18
+ class PixmapLabel(QLabel):
19
+ """ Label for high dpi pixmap """
20
+
21
+ def __init__(self, parent=None):
22
+ super().__init__(parent)
23
+ self.__pixmap = QPixmap()
24
+
25
+ def setPixmap(self, pixmap: QPixmap):
26
+ self.__pixmap = pixmap
27
+ self.setFixedSize(pixmap.size())
28
+ self.update()
29
+
30
+ def pixmap(self):
31
+ return self.__pixmap
32
+
33
+ def paintEvent(self, e):
34
+ if self.__pixmap.isNull():
35
+ return super().paintEvent(e)
36
+
37
+ painter = QPainter(self)
38
+ painter.setRenderHints(QPainter.Antialiasing |
39
+ QPainter.SmoothPixmapTransform)
40
+ painter.setPen(Qt.NoPen)
41
+ painter.drawPixmap(self.rect(), self.__pixmap)
42
+
43
+
44
+ class FluentLabelBase(QLabel):
45
+ """ Fluent label base class
46
+
47
+ Constructors
48
+ ------------
49
+ * FluentLabelBase(`parent`: QWidget = None)
50
+ * FluentLabelBase(`text`: str, `parent`: QWidget = None)
51
+ """
52
+
53
+ @singledispatchmethod
54
+ def __init__(self, parent: QWidget = None):
55
+ super().__init__(parent)
56
+ self._init()
57
+
58
+ @__init__.register
59
+ def _(self, text: str, parent: QWidget = None):
60
+ self.__init__(parent)
61
+ self.setText(text)
62
+
63
+ def _init(self):
64
+ FluentStyleSheet.LABEL.apply(self)
65
+ self.setFont(self.getFont())
66
+ self.setTextColor()
67
+ qconfig.themeChanged.connect(lambda: self.setTextColor(self.lightColor, self.darkColor))
68
+
69
+ self.customContextMenuRequested.connect(self._onContextMenuRequested)
70
+ return self
71
+
72
+ def getFont(self):
73
+ raise NotImplementedError
74
+
75
+ @exceptionHandler()
76
+ def setTextColor(self, light=QColor(0, 0, 0), dark=QColor(255, 255, 255)):
77
+ """ set the text color of label
78
+
79
+ Parameters
80
+ ----------
81
+ light, dark: QColor | Qt.GlobalColor | str
82
+ text color in light/dark mode
83
+ """
84
+ self._lightColor = QColor(light)
85
+ self._darkColor = QColor(dark)
86
+
87
+ setCustomStyleSheet(
88
+ self,
89
+ f"FluentLabelBase{{color:{self.lightColor.name(QColor.NameFormat.HexArgb)}}}",
90
+ f"FluentLabelBase{{color:{self.darkColor.name(QColor.NameFormat.HexArgb)}}}"
91
+ )
92
+
93
+ @Property(QColor)
94
+ def lightColor(self):
95
+ return self._lightColor
96
+
97
+ @lightColor.setter
98
+ def lightColor(self, color: QColor):
99
+ self.setTextColor(color, self.darkColor)
100
+
101
+ @Property(QColor)
102
+ def darkColor(self):
103
+ return self._darkColor
104
+
105
+ @darkColor.setter
106
+ def darkColor(self, color: QColor):
107
+ self.setTextColor(self.lightColor, color)
108
+
109
+ @Property(int)
110
+ def pixelFontSize(self):
111
+ return self.font().pixelSize()
112
+
113
+ @pixelFontSize.setter
114
+ def pixelFontSize(self, size: int):
115
+ font = self.font()
116
+ font.setPixelSize(size)
117
+ self.setFont(font)
118
+
119
+ @Property(bool)
120
+ def strikeOut(self):
121
+ return self.font().strikeOut()
122
+
123
+ @strikeOut.setter
124
+ def strikeOut(self, isStrikeOut: bool):
125
+ font = self.font()
126
+ font.setStrikeOut(isStrikeOut)
127
+ self.setFont(font)
128
+
129
+ @Property(bool)
130
+ def underline(self):
131
+ return self.font().underline()
132
+
133
+ @underline.setter
134
+ def underline(self, isUnderline: bool):
135
+ font = self.font()
136
+ font.setStyle()
137
+ font.setUnderline(isUnderline)
138
+ self.setFont(font)
139
+
140
+ def _onContextMenuRequested(self, pos):
141
+ menu = LabelContextMenu(parent=self)
142
+ menu.exec(self.mapToGlobal(pos))
143
+
144
+
145
+ class CaptionLabel(FluentLabelBase):
146
+ """ Caption text label
147
+
148
+ Constructors
149
+ ------------
150
+ * CaptionLabel(`parent`: QWidget = None)
151
+ * CaptionLabel(`text`: str, `parent`: QWidget = None)
152
+ """
153
+
154
+ def getFont(self):
155
+ return getFont(12)
156
+
157
+
158
+ class BodyLabel(FluentLabelBase):
159
+ """ Body text label
160
+
161
+ Constructors
162
+ ------------
163
+ * BodyLabel(`parent`: QWidget = None)
164
+ * BodyLabel(`text`: str, `parent`: QWidget = None)
165
+ """
166
+
167
+ def getFont(self):
168
+ return getFont(14)
169
+
170
+
171
+ class StrongBodyLabel(FluentLabelBase):
172
+ """ Strong body text label
173
+
174
+ Constructors
175
+ ------------
176
+ * StrongBodyLabel(`parent`: QWidget = None)
177
+ * StrongBodyLabel(`text`: str, `parent`: QWidget = None)
178
+ """
179
+
180
+ def getFont(self):
181
+ return getFont(14, QFont.DemiBold)
182
+
183
+
184
+ class SubtitleLabel(FluentLabelBase):
185
+ """ Subtitle text label
186
+
187
+ Constructors
188
+ ------------
189
+ * SubtitleLabel(`parent`: QWidget = None)
190
+ * SubtitleLabel(`text`: str, `parent`: QWidget = None)
191
+ """
192
+
193
+ def getFont(self):
194
+ return getFont(20, QFont.DemiBold)
195
+
196
+
197
+ class TitleLabel(FluentLabelBase):
198
+ """ Sub title text label
199
+
200
+ Constructors
201
+ ------------
202
+ * TitleLabel(`parent`: QWidget = None)
203
+ * TitleLabel(`text`: str, `parent`: QWidget = None)
204
+ """
205
+
206
+ def getFont(self):
207
+ return getFont(28, QFont.DemiBold)
208
+
209
+
210
+ class LargeTitleLabel(FluentLabelBase):
211
+ """ Large title text label
212
+
213
+ Constructors
214
+ ------------
215
+ * LargeTitleLabel(`parent`: QWidget = None)
216
+ * LargeTitleLabel(`text`: str, `parent`: QWidget = None)
217
+ """
218
+
219
+ def getFont(self):
220
+ return getFont(40, QFont.DemiBold)
221
+
222
+
223
+ class DisplayLabel(FluentLabelBase):
224
+ """ Display text label
225
+
226
+ Constructors
227
+ ------------
228
+ * DisplayLabel(`parent`: QWidget = None)
229
+ * DisplayLabel(`text`: str, `parent`: QWidget = None)
230
+ """
231
+
232
+ def getFont(self):
233
+ return getFont(68, QFont.DemiBold)
234
+
235
+
236
+ class ImageLabel(QLabel):
237
+ """ Image label
238
+
239
+ Constructors
240
+ ------------
241
+ * ImageLabel(`parent`: QWidget = None)
242
+ * ImageLabel(`image`: str | QImage | QPixmap, `parent`: QWidget = None)
243
+ """
244
+
245
+ clicked = Signal()
246
+
247
+ @singledispatchmethod
248
+ def __init__(self, parent: QWidget = None):
249
+ super().__init__(parent)
250
+ self.image = QImage()
251
+ self.setBorderRadius(0, 0, 0, 0)
252
+ self._postInit()
253
+
254
+ @__init__.register
255
+ def _(self, image: str, parent=None):
256
+ self.__init__(parent)
257
+ self.setImage(image)
258
+ self._postInit()
259
+
260
+ @__init__.register
261
+ def _(self, image: QImage, parent=None):
262
+ self.__init__(parent)
263
+ self.setImage(image)
264
+ self._postInit()
265
+
266
+ @__init__.register
267
+ def _(self, image: QPixmap, parent=None):
268
+ self.__init__(parent)
269
+ self.setImage(image)
270
+ self._postInit()
271
+
272
+ def _postInit(self):
273
+ pass
274
+
275
+ def _onFrameChanged(self, index: int):
276
+ self.image = self.movie().currentImage()
277
+ self.update()
278
+
279
+ def setBorderRadius(self, topLeft: int, topRight: int, bottomLeft: int, bottomRight: int):
280
+ """ set the border radius of image """
281
+ self._topLeftRadius = topLeft
282
+ self._topRightRadius = topRight
283
+ self._bottomLeftRadius = bottomLeft
284
+ self._bottomRightRadius = bottomRight
285
+ self.update()
286
+
287
+ def setImage(self, image: Union[str, QPixmap, QImage] = None):
288
+ """ set the image of label """
289
+ self.image = image or QImage()
290
+
291
+ if isinstance(image, str):
292
+ reader = QImageReader(image)
293
+ if reader.supportsAnimation():
294
+ self.setMovie(QMovie(image))
295
+ else:
296
+ self.image = reader.read()
297
+ elif isinstance(image, QPixmap):
298
+ self.image = image.toImage()
299
+
300
+ self.setFixedSize(self.image.size())
301
+ self.update()
302
+
303
+ def scaledToWidth(self, width: int):
304
+ if self.isNull():
305
+ return
306
+
307
+ h = int(width / self.image.width() * self.image.height())
308
+ self.setFixedSize(width, h)
309
+
310
+ if self.movie():
311
+ self.movie().setScaledSize(QSize(width, h))
312
+
313
+ def scaledToHeight(self, height: int):
314
+ if self.isNull():
315
+ return
316
+
317
+ w = int(height / self.image.height() * self.image.width())
318
+ self.setFixedSize(w, height)
319
+
320
+ if self.movie():
321
+ self.movie().setScaledSize(QSize(w, height))
322
+
323
+ def setScaledSize(self, size: QSize):
324
+ if self.isNull():
325
+ return
326
+
327
+ self.setFixedSize(size)
328
+
329
+ if self.movie():
330
+ self.movie().setScaledSize(size)
331
+
332
+ def isNull(self):
333
+ return self.image.isNull()
334
+
335
+ def mouseReleaseEvent(self, e):
336
+ super().mouseReleaseEvent(e)
337
+ self.clicked.emit()
338
+
339
+ def setPixmap(self, pixmap: QPixmap):
340
+ self.setImage(pixmap)
341
+
342
+ def pixmap(self) -> QPixmap:
343
+ return QPixmap.fromImage(self.image)
344
+
345
+ def setMovie(self, movie: QMovie):
346
+ super().setMovie(movie)
347
+ self.movie().start()
348
+ self.image = self.movie().currentImage()
349
+ self.movie().frameChanged.connect(self._onFrameChanged)
350
+
351
+ def paintEvent(self, e):
352
+ if self.isNull():
353
+ return
354
+
355
+ painter = QPainter(self)
356
+ painter.setRenderHints(QPainter.Antialiasing)
357
+
358
+ path = QPainterPath()
359
+ w, h = self.width(), self.height()
360
+
361
+ # top line
362
+ path.moveTo(self.topLeftRadius, 0)
363
+ path.lineTo(w - self.topRightRadius, 0)
364
+
365
+ # top right arc
366
+ d = self.topRightRadius * 2
367
+ path.arcTo(w - d, 0, d, d, 90, -90)
368
+
369
+ # right line
370
+ path.lineTo(w, h - self.bottomRightRadius)
371
+
372
+ # bottom right arc
373
+ d = self.bottomRightRadius * 2
374
+ path.arcTo(w - d, h - d, d, d, 0, -90)
375
+
376
+ # bottom line
377
+ path.lineTo(self.bottomLeftRadius, h)
378
+
379
+ # bottom left arc
380
+ d = self.bottomLeftRadius * 2
381
+ path.arcTo(0, h - d, d, d, -90, -90)
382
+
383
+ # left line
384
+ path.lineTo(0, self.topLeftRadius)
385
+
386
+ # top left arc
387
+ d = self.topLeftRadius * 2
388
+ path.arcTo(0, 0, d, d, -180, -90)
389
+
390
+ # draw image
391
+ image = self.image.scaled(
392
+ self.size()*self.devicePixelRatioF(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
393
+
394
+ painter.setPen(Qt.NoPen)
395
+ painter.setClipPath(path)
396
+ painter.drawImage(self.rect(), image)
397
+
398
+ @Property(int)
399
+ def topLeftRadius(self):
400
+ return self._topLeftRadius
401
+
402
+ @topLeftRadius.setter
403
+ def topLeftRadius(self, radius: int):
404
+ self.setBorderRadius(radius, self.topRightRadius, self.bottomLeftRadius, self.bottomRightRadius)
405
+
406
+ @Property(int)
407
+ def topRightRadius(self):
408
+ return self._topRightRadius
409
+
410
+ @topRightRadius.setter
411
+ def topRightRadius(self, radius: int):
412
+ self.setBorderRadius(self.topLeftRadius, radius, self.bottomLeftRadius, self.bottomRightRadius)
413
+
414
+ @Property(int)
415
+ def bottomLeftRadius(self):
416
+ return self._bottomLeftRadius
417
+
418
+ @bottomLeftRadius.setter
419
+ def bottomLeftRadius(self, radius: int):
420
+ self.setBorderRadius(self.topLeftRadius, self.topRightRadius, radius, self.bottomRightRadius)
421
+
422
+ @Property(int)
423
+ def bottomRightRadius(self):
424
+ return self._bottomRightRadius
425
+
426
+ @bottomRightRadius.setter
427
+ def bottomRightRadius(self, radius: int):
428
+ self.setBorderRadius(
429
+ self.topLeftRadius, self.topRightRadius, self.bottomLeftRadius, radius)
430
+
431
+
432
+ class AvatarWidget(ImageLabel):
433
+ """ Avatar widget
434
+
435
+ Constructors
436
+ ------------
437
+ * AvatarWidget(`parent`: QWidget = None)
438
+ * AvatarWidget(`image`: str | QImage | QPixmap, `parent`: QWidget = None)
439
+ """
440
+
441
+ def _postInit(self):
442
+ self.setRadius(48)
443
+ self.lightBackgroundColor = QColor(0, 0, 0, 50)
444
+ self.darkBackgroundColor = QColor(255, 255, 255, 50)
445
+
446
+ def getRadius(self):
447
+ return self._radius
448
+
449
+ def setRadius(self, radius: int):
450
+ self._radius = radius
451
+ setFont(self, radius)
452
+ self.setFixedSize(2*radius, 2*radius)
453
+ self.update()
454
+
455
+ def setBackgroundColor(self, light: QColor, dark: QColor):
456
+ self.lightBackgroundColor = QColor(light)
457
+ self.darkBackgroundColor = QColor(light)
458
+ self.update()
459
+
460
+ def paintEvent(self, e):
461
+ painter = QPainter(self)
462
+ painter.setRenderHints(QPainter.Antialiasing)
463
+
464
+ if not self.isNull():
465
+ self._drawImageAvatar(painter)
466
+ else:
467
+ self._drawTextAvatar(painter)
468
+
469
+ def _drawImageAvatar(self, painter: QPainter):
470
+ # center crop image
471
+ image = self.image.scaled(
472
+ self.size()*self.devicePixelRatioF(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) # type: QImage
473
+
474
+ iw, ih = image.width(), image.height()
475
+ d = self.getRadius() * 2 * self.devicePixelRatioF()
476
+ x, y = (iw - d) / 2, (ih - d) / 2
477
+ image = image.copy(int(x), int(y), int(d), int(d))
478
+
479
+ # draw image
480
+ path = QPainterPath()
481
+ path.addEllipse(QRectF(self.rect()))
482
+
483
+ painter.setPen(Qt.NoPen)
484
+ painter.setClipPath(path)
485
+ painter.drawImage(self.rect(), image)
486
+
487
+ def _drawTextAvatar(self, painter: QPainter):
488
+ if not self.text():
489
+ return
490
+
491
+ painter.setBrush(self.darkBackgroundColor if isDarkTheme() else self.lightBackgroundColor)
492
+ painter.setPen(Qt.NoPen)
493
+ painter.drawEllipse(QRectF(self.rect()))
494
+
495
+ painter.setFont(self.font())
496
+ painter.setPen(Qt.white if isDarkTheme() else Qt.black)
497
+ painter.drawText(self.rect(), Qt.AlignCenter, self.text()[0].upper())
498
+
499
+ radius = Property(int, getRadius, setRadius)
500
+
501
+
502
+ class HyperlinkLabel(QPushButton):
503
+ """ Hyperlink label
504
+
505
+ Constructors
506
+ ------------
507
+ * HyperlinkLabel(`parent`: QWidget = None)
508
+ * HyperlinkLabel(`text`: str, `parent`: QWidget = None)
509
+ * HyperlinkLabel(`url`: QUrl, `parent`: QWidget = None)
510
+ """
511
+
512
+ @singledispatchmethod
513
+ def __init__(self, parent=None):
514
+ super().__init__(parent=parent)
515
+ self._url = QUrl()
516
+
517
+ setFont(self, 14)
518
+ self.setUnderlineVisible(False)
519
+ FluentStyleSheet.LABEL.apply(self)
520
+ self.setCursor(Qt.PointingHandCursor)
521
+ self.clicked.connect(self._onClicked)
522
+
523
+ @__init__.register
524
+ def _(self, text: str, parent=None):
525
+ self.__init__(parent)
526
+ self.setText(text)
527
+
528
+ @__init__.register
529
+ def _(self, url: QUrl, text: str, parent=None):
530
+ self.__init__(parent)
531
+ self.setText(text)
532
+ self._url = url
533
+
534
+ def getUrl(self) -> QUrl:
535
+ return self._url
536
+
537
+ def setUrl(self, url: Union[QUrl, str]):
538
+ self._url = QUrl(url)
539
+
540
+ def isUnderlineVisible(self):
541
+ return self._isUnderlineVisible
542
+
543
+ def setUnderlineVisible(self, isVisible: bool):
544
+ self._isUnderlineVisible = isVisible
545
+ self.setProperty('underline', isVisible)
546
+ self.setStyle(QApplication.style())
547
+
548
+ def _onClicked(self):
549
+ if self.getUrl().isValid():
550
+ QDesktopServices.openUrl(self.getUrl())
551
+
552
+ url = Property(QUrl, getUrl, setUrl)
553
+ underlineVisible = Property(bool, isUnderlineVisible, setUnderlineVisible)