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,369 @@
1
+ # coding:utf-8
2
+ from typing import List, Union
3
+ from PySide6.QtCore import Qt, Signal, QRectF, Property, QPropertyAnimation, QPoint, QSize
4
+ from PySide6.QtGui import QPixmap, QPainter, QColor, QPainterPath, QFont, QIcon
5
+ from PySide6.QtWidgets import QWidget, QFrame, QVBoxLayout, QHBoxLayout, QLabel
6
+
7
+ from ...common.overload import singledispatchmethod
8
+ from ...common.style_sheet import isDarkTheme, FluentStyleSheet
9
+ from ...common.animation import BackgroundAnimationWidget, DropShadowAnimation
10
+ from ...common.font import setFont
11
+ from ...common.icon import FluentIconBase
12
+ from .label import BodyLabel, CaptionLabel
13
+ from .icon_widget import IconWidget
14
+
15
+
16
+ class CardWidget(BackgroundAnimationWidget, QFrame):
17
+ """ Card widget """
18
+
19
+ clicked = Signal()
20
+
21
+ def __init__(self, parent=None):
22
+ super().__init__(parent=parent)
23
+ self._isClickEnabled = False
24
+ self._borderRadius = 5
25
+
26
+ def mouseReleaseEvent(self, e):
27
+ super().mouseReleaseEvent(e)
28
+ self.clicked.emit()
29
+
30
+ def setClickEnabled(self, isEnabled: bool):
31
+ self._isClickEnabled = isEnabled
32
+ self.update()
33
+
34
+ def isClickEnabled(self):
35
+ return self._isClickEnabled
36
+
37
+ def _normalBackgroundColor(self):
38
+ return QColor(255, 255, 255, 13 if isDarkTheme() else 170)
39
+
40
+ def _hoverBackgroundColor(self):
41
+ return QColor(255, 255, 255, 21 if isDarkTheme() else 64)
42
+
43
+ def _pressedBackgroundColor(self):
44
+ return QColor(255, 255, 255, 8 if isDarkTheme() else 64)
45
+
46
+ def getBorderRadius(self):
47
+ return self._borderRadius
48
+
49
+ def setBorderRadius(self, radius: int):
50
+ self._borderRadius = radius
51
+ self.update()
52
+
53
+ def paintEvent(self, e):
54
+ painter = QPainter(self)
55
+ painter.setRenderHints(QPainter.Antialiasing)
56
+
57
+ w, h = self.width(), self.height()
58
+ r = self.borderRadius
59
+ d = 2 * r
60
+
61
+ isDark = isDarkTheme()
62
+
63
+ # draw top border
64
+ path = QPainterPath()
65
+ # path.moveTo(1, h - r)
66
+ path.arcMoveTo(1, h - d - 1, d, d, 240)
67
+ path.arcTo(1, h - d - 1, d, d, 225, -60)
68
+ path.lineTo(1, r)
69
+ path.arcTo(1, 1, d, d, -180, -90)
70
+ path.lineTo(w - r, 1)
71
+ path.arcTo(w - d - 1, 1, d, d, 90, -90)
72
+ path.lineTo(w - 1, h - r)
73
+ path.arcTo(w - d - 1, h - d - 1, d, d, 0, -60)
74
+
75
+ topBorderColor = QColor(0, 0, 0, 20)
76
+ if isDark:
77
+ if self.isPressed:
78
+ topBorderColor = QColor(255, 255, 255, 18)
79
+ elif self.isHover:
80
+ topBorderColor = QColor(255, 255, 255, 13)
81
+ else:
82
+ topBorderColor = QColor(0, 0, 0, 15)
83
+
84
+ painter.strokePath(path, topBorderColor)
85
+
86
+ # draw bottom border
87
+ path = QPainterPath()
88
+ path.arcMoveTo(1, h - d - 1, d, d, 240)
89
+ path.arcTo(1, h - d - 1, d, d, 240, 30)
90
+ path.lineTo(w - r - 1, h - 1)
91
+ path.arcTo(w - d - 1, h - d - 1, d, d, 270, 30)
92
+
93
+ bottomBorderColor = topBorderColor
94
+ if not isDark and self.isHover and not self.isPressed:
95
+ bottomBorderColor = QColor(0, 0, 0, 27)
96
+
97
+ painter.strokePath(path, bottomBorderColor)
98
+
99
+ # draw background
100
+ painter.setPen(Qt.NoPen)
101
+ rect = self.rect().adjusted(1, 1, -1, -1)
102
+ painter.setBrush(self.backgroundColor)
103
+ painter.drawRoundedRect(rect, r, r)
104
+
105
+ borderRadius = Property(int, getBorderRadius, setBorderRadius)
106
+
107
+
108
+
109
+ class SimpleCardWidget(CardWidget):
110
+ """ Simple card widget """
111
+
112
+ def __init__(self, parent=None):
113
+ super().__init__(parent)
114
+
115
+ def _normalBackgroundColor(self):
116
+ return QColor(255, 255, 255, 13 if isDarkTheme() else 170)
117
+
118
+ def _hoverBackgroundColor(self):
119
+ return self._normalBackgroundColor()
120
+
121
+ def _pressedBackgroundColor(self):
122
+ return self._normalBackgroundColor()
123
+
124
+ def paintEvent(self, e):
125
+ painter = QPainter(self)
126
+ painter.setRenderHints(QPainter.Antialiasing)
127
+ painter.setBrush(self.backgroundColor)
128
+
129
+ if isDarkTheme():
130
+ painter.setPen(QColor(0, 0, 0, 48))
131
+ else:
132
+ painter.setPen(QColor(0, 0, 0, 12))
133
+
134
+ r = self.borderRadius
135
+ painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), r, r)
136
+
137
+
138
+
139
+ class ElevatedCardWidget(SimpleCardWidget):
140
+ """ Card widget with shadow effect """
141
+
142
+ def __init__(self, parent=None):
143
+ super().__init__(parent)
144
+ self.shadowAni = DropShadowAnimation(self, hoverColor=QColor(0, 0, 0, 20))
145
+ self.shadowAni.setOffset(0, 5)
146
+ self.shadowAni.setBlurRadius(38)
147
+
148
+ self.elevatedAni = QPropertyAnimation(self, b'pos', self)
149
+ self.elevatedAni.setDuration(100)
150
+
151
+ self._originalPos = self.pos()
152
+ self.setBorderRadius(8)
153
+
154
+ def enterEvent(self, e):
155
+ super().enterEvent(e)
156
+
157
+ if self.elevatedAni.state() != QPropertyAnimation.Running:
158
+ self._originalPos = self.pos()
159
+
160
+ self._startElevateAni(self.pos(), self.pos() - QPoint(0, 3))
161
+
162
+ def leaveEvent(self, e):
163
+ super().leaveEvent(e)
164
+ self._startElevateAni(self.pos(), self._originalPos)
165
+
166
+ def mousePressEvent(self, e):
167
+ super().mousePressEvent(e)
168
+ self._startElevateAni(self.pos(), self._originalPos)
169
+
170
+ def _startElevateAni(self, start, end):
171
+ self.elevatedAni.setStartValue(start)
172
+ self.elevatedAni.setEndValue(end)
173
+ self.elevatedAni.start()
174
+
175
+ def _hoverBackgroundColor(self):
176
+ return QColor(255, 255, 255, 16) if isDarkTheme() else QColor(255, 255, 255)
177
+
178
+ def _pressedBackgroundColor(self):
179
+ return QColor(255, 255, 255, 6 if isDarkTheme() else 118)
180
+
181
+
182
+
183
+ class CardSeparator(QWidget):
184
+ """ Card separator """
185
+
186
+ def __init__(self, parent=None):
187
+ super().__init__(parent=parent)
188
+ self.setFixedHeight(3)
189
+
190
+ def paintEvent(self, e):
191
+ painter = QPainter(self)
192
+ painter.setRenderHints(QPainter.Antialiasing)
193
+
194
+ if isDarkTheme():
195
+ painter.setPen(QColor(255, 255, 255, 46))
196
+ else:
197
+ painter.setPen(QColor(0, 0, 0, 12))
198
+
199
+ painter.drawLine(2, 1, self.width() - 2, 1)
200
+
201
+
202
+ class HeaderCardWidget(SimpleCardWidget):
203
+ """ Header card widget """
204
+
205
+ @singledispatchmethod
206
+ def __init__(self, parent=None):
207
+ super().__init__(parent)
208
+ self.headerView = QWidget(self)
209
+ self.headerLabel = QLabel(self)
210
+ self.separator = CardSeparator(self)
211
+ self.view = QWidget(self)
212
+
213
+ self.vBoxLayout = QVBoxLayout(self)
214
+ self.headerLayout = QHBoxLayout(self.headerView)
215
+ self.viewLayout = QHBoxLayout(self.view)
216
+
217
+ self.headerLayout.addWidget(self.headerLabel)
218
+ self.headerLayout.setContentsMargins(24, 0, 16, 0)
219
+ self.headerView.setFixedHeight(48)
220
+
221
+ self.vBoxLayout.setSpacing(0)
222
+ self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
223
+ self.vBoxLayout.addWidget(self.headerView)
224
+ self.vBoxLayout.addWidget(self.separator)
225
+ self.vBoxLayout.addWidget(self.view)
226
+
227
+ self.viewLayout.setContentsMargins(24, 24, 24, 24)
228
+ setFont(self.headerLabel, 15, QFont.DemiBold)
229
+
230
+ self.view.setObjectName('view')
231
+ self.headerView.setObjectName('headerView')
232
+ self.headerLabel.setObjectName('headerLabel')
233
+ FluentStyleSheet.CARD_WIDGET.apply(self)
234
+
235
+ self._postInit()
236
+
237
+ @__init__.register
238
+ def _(self, title: str, parent=None):
239
+ self.__init__(parent)
240
+ self.setTitle(title)
241
+
242
+ def getTitle(self):
243
+ return self.headerLabel.text()
244
+
245
+ def setTitle(self, title: str):
246
+ self.headerLabel.setText(title)
247
+
248
+ def _postInit(self):
249
+ pass
250
+
251
+ title = Property(str, getTitle, setTitle)
252
+
253
+
254
+
255
+ class CardGroupWidget(QWidget):
256
+
257
+ def __init__(self, icon: Union[str, FluentIconBase, QIcon], title: str, content: str, parent=None):
258
+ super().__init__(parent=parent)
259
+ self.vBoxLayout = QVBoxLayout(self)
260
+ self.hBoxLayout = QHBoxLayout()
261
+
262
+ self.iconWidget = IconWidget(icon)
263
+ self.titleLabel = BodyLabel(title)
264
+ self.contentLabel = CaptionLabel(content)
265
+ self.textLayout = QVBoxLayout()
266
+
267
+ self.separator = CardSeparator()
268
+
269
+ self.__initWidget()
270
+
271
+ def __initWidget(self):
272
+ self.separator.hide()
273
+ self.iconWidget.setFixedSize(20, 20)
274
+ self.contentLabel.setTextColor(QColor(96, 96, 96), QColor(206, 206, 206))
275
+
276
+ self.vBoxLayout.setSpacing(0)
277
+ self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
278
+ self.vBoxLayout.addLayout(self.hBoxLayout)
279
+ self.vBoxLayout.addWidget(self.separator)
280
+
281
+ self.textLayout.addWidget(self.titleLabel)
282
+ self.textLayout.addWidget(self.contentLabel)
283
+ self.hBoxLayout.addWidget(self.iconWidget)
284
+ self.hBoxLayout.addLayout(self.textLayout)
285
+ self.hBoxLayout.addStretch(1)
286
+
287
+ self.hBoxLayout.setSpacing(15)
288
+ self.hBoxLayout.setContentsMargins(24, 10, 24, 10)
289
+ self.textLayout.setContentsMargins(0, 0, 0, 0)
290
+ self.textLayout.setSpacing(0)
291
+ self.hBoxLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)
292
+ self.textLayout.setAlignment(Qt.AlignmentFlag.AlignCenter)
293
+
294
+ def title(self):
295
+ return self.titleLabel.text()
296
+
297
+ def setTitle(self, text: str):
298
+ self.titleLabel.setText(text)
299
+
300
+ def content(self):
301
+ return self.contentLabel.text()
302
+
303
+ def setContent(self, text: str):
304
+ self.contentLabel.setText(text)
305
+
306
+ def icon(self):
307
+ return self.iconWidget.icon
308
+
309
+ def setIcon(self, icon: Union[str, FluentIconBase, QIcon]):
310
+ self.iconWidget.setIcon(icon)
311
+
312
+ def setIconSize(self, size: QSize):
313
+ self.iconWidget.setFixedSize(size)
314
+
315
+ def setSeparatorVisible(self, isVisible: bool):
316
+ self.separator.setVisible(isVisible)
317
+
318
+ def isSeparatorVisible(self):
319
+ return self.separator.isVisible()
320
+
321
+ def addWidget(self, widget: QWidget, stretch=0):
322
+ self.hBoxLayout.addWidget(widget, stretch=stretch)
323
+
324
+
325
+ class GroupHeaderCardWidget(HeaderCardWidget):
326
+ """ Group header card widget """
327
+
328
+ def _postInit(self):
329
+ super()._postInit()
330
+ self.groupWidgets = [] # type: List[CardGroupWidget]
331
+ self.groupLayout = QVBoxLayout()
332
+
333
+ self.groupLayout.setSpacing(0)
334
+ self.viewLayout.setContentsMargins(0, 0, 0, 0)
335
+ self.groupLayout.setContentsMargins(0, 0, 0, 0)
336
+ self.viewLayout.addLayout(self.groupLayout)
337
+
338
+ def addGroup(self, icon: Union[str, FluentIconBase, QIcon], title: str, content: str, widget: QWidget, stretch=0) -> CardGroupWidget:
339
+ """ add widget to a new group
340
+
341
+ Parameters
342
+ ----------
343
+ icon: str | QIcon | FluentIconBase
344
+ the icon to be drawn
345
+
346
+ title: str
347
+ the title of card
348
+
349
+ content: str
350
+ the content of card
351
+
352
+ widget: QWidget
353
+ the widget to be added
354
+
355
+ stretch: int
356
+ the layout stretch of widget
357
+ """
358
+ group = CardGroupWidget(icon, title, content, self)
359
+ group.addWidget(widget, stretch=stretch)
360
+
361
+ if self.groupWidgets:
362
+ self.groupWidgets[-1].setSeparatorVisible(True)
363
+
364
+ self.groupLayout.addWidget(group)
365
+ self.groupWidgets.append(group)
366
+ return group
367
+
368
+ def groupCount(self):
369
+ return len(self.groupWidgets)
@@ -0,0 +1,203 @@
1
+ # coding: utf-8
2
+ from enum import Enum
3
+
4
+ from PySide6.QtCore import Qt
5
+ from PySide6.QtGui import QPainter, QColor
6
+ from PySide6.QtWidgets import QCheckBox, QStyle, QStyleOptionButton, QWidget
7
+
8
+ from ...common.icon import FluentIconBase, Theme, getIconColor
9
+ from ...common.style_sheet import FluentStyleSheet, isDarkTheme, ThemeColor, themeColor, setCustomStyleSheet
10
+ from ...common.overload import singledispatchmethod
11
+ from ...common.color import fallbackThemeColor, validColor
12
+
13
+
14
+ class CheckBoxIcon(FluentIconBase, Enum):
15
+ """ CheckBoxIcon """
16
+
17
+ ACCEPT = "Accept"
18
+ PARTIAL_ACCEPT = "PartialAccept"
19
+
20
+ def path(self, theme=Theme.AUTO):
21
+ c = getIconColor(theme, reverse=True)
22
+ return f':/fastuiwidgets/images/check_box/{self.value}_{c}.svg'
23
+
24
+
25
+ class CheckBoxState(Enum):
26
+ """ Check box state """
27
+
28
+ NORMAL = 0
29
+ HOVER = 1
30
+ PRESSED = 2
31
+ CHECKED = 3
32
+ CHECKED_HOVER = 4
33
+ CHECKED_PRESSED = 5
34
+ DISABLED = 6
35
+ CHECKED_DISABLED = 7
36
+
37
+
38
+ class CheckBox(QCheckBox):
39
+ """ Check box
40
+
41
+ Constructors
42
+ ------------
43
+ * CheckBox(`parent`: QWidget = None)
44
+ * CheckBox(`text`: str, `parent`: QWidget = None)
45
+ """
46
+
47
+ @singledispatchmethod
48
+ def __init__(self, parent: QWidget = None):
49
+ super().__init__(parent)
50
+ FluentStyleSheet.CHECK_BOX.apply(self)
51
+ self.isPressed = False
52
+ self.isHover = False
53
+ self.lightCheckedColor = QColor()
54
+ self.darkCheckedColor = QColor()
55
+ self.lightTextColor = QColor(0, 0, 0)
56
+ self.darkTextColor = QColor(255, 255, 255)
57
+
58
+ self._states = {}
59
+
60
+ @__init__.register
61
+ def _(self, text: str, parent: QWidget = None):
62
+ self.__init__(parent)
63
+ self.setText(text)
64
+
65
+ def mousePressEvent(self, e):
66
+ self.isPressed = True
67
+ super().mousePressEvent(e)
68
+
69
+ def mouseReleaseEvent(self, e):
70
+ self.isPressed = False
71
+ super().mouseReleaseEvent(e)
72
+
73
+ def enterEvent(self, e):
74
+ self.isHover = True
75
+ self.update()
76
+
77
+ def leaveEvent(self, e):
78
+ self.isHover = False
79
+ self.update()
80
+
81
+ def setCheckedColor(self, light, dark):
82
+ """ set the color of indicator in checked status
83
+
84
+ Parameters
85
+ ----------
86
+ light, dark: str | QColor | Qt.GlobalColor
87
+ indicator color in light/dark theme mode
88
+ """
89
+ self.lightCheckedColor = QColor(light)
90
+ self.darkCheckedColor = QColor(dark)
91
+ self.update()
92
+
93
+ def setTextColor(self, light, dark):
94
+ """ set the color of text
95
+
96
+ Parameters
97
+ ----------
98
+ light, dark: str | QColor | Qt.GlobalColor
99
+ text color in light/dark theme mode
100
+ """
101
+ self.lightTextColor = QColor(light)
102
+ self.darkTextColor = QColor(dark)
103
+
104
+ setCustomStyleSheet(
105
+ self,
106
+ f"CheckBox{{color:{self.lightTextColor.name(QColor.NameFormat.HexArgb)}}}",
107
+ f"CheckBox{{color:{self.darkTextColor.name(QColor.NameFormat.HexArgb)}}}"
108
+ )
109
+
110
+ def _borderColor(self):
111
+ if isDarkTheme():
112
+ map = {
113
+ CheckBoxState.NORMAL: QColor(255, 255, 255, 141),
114
+ CheckBoxState.HOVER: QColor(255, 255, 255, 141),
115
+ CheckBoxState.PRESSED: QColor(255, 255, 255, 40),
116
+ CheckBoxState.CHECKED : fallbackThemeColor(self.darkCheckedColor),
117
+ CheckBoxState.CHECKED_HOVER: validColor(self.darkCheckedColor, ThemeColor.DARK_1.color()),
118
+ CheckBoxState.CHECKED_PRESSED : validColor(self.darkCheckedColor, ThemeColor.DARK_2.color()),
119
+ CheckBoxState.DISABLED : QColor(255, 255, 255, 41),
120
+ CheckBoxState.CHECKED_DISABLED : QColor(0, 0, 0, 0)
121
+ }
122
+ else:
123
+ map = {
124
+ CheckBoxState.NORMAL: QColor(0, 0, 0, 122),
125
+ CheckBoxState.HOVER: QColor(0, 0, 0, 143),
126
+ CheckBoxState.PRESSED: QColor(0, 0, 0, 69),
127
+ CheckBoxState.CHECKED : fallbackThemeColor(self.lightCheckedColor),
128
+ CheckBoxState.CHECKED_HOVER : validColor(self.lightCheckedColor, ThemeColor.LIGHT_1.color()),
129
+ CheckBoxState.CHECKED_PRESSED : validColor(self.lightCheckedColor, ThemeColor.LIGHT_2.color()),
130
+ CheckBoxState.DISABLED : QColor(0, 0, 0, 56),
131
+ CheckBoxState.CHECKED_DISABLED : QColor(0, 0, 0, 0)
132
+ }
133
+
134
+ return map[self._state()]
135
+
136
+ def _backgroundColor(self):
137
+ if isDarkTheme():
138
+ map = {
139
+ CheckBoxState.NORMAL: QColor(0, 0, 0, 26),
140
+ CheckBoxState.HOVER: QColor(255, 255, 255, 11),
141
+ CheckBoxState.PRESSED: QColor(255, 255, 255, 18),
142
+ CheckBoxState.CHECKED: fallbackThemeColor(self.darkCheckedColor),
143
+ CheckBoxState.CHECKED_HOVER: validColor(self.darkCheckedColor, ThemeColor.DARK_1.color()),
144
+ CheckBoxState.CHECKED_PRESSED: validColor(self.darkCheckedColor, ThemeColor.DARK_2.color()),
145
+ CheckBoxState.DISABLED: QColor(0, 0, 0, 0),
146
+ CheckBoxState.CHECKED_DISABLED: QColor(255, 255, 255, 41)
147
+ }
148
+ else:
149
+ map = {
150
+ CheckBoxState.NORMAL: QColor(0, 0, 0, 6),
151
+ CheckBoxState.HOVER: QColor(0, 0, 0, 13),
152
+ CheckBoxState.PRESSED: QColor(0, 0, 0, 31),
153
+ CheckBoxState.CHECKED: fallbackThemeColor(self.lightCheckedColor),
154
+ CheckBoxState.CHECKED_HOVER: validColor(self.lightCheckedColor, ThemeColor.LIGHT_1.color()),
155
+ CheckBoxState.CHECKED_PRESSED: validColor(self.lightCheckedColor, ThemeColor.LIGHT_2.color()),
156
+ CheckBoxState.DISABLED: QColor(0, 0, 0, 0),
157
+ CheckBoxState.CHECKED_DISABLED: QColor(0, 0, 0, 56)
158
+ }
159
+
160
+ return map[self._state()]
161
+
162
+ def _state(self):
163
+ if not self.isEnabled():
164
+ return CheckBoxState.CHECKED_DISABLED if self.isChecked() else CheckBoxState.DISABLED
165
+
166
+ if self.isChecked():
167
+ if self.isPressed:
168
+ return CheckBoxState.CHECKED_PRESSED
169
+ if self.isHover:
170
+ return CheckBoxState.CHECKED_HOVER
171
+
172
+ return CheckBoxState.CHECKED
173
+ else:
174
+ if self.isPressed:
175
+ return CheckBoxState.PRESSED
176
+ if self.isHover:
177
+ return CheckBoxState.HOVER
178
+
179
+ return CheckBoxState.NORMAL
180
+
181
+ def paintEvent(self, e):
182
+ super().paintEvent(e)
183
+ painter = QPainter(self)
184
+ painter.setRenderHints(QPainter.RenderHint.Antialiasing)
185
+
186
+ # get the rect of indicator
187
+ opt = QStyleOptionButton()
188
+ opt.initFrom(self)
189
+ rect = self.style().subElementRect(QStyle.SE_CheckBoxIndicator, opt, self)
190
+
191
+ # draw shape
192
+ painter.setPen(self._borderColor())
193
+ painter.setBrush(self._backgroundColor())
194
+ painter.drawRoundedRect(rect, 4.5, 4.5)
195
+
196
+ if not self.isEnabled():
197
+ painter.setOpacity(0.8)
198
+
199
+ # draw icon
200
+ if self.checkState() == Qt.Checked:
201
+ CheckBoxIcon.ACCEPT.render(painter, rect)
202
+ elif self.checkState() == Qt.PartiallyChecked:
203
+ CheckBoxIcon.PARTIAL_ACCEPT.render(painter, rect)