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,390 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
from typing import List, Union
|
3
|
+
from PySide6.QtCore import QEvent, Qt, QPropertyAnimation, Property, QEasingCurve, QRectF
|
4
|
+
from PySide6.QtGui import QColor, QPainter, QIcon, QPainterPath
|
5
|
+
from PySide6.QtWidgets import QFrame, QWidget, QAbstractButton, QApplication, QScrollArea, QVBoxLayout
|
6
|
+
|
7
|
+
from ...common.config import isDarkTheme
|
8
|
+
from ...common.icon import FluentIcon as FIF
|
9
|
+
from ...common.style_sheet import FluentStyleSheet
|
10
|
+
from .setting_card import SettingCard
|
11
|
+
from ..layout.v_box_layout import VBoxLayout
|
12
|
+
|
13
|
+
|
14
|
+
class ExpandButton(QAbstractButton):
|
15
|
+
""" Expand button """
|
16
|
+
|
17
|
+
def __init__(self, parent=None):
|
18
|
+
super().__init__(parent)
|
19
|
+
self.setFixedSize(30, 30)
|
20
|
+
self.__angle = 0
|
21
|
+
self.isHover = False
|
22
|
+
self.isPressed = False
|
23
|
+
self.rotateAni = QPropertyAnimation(self, b'angle', self)
|
24
|
+
self.clicked.connect(self.__onClicked)
|
25
|
+
|
26
|
+
def paintEvent(self, e):
|
27
|
+
painter = QPainter(self)
|
28
|
+
painter.setRenderHints(QPainter.Antialiasing |
|
29
|
+
QPainter.SmoothPixmapTransform)
|
30
|
+
painter.setPen(Qt.NoPen)
|
31
|
+
|
32
|
+
# draw background
|
33
|
+
r = 255 if isDarkTheme() else 0
|
34
|
+
color = Qt.transparent
|
35
|
+
|
36
|
+
if self.isEnabled():
|
37
|
+
if self.isPressed:
|
38
|
+
color = QColor(r, r, r, 10)
|
39
|
+
elif self.isHover:
|
40
|
+
color = QColor(r, r, r, 14)
|
41
|
+
else:
|
42
|
+
painter.setOpacity(0.36)
|
43
|
+
|
44
|
+
painter.setBrush(color)
|
45
|
+
painter.drawRoundedRect(self.rect(), 4, 4)
|
46
|
+
|
47
|
+
# draw icon
|
48
|
+
painter.translate(self.width()//2, self.height()//2)
|
49
|
+
painter.rotate(self.__angle)
|
50
|
+
FIF.ARROW_DOWN.render(painter, QRectF(-5, -5, 9.6, 9.6))
|
51
|
+
|
52
|
+
def enterEvent(self, e):
|
53
|
+
self.setHover(True)
|
54
|
+
|
55
|
+
def leaveEvent(self, e):
|
56
|
+
self.setHover(False)
|
57
|
+
|
58
|
+
def mousePressEvent(self, e):
|
59
|
+
super().mousePressEvent(e)
|
60
|
+
self.setPressed(True)
|
61
|
+
|
62
|
+
def mouseReleaseEvent(self, e):
|
63
|
+
super().mouseReleaseEvent(e)
|
64
|
+
self.setPressed(False)
|
65
|
+
|
66
|
+
def setHover(self, isHover: bool):
|
67
|
+
self.isHover = isHover
|
68
|
+
self.update()
|
69
|
+
|
70
|
+
def setPressed(self, isPressed: bool):
|
71
|
+
self.isPressed = isPressed
|
72
|
+
self.update()
|
73
|
+
|
74
|
+
def __onClicked(self):
|
75
|
+
self.setExpand(self.angle < 180)
|
76
|
+
|
77
|
+
def setExpand(self, isExpand: bool):
|
78
|
+
self.rotateAni.stop()
|
79
|
+
self.rotateAni.setEndValue(180 if isExpand else 0)
|
80
|
+
self.rotateAni.setDuration(200)
|
81
|
+
self.rotateAni.start()
|
82
|
+
|
83
|
+
def getAngle(self):
|
84
|
+
return self.__angle
|
85
|
+
|
86
|
+
def setAngle(self, angle):
|
87
|
+
self.__angle = angle
|
88
|
+
self.update()
|
89
|
+
|
90
|
+
angle = Property(float, getAngle, setAngle)
|
91
|
+
|
92
|
+
|
93
|
+
class SpaceWidget(QWidget):
|
94
|
+
""" Spacing widget """
|
95
|
+
|
96
|
+
def __init__(self, parent=None):
|
97
|
+
super().__init__(parent=parent)
|
98
|
+
self.setAttribute(Qt.WA_TranslucentBackground)
|
99
|
+
self.setFixedHeight(1)
|
100
|
+
|
101
|
+
|
102
|
+
class HeaderSettingCard(SettingCard):
|
103
|
+
""" Header setting card """
|
104
|
+
|
105
|
+
def __init__(self, icon, title, content=None, parent=None):
|
106
|
+
super().__init__(icon, title, content, parent)
|
107
|
+
self.expandButton = ExpandButton(self)
|
108
|
+
|
109
|
+
self.hBoxLayout.addWidget(self.expandButton, 0, Qt.AlignRight)
|
110
|
+
self.hBoxLayout.addSpacing(8)
|
111
|
+
|
112
|
+
self.titleLabel.setObjectName("titleLabel")
|
113
|
+
self.installEventFilter(self)
|
114
|
+
|
115
|
+
def eventFilter(self, obj, e):
|
116
|
+
if obj is self:
|
117
|
+
if e.type() == QEvent.Enter:
|
118
|
+
self.expandButton.setHover(True)
|
119
|
+
elif e.type() == QEvent.Leave:
|
120
|
+
self.expandButton.setHover(False)
|
121
|
+
elif e.type() == QEvent.MouseButtonPress and e.button() == Qt.LeftButton:
|
122
|
+
self.expandButton.setPressed(True)
|
123
|
+
elif e.type() == QEvent.MouseButtonRelease and e.button() == Qt.LeftButton:
|
124
|
+
self.expandButton.setPressed(False)
|
125
|
+
self.expandButton.click()
|
126
|
+
|
127
|
+
return super().eventFilter(obj, e)
|
128
|
+
|
129
|
+
def addWidget(self, widget: QWidget):
|
130
|
+
""" add widget to tail """
|
131
|
+
N = self.hBoxLayout.count()
|
132
|
+
self.hBoxLayout.removeItem(self.hBoxLayout.itemAt(N - 1))
|
133
|
+
self.hBoxLayout.addWidget(widget, 0, Qt.AlignRight)
|
134
|
+
self.hBoxLayout.addSpacing(19)
|
135
|
+
self.hBoxLayout.addWidget(self.expandButton, 0, Qt.AlignRight)
|
136
|
+
self.hBoxLayout.addSpacing(8)
|
137
|
+
|
138
|
+
def paintEvent(self, e):
|
139
|
+
painter = QPainter(self)
|
140
|
+
painter.setRenderHints(QPainter.Antialiasing)
|
141
|
+
painter.setPen(Qt.NoPen)
|
142
|
+
|
143
|
+
if isDarkTheme():
|
144
|
+
painter.setBrush(QColor(255, 255, 255, 13))
|
145
|
+
else:
|
146
|
+
painter.setBrush(QColor(255, 255, 255, 170))
|
147
|
+
|
148
|
+
p = self.parent() # type: ExpandSettingCard
|
149
|
+
path = QPainterPath()
|
150
|
+
path.setFillRule(Qt.WindingFill)
|
151
|
+
path.addRoundedRect(QRectF(self.rect().adjusted(1, 1, -1, -1)), 6, 6)
|
152
|
+
|
153
|
+
# set the bottom border radius to 0 if parent is expanded
|
154
|
+
if p.isExpand:
|
155
|
+
path.addRect(1, self.height() - 8, self.width() - 2, 8)
|
156
|
+
|
157
|
+
painter.drawPath(path.simplified())
|
158
|
+
|
159
|
+
|
160
|
+
class ExpandBorderWidget(QWidget):
|
161
|
+
""" Expand setting card border widget """
|
162
|
+
|
163
|
+
def __init__(self, parent=None):
|
164
|
+
super().__init__(parent=parent)
|
165
|
+
self.setAttribute(Qt.WA_TransparentForMouseEvents)
|
166
|
+
parent.installEventFilter(self)
|
167
|
+
|
168
|
+
def eventFilter(self, obj, e):
|
169
|
+
if obj is self.parent() and e.type() == QEvent.Resize:
|
170
|
+
self.resize(e.size())
|
171
|
+
|
172
|
+
return super().eventFilter(obj, e)
|
173
|
+
|
174
|
+
def paintEvent(self, e):
|
175
|
+
painter = QPainter(self)
|
176
|
+
painter.setRenderHints(QPainter.Antialiasing)
|
177
|
+
painter.setBrush(Qt.NoBrush)
|
178
|
+
|
179
|
+
if isDarkTheme():
|
180
|
+
painter.setPen(QColor(0, 0, 0, 50))
|
181
|
+
else:
|
182
|
+
painter.setPen(QColor(0, 0, 0, 19))
|
183
|
+
|
184
|
+
p = self.parent() # type: ExpandSettingCard
|
185
|
+
r, d = 6, 12
|
186
|
+
ch, h, w = p.card.height(), self.height(), self.width()
|
187
|
+
|
188
|
+
# only draw rounded rect if parent is not expanded
|
189
|
+
painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), r, r)
|
190
|
+
|
191
|
+
# draw the seperator line under card widget
|
192
|
+
if ch < h:
|
193
|
+
painter.drawLine(1, ch, w - 1, ch)
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
class ExpandSettingCard(QScrollArea):
|
199
|
+
""" Expandable setting card """
|
200
|
+
|
201
|
+
def __init__(self, icon: Union[str, QIcon, FIF], title: str, content: str = None, parent=None):
|
202
|
+
super().__init__(parent=parent)
|
203
|
+
self.isExpand = False
|
204
|
+
|
205
|
+
self.scrollWidget = QFrame(self)
|
206
|
+
self.view = QFrame(self.scrollWidget)
|
207
|
+
self.card = HeaderSettingCard(icon, title, content, self)
|
208
|
+
|
209
|
+
self.scrollLayout = QVBoxLayout(self.scrollWidget)
|
210
|
+
self.viewLayout = QVBoxLayout(self.view)
|
211
|
+
self.spaceWidget = SpaceWidget(self.scrollWidget)
|
212
|
+
self.borderWidget = ExpandBorderWidget(self)
|
213
|
+
|
214
|
+
# expand animation
|
215
|
+
self.expandAni = QPropertyAnimation(self.verticalScrollBar(), b'value', self)
|
216
|
+
|
217
|
+
self.__initWidget()
|
218
|
+
|
219
|
+
def __initWidget(self):
|
220
|
+
""" initialize widgets """
|
221
|
+
self.setWidget(self.scrollWidget)
|
222
|
+
self.setWidgetResizable(True)
|
223
|
+
self.setFixedHeight(self.card.height())
|
224
|
+
self.setViewportMargins(0, self.card.height(), 0, 0)
|
225
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
226
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
227
|
+
|
228
|
+
# initialize layout
|
229
|
+
self.scrollLayout.setContentsMargins(0, 0, 0, 0)
|
230
|
+
self.scrollLayout.setSpacing(0)
|
231
|
+
self.scrollLayout.addWidget(self.view)
|
232
|
+
self.scrollLayout.addWidget(self.spaceWidget)
|
233
|
+
|
234
|
+
# initialize expand animation
|
235
|
+
self.expandAni.setEasingCurve(QEasingCurve.OutQuad)
|
236
|
+
self.expandAni.setDuration(200)
|
237
|
+
|
238
|
+
# initialize style sheet
|
239
|
+
self.view.setObjectName('view')
|
240
|
+
self.scrollWidget.setObjectName('scrollWidget')
|
241
|
+
self.setProperty('isExpand', False)
|
242
|
+
FluentStyleSheet.EXPAND_SETTING_CARD.apply(self.card)
|
243
|
+
FluentStyleSheet.EXPAND_SETTING_CARD.apply(self)
|
244
|
+
|
245
|
+
self.card.installEventFilter(self)
|
246
|
+
self.expandAni.valueChanged.connect(self._onExpandValueChanged)
|
247
|
+
self.card.expandButton.clicked.connect(self.toggleExpand)
|
248
|
+
|
249
|
+
def addWidget(self, widget: QWidget):
|
250
|
+
""" add widget to tail """
|
251
|
+
self.card.addWidget(widget)
|
252
|
+
|
253
|
+
def wheelEvent(self, e):
|
254
|
+
e.ignore()
|
255
|
+
|
256
|
+
def setExpand(self, isExpand: bool):
|
257
|
+
""" set the expand status of card """
|
258
|
+
if self.isExpand == isExpand:
|
259
|
+
return
|
260
|
+
|
261
|
+
# update style sheet
|
262
|
+
self.isExpand = isExpand
|
263
|
+
self.setProperty('isExpand', isExpand)
|
264
|
+
self.setStyle(QApplication.style())
|
265
|
+
|
266
|
+
# start expand animation
|
267
|
+
if isExpand:
|
268
|
+
h = self.viewLayout.sizeHint().height()
|
269
|
+
self.verticalScrollBar().setValue(h)
|
270
|
+
self.expandAni.setStartValue(h)
|
271
|
+
self.expandAni.setEndValue(0)
|
272
|
+
else:
|
273
|
+
self.expandAni.setStartValue(0)
|
274
|
+
self.expandAni.setEndValue(self.verticalScrollBar().maximum())
|
275
|
+
|
276
|
+
self.expandAni.start()
|
277
|
+
self.card.expandButton.setExpand(isExpand)
|
278
|
+
|
279
|
+
def toggleExpand(self):
|
280
|
+
""" toggle expand status """
|
281
|
+
self.setExpand(not self.isExpand)
|
282
|
+
|
283
|
+
def resizeEvent(self, e):
|
284
|
+
self.card.resize(self.width(), self.card.height())
|
285
|
+
self.scrollWidget.resize(self.width(), self.scrollWidget.height())
|
286
|
+
|
287
|
+
def _onExpandValueChanged(self):
|
288
|
+
vh = self.viewLayout.sizeHint().height()
|
289
|
+
h = self.viewportMargins().top()
|
290
|
+
self.setFixedHeight(max(h + vh - self.verticalScrollBar().value(), h))
|
291
|
+
|
292
|
+
def _adjustViewSize(self):
|
293
|
+
""" adjust view size """
|
294
|
+
h = self.viewLayout.sizeHint().height()
|
295
|
+
self.spaceWidget.setFixedHeight(h)
|
296
|
+
|
297
|
+
if self.isExpand:
|
298
|
+
self.setFixedHeight(self.card.height()+h)
|
299
|
+
|
300
|
+
def setValue(self, value):
|
301
|
+
""" set the value of config item """
|
302
|
+
pass
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
class GroupSeparator(QWidget):
|
307
|
+
""" group separator """
|
308
|
+
|
309
|
+
def __init__(self, parent=None):
|
310
|
+
super().__init__(parent=parent)
|
311
|
+
self.setFixedHeight(3)
|
312
|
+
|
313
|
+
def paintEvent(self, e):
|
314
|
+
painter = QPainter(self)
|
315
|
+
painter.setRenderHints(QPainter.Antialiasing)
|
316
|
+
|
317
|
+
if isDarkTheme():
|
318
|
+
painter.setPen(QColor(0, 0, 0, 50))
|
319
|
+
else:
|
320
|
+
painter.setPen(QColor(0, 0, 0, 19))
|
321
|
+
|
322
|
+
painter.drawLine(0, 1, self.width(), 1)
|
323
|
+
|
324
|
+
|
325
|
+
class ExpandGroupSettingCard(ExpandSettingCard):
|
326
|
+
""" Expand group setting card """
|
327
|
+
|
328
|
+
def __init__(self, icon: Union[str, QIcon, FIF], title: str, content: str = None, parent=None):
|
329
|
+
super().__init__(icon, title, content, parent)
|
330
|
+
self.widgets = [] # type: List[QWidget]
|
331
|
+
|
332
|
+
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
333
|
+
self.viewLayout.setSpacing(0)
|
334
|
+
|
335
|
+
def addGroupWidget(self, widget: QWidget):
|
336
|
+
""" add widget to group """
|
337
|
+
# add separator
|
338
|
+
if self.viewLayout.count() >= 1:
|
339
|
+
self.viewLayout.addWidget(GroupSeparator(self.view))
|
340
|
+
|
341
|
+
widget.setParent(self.view)
|
342
|
+
self.widgets.append(widget)
|
343
|
+
self.viewLayout.addWidget(widget)
|
344
|
+
self._adjustViewSize()
|
345
|
+
|
346
|
+
def removeGroupWidget(self, widget: QWidget):
|
347
|
+
""" remove a group from card """
|
348
|
+
if widget not in self.widgets:
|
349
|
+
return
|
350
|
+
|
351
|
+
layoutIndex = self.viewLayout.indexOf(widget)
|
352
|
+
index = self.widgets.index(widget)
|
353
|
+
|
354
|
+
self.viewLayout.removeWidget(widget)
|
355
|
+
self.widgets.remove(widget)
|
356
|
+
|
357
|
+
if not self.widgets:
|
358
|
+
return self._adjustViewSize()
|
359
|
+
|
360
|
+
# remove separator
|
361
|
+
if layoutIndex >= 1:
|
362
|
+
separator = self.viewLayout.itemAt(layoutIndex - 1).widget()
|
363
|
+
separator.deleteLater()
|
364
|
+
self.viewLayout.removeWidget(separator)
|
365
|
+
elif index == 0:
|
366
|
+
separator = self.viewLayout.itemAt(0).widget()
|
367
|
+
separator.deleteLater()
|
368
|
+
self.viewLayout.removeWidget(separator)
|
369
|
+
|
370
|
+
self._adjustViewSize()
|
371
|
+
|
372
|
+
def _adjustViewSize(self):
|
373
|
+
""" adjust view size """
|
374
|
+
h = sum(w.sizeHint().height() + 3 for w in self.widgets)
|
375
|
+
self.spaceWidget.setFixedHeight(h)
|
376
|
+
|
377
|
+
if self.isExpand:
|
378
|
+
self.setFixedHeight(self.card.height()+h)
|
379
|
+
|
380
|
+
|
381
|
+
class SimpleExpandGroupSettingCard(ExpandGroupSettingCard):
|
382
|
+
""" Simple expand group setting card """
|
383
|
+
|
384
|
+
def _adjustViewSize(self):
|
385
|
+
""" adjust view size """
|
386
|
+
h = self.viewLayout.sizeHint().height()
|
387
|
+
self.spaceWidget.setFixedHeight(h)
|
388
|
+
|
389
|
+
if self.isExpand:
|
390
|
+
self.setFixedHeight(self.card.height()+h)
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
from typing import List
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from PySide6.QtCore import Qt, Signal, QSize
|
6
|
+
from PySide6.QtGui import QPainter, QIcon
|
7
|
+
from PySide6.QtWidgets import (QPushButton, QFileDialog, QWidget, QLabel,
|
8
|
+
QHBoxLayout, QToolButton, QSizePolicy)
|
9
|
+
|
10
|
+
from ...components.widgets.button import ToolButton, PushButton
|
11
|
+
from ...common.config import ConfigItem, qconfig
|
12
|
+
from ...common.icon import drawIcon
|
13
|
+
from ...common.icon import FluentIcon as FIF
|
14
|
+
from ..dialog_box.dialog import Dialog
|
15
|
+
from .expand_setting_card import ExpandSettingCard
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class FolderItem(QWidget):
|
20
|
+
""" Folder item """
|
21
|
+
|
22
|
+
removed = Signal(QWidget)
|
23
|
+
|
24
|
+
def __init__(self, folder: str, parent=None):
|
25
|
+
super().__init__(parent=parent)
|
26
|
+
self.folder = folder
|
27
|
+
self.hBoxLayout = QHBoxLayout(self)
|
28
|
+
self.folderLabel = QLabel(folder, self)
|
29
|
+
self.removeButton = ToolButton(FIF.CLOSE, self)
|
30
|
+
|
31
|
+
self.removeButton.setFixedSize(39, 29)
|
32
|
+
self.removeButton.setIconSize(QSize(12, 12))
|
33
|
+
|
34
|
+
self.setFixedHeight(53)
|
35
|
+
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
|
36
|
+
self.hBoxLayout.setContentsMargins(48, 0, 60, 0)
|
37
|
+
self.hBoxLayout.addWidget(self.folderLabel, 0, Qt.AlignLeft)
|
38
|
+
self.hBoxLayout.addSpacing(16)
|
39
|
+
self.hBoxLayout.addStretch(1)
|
40
|
+
self.hBoxLayout.addWidget(self.removeButton, 0, Qt.AlignRight)
|
41
|
+
self.hBoxLayout.setAlignment(Qt.AlignVCenter)
|
42
|
+
|
43
|
+
self.removeButton.clicked.connect(
|
44
|
+
lambda: self.removed.emit(self))
|
45
|
+
|
46
|
+
|
47
|
+
class FolderListSettingCard(ExpandSettingCard):
|
48
|
+
""" Folder list setting card """
|
49
|
+
|
50
|
+
folderChanged = Signal(list)
|
51
|
+
|
52
|
+
def __init__(self, configItem: ConfigItem, title: str, content: str = None, directory="./", parent=None):
|
53
|
+
"""
|
54
|
+
Parameters
|
55
|
+
----------
|
56
|
+
configItem: RangeConfigItem
|
57
|
+
configuration item operated by the card
|
58
|
+
|
59
|
+
title: str
|
60
|
+
the title of card
|
61
|
+
|
62
|
+
content: str
|
63
|
+
the content of card
|
64
|
+
|
65
|
+
directory: str
|
66
|
+
working directory of file dialog
|
67
|
+
|
68
|
+
parent: QWidget
|
69
|
+
parent widget
|
70
|
+
"""
|
71
|
+
super().__init__(FIF.FOLDER, title, content, parent)
|
72
|
+
self.configItem = configItem
|
73
|
+
self._dialogDirectory = directory
|
74
|
+
self.addFolderButton = PushButton(self.tr('Add folder'), self, FIF.FOLDER_ADD)
|
75
|
+
|
76
|
+
self.folders = qconfig.get(configItem).copy() # type:List[str]
|
77
|
+
self.__initWidget()
|
78
|
+
|
79
|
+
def __initWidget(self):
|
80
|
+
self.addWidget(self.addFolderButton)
|
81
|
+
|
82
|
+
# initialize layout
|
83
|
+
self.viewLayout.setSpacing(0)
|
84
|
+
self.viewLayout.setAlignment(Qt.AlignTop)
|
85
|
+
self.viewLayout.setContentsMargins(0, 0, 0, 0)
|
86
|
+
for folder in self.folders:
|
87
|
+
self.__addFolderItem(folder)
|
88
|
+
|
89
|
+
self.addFolderButton.clicked.connect(self.__showFolderDialog)
|
90
|
+
|
91
|
+
def __showFolderDialog(self):
|
92
|
+
""" show folder dialog """
|
93
|
+
folder = QFileDialog.getExistingDirectory(
|
94
|
+
self, self.tr("Choose folder"), self._dialogDirectory)
|
95
|
+
|
96
|
+
if not folder or folder in self.folders:
|
97
|
+
return
|
98
|
+
|
99
|
+
self.__addFolderItem(folder)
|
100
|
+
self.folders.append(folder)
|
101
|
+
qconfig.set(self.configItem, self.folders)
|
102
|
+
self.folderChanged.emit(self.folders)
|
103
|
+
|
104
|
+
def __addFolderItem(self, folder: str):
|
105
|
+
""" add folder item """
|
106
|
+
item = FolderItem(folder, self.view)
|
107
|
+
item.removed.connect(self.__showConfirmDialog)
|
108
|
+
self.viewLayout.addWidget(item)
|
109
|
+
item.show()
|
110
|
+
self._adjustViewSize()
|
111
|
+
|
112
|
+
def __showConfirmDialog(self, item: FolderItem):
|
113
|
+
""" show confirm dialog """
|
114
|
+
name = Path(item.folder).name
|
115
|
+
title = self.tr('Are you sure you want to delete the folder?')
|
116
|
+
content = self.tr("If you delete the ") + f'"{name}"' + \
|
117
|
+
self.tr(" folder and remove it from the list, the folder will no "
|
118
|
+
"longer appear in the list, but will not be deleted.")
|
119
|
+
w = Dialog(title, content, self.window())
|
120
|
+
w.yesSignal.connect(lambda: self.__removeFolder(item))
|
121
|
+
w.exec_()
|
122
|
+
|
123
|
+
def __removeFolder(self, item: FolderItem):
|
124
|
+
""" remove folder """
|
125
|
+
if item.folder not in self.folders:
|
126
|
+
return
|
127
|
+
|
128
|
+
self.folders.remove(item.folder)
|
129
|
+
self.viewLayout.removeWidget(item)
|
130
|
+
item.deleteLater()
|
131
|
+
self._adjustViewSize()
|
132
|
+
|
133
|
+
self.folderChanged.emit(self.folders)
|
134
|
+
qconfig.set(self.configItem, self.folders)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
from typing import Union
|
3
|
+
from PySide6.QtCore import Signal
|
4
|
+
from PySide6.QtGui import QIcon
|
5
|
+
from PySide6.QtWidgets import QButtonGroup, QLabel
|
6
|
+
|
7
|
+
from ...common.config import OptionsConfigItem, qconfig
|
8
|
+
from ...common.icon import FluentIconBase
|
9
|
+
from ..widgets.button import RadioButton
|
10
|
+
from .expand_setting_card import ExpandSettingCard
|
11
|
+
|
12
|
+
|
13
|
+
class OptionsSettingCard(ExpandSettingCard):
|
14
|
+
""" setting card with a group of options """
|
15
|
+
|
16
|
+
optionChanged = Signal(OptionsConfigItem)
|
17
|
+
|
18
|
+
def __init__(self, configItem, icon: Union[str, QIcon, FluentIconBase], title, content=None, texts=None, parent=None):
|
19
|
+
"""
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
configItem: OptionsConfigItem
|
23
|
+
options config item
|
24
|
+
|
25
|
+
icon: str | QIcon | FluentIconBase
|
26
|
+
the icon to be drawn
|
27
|
+
|
28
|
+
title: str
|
29
|
+
the title of setting card
|
30
|
+
|
31
|
+
content: str
|
32
|
+
the content of setting card
|
33
|
+
|
34
|
+
texts: List[str]
|
35
|
+
the texts of radio buttons
|
36
|
+
|
37
|
+
parent: QWidget
|
38
|
+
parent window
|
39
|
+
"""
|
40
|
+
super().__init__(icon, title, content, parent)
|
41
|
+
self.texts = texts or []
|
42
|
+
self.configItem = configItem
|
43
|
+
self.configName = configItem.name
|
44
|
+
self.choiceLabel = QLabel(self)
|
45
|
+
self.buttonGroup = QButtonGroup(self)
|
46
|
+
|
47
|
+
self.choiceLabel.setObjectName("titleLabel")
|
48
|
+
self.addWidget(self.choiceLabel)
|
49
|
+
|
50
|
+
# create buttons
|
51
|
+
self.viewLayout.setSpacing(19)
|
52
|
+
self.viewLayout.setContentsMargins(48, 18, 0, 18)
|
53
|
+
for text, option in zip(texts, configItem.options):
|
54
|
+
button = RadioButton(text, self.view)
|
55
|
+
self.buttonGroup.addButton(button)
|
56
|
+
self.viewLayout.addWidget(button)
|
57
|
+
button.setProperty(self.configName, option)
|
58
|
+
|
59
|
+
self._adjustViewSize()
|
60
|
+
self.setValue(qconfig.get(self.configItem))
|
61
|
+
configItem.valueChanged.connect(self.setValue)
|
62
|
+
self.buttonGroup.buttonClicked.connect(self.__onButtonClicked)
|
63
|
+
|
64
|
+
def __onButtonClicked(self, button: RadioButton):
|
65
|
+
""" button clicked slot """
|
66
|
+
if button.text() == self.choiceLabel.text():
|
67
|
+
return
|
68
|
+
|
69
|
+
value = button.property(self.configName)
|
70
|
+
qconfig.set(self.configItem, value)
|
71
|
+
|
72
|
+
self.choiceLabel.setText(button.text())
|
73
|
+
self.choiceLabel.adjustSize()
|
74
|
+
self.optionChanged.emit(self.configItem)
|
75
|
+
|
76
|
+
def setValue(self, value):
|
77
|
+
""" select button according to the value """
|
78
|
+
qconfig.set(self.configItem, value)
|
79
|
+
|
80
|
+
for button in self.buttonGroup.buttons():
|
81
|
+
isChecked = button.property(self.configName) == value
|
82
|
+
button.setChecked(isChecked)
|
83
|
+
|
84
|
+
if isChecked:
|
85
|
+
self.choiceLabel.setText(button.text())
|
86
|
+
self.choiceLabel.adjustSize()
|