PySide6Plot 0.0.1__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.
- PySide6Plot/__init__.py +187 -0
- PySide6Plot/compoents/__init__.py +3 -0
- PySide6Plot/compoents/average_line.py +232 -0
- PySide6Plot/compoents/draw_line.py +624 -0
- PySide6Plot/compoents/frame_recorder.py +213 -0
- PySide6Plot/compoents/zoom_move.py +160 -0
- PySide6Plot/libs/__init__.py +3 -0
- PySide6Plot/libs/constant.py +19 -0
- PySide6Plot/libs/data_handler.py +230 -0
- PySide6Plot/libs/helpers.py +401 -0
- PySide6Plot/libs/plot_item.py +233 -0
- PySide6Plot/libs/style.py +119 -0
- PySide6Plot/resources/icons/ChevronLeft_black.svg +44 -0
- PySide6Plot/resources/icons/ChevronLeft_white.svg +44 -0
- PySide6Plot/resources/qss/dark/navigation_view_interface.qss +16 -0
- PySide6Plot/resources/qss/light/navigation_view_interface.qss +16 -0
- PySide6Plot/widgets/__init__.py +3 -0
- PySide6Plot/widgets/colorful_toggle_button.py +131 -0
- PySide6Plot/widgets/fluent_scroller.py +450 -0
- PySide6Plot/widgets/line_card.py +138 -0
- PySide6Plot/widgets/navigation_widget.py +49 -0
- PySide6Plot/widgets/q_plot_widget.py +750 -0
- PySide6Plot/widgets/removable_table.py +259 -0
- PySide6Plot/widgets/transparent_Line_edit.py +69 -0
- PySide6Plot/widgets/transparent_selector.py +208 -0
- PySide6Plot/widgets/value_select_box.py +369 -0
- PySide6Plot/widgets/zoom_bar.py +136 -0
- pyside6plot-0.0.1.dist-info/METADATA +37 -0
- pyside6plot-0.0.1.dist-info/RECORD +31 -0
- pyside6plot-0.0.1.dist-info/WHEEL +5 -0
- pyside6plot-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
# Modify from PySide6-fluent-widgets
|
|
2
|
+
# PySide6-Fluent-Widgets 1.2.0
|
|
3
|
+
from PySide6.QtCore import QEvent, Qt, Signal, QPropertyAnimation, Property, QRectF, QTimer, QPoint
|
|
4
|
+
from PySide6.QtWidgets import QWidget, QToolButton, QGraphicsOpacityEffect, QHBoxLayout, QVBoxLayout, QApplication
|
|
5
|
+
from PySide6.QtGui import QPainter, QColor, QMouseEvent
|
|
6
|
+
from qfluentwidgets.common.icon import FluentIcon
|
|
7
|
+
from qfluentwidgets.common.style_sheet import isDarkTheme
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ArrowButton(QToolButton):
|
|
11
|
+
"""Arrow button"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, icon: FluentIcon, parent=None):
|
|
14
|
+
super().__init__(parent=parent)
|
|
15
|
+
self.setFixedSize(10, 10)
|
|
16
|
+
self._icon = icon
|
|
17
|
+
|
|
18
|
+
def paintEvent(self, e):
|
|
19
|
+
painter = QPainter(self)
|
|
20
|
+
painter.setRenderHints(QPainter.RenderHint.Antialiasing)
|
|
21
|
+
|
|
22
|
+
s = 7 if self.isDown() else 8
|
|
23
|
+
x = (self.width() - s) / 2
|
|
24
|
+
self._icon.render(painter, QRectF(x, x, s, s), fill="#858789")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ScrollBarGroove(QWidget):
|
|
28
|
+
"""Scroll bar groove"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, orient: Qt.Orientation, parent):
|
|
31
|
+
super().__init__(parent=parent)
|
|
32
|
+
if orient == Qt.Orientation.Vertical:
|
|
33
|
+
self.setFixedWidth(12)
|
|
34
|
+
self.upButton = ArrowButton(FluentIcon.CARE_UP_SOLID, self)
|
|
35
|
+
self.downButton = ArrowButton(FluentIcon.CARE_DOWN_SOLID, self)
|
|
36
|
+
self.setLayout(QVBoxLayout(self))
|
|
37
|
+
self.layout().addWidget(self.upButton, 0, Qt.AlignmentFlag.AlignHCenter)
|
|
38
|
+
self.layout().addStretch(1)
|
|
39
|
+
self.layout().addWidget(self.downButton, 0, Qt.AlignmentFlag.AlignHCenter)
|
|
40
|
+
self.layout().setContentsMargins(0, 3, 0, 3)
|
|
41
|
+
else:
|
|
42
|
+
self.setFixedHeight(12)
|
|
43
|
+
self.upButton = ArrowButton(FluentIcon.CARE_LEFT_SOLID, self)
|
|
44
|
+
self.downButton = ArrowButton(FluentIcon.CARE_RIGHT_SOLID, self)
|
|
45
|
+
self.setLayout(QHBoxLayout(self))
|
|
46
|
+
self.layout().addWidget(self.upButton, 0, Qt.AlignmentFlag.AlignVCenter)
|
|
47
|
+
self.layout().addStretch(1)
|
|
48
|
+
self.layout().addWidget(self.downButton, 0, Qt.AlignmentFlag.AlignVCenter)
|
|
49
|
+
self.layout().setContentsMargins(3, 0, 3, 0)
|
|
50
|
+
|
|
51
|
+
self.opacityEffect = QGraphicsOpacityEffect(self)
|
|
52
|
+
self.opacityAni = QPropertyAnimation(self.opacityEffect, b"opacity", self)
|
|
53
|
+
self.setGraphicsEffect(self.opacityEffect)
|
|
54
|
+
self.opacityEffect.setOpacity(0)
|
|
55
|
+
|
|
56
|
+
def fadeIn(self):
|
|
57
|
+
self.opacityAni.setEndValue(1)
|
|
58
|
+
self.opacityAni.setDuration(150)
|
|
59
|
+
self.opacityAni.start()
|
|
60
|
+
|
|
61
|
+
def fadeOut(self):
|
|
62
|
+
self.opacityAni.setEndValue(0)
|
|
63
|
+
self.opacityAni.setDuration(150)
|
|
64
|
+
self.opacityAni.start()
|
|
65
|
+
|
|
66
|
+
def paintEvent(self, e):
|
|
67
|
+
painter = QPainter(self)
|
|
68
|
+
painter.setRenderHints(QPainter.RenderHint.Antialiasing)
|
|
69
|
+
painter.setPen(Qt.PenStyle.NoPen)
|
|
70
|
+
|
|
71
|
+
if not isDarkTheme():
|
|
72
|
+
painter.setBrush(QColor(252, 252, 252, 217))
|
|
73
|
+
else:
|
|
74
|
+
painter.setBrush(QColor(44, 44, 44, 245))
|
|
75
|
+
|
|
76
|
+
painter.drawRoundedRect(self.rect(), 6, 6)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ScrollBarHandle(QWidget):
|
|
80
|
+
"""Scroll bar handle"""
|
|
81
|
+
|
|
82
|
+
def __init__(self, orient: Qt.Orientation, parent=None):
|
|
83
|
+
super().__init__(parent)
|
|
84
|
+
self.orient = orient
|
|
85
|
+
if orient == Qt.Orientation.Vertical:
|
|
86
|
+
self.setFixedWidth(3)
|
|
87
|
+
else:
|
|
88
|
+
self.setFixedHeight(3)
|
|
89
|
+
|
|
90
|
+
def paintEvent(self, e):
|
|
91
|
+
painter = QPainter(self)
|
|
92
|
+
painter.setRenderHints(QPainter.RenderHint.Antialiasing)
|
|
93
|
+
painter.setPen(Qt.PenStyle.NoPen)
|
|
94
|
+
|
|
95
|
+
r = self.width() / 2 if self.orient == Qt.Orientation.Vertical else self.height() / 2
|
|
96
|
+
c = QColor(255, 255, 255, 139) if isDarkTheme() else QColor(0, 0, 0, 114)
|
|
97
|
+
painter.setBrush(c)
|
|
98
|
+
painter.drawRoundedRect(self.rect(), r, r)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class FluentScrollBar(QWidget):
|
|
102
|
+
"""Fluent scroll bar"""
|
|
103
|
+
|
|
104
|
+
rangeChanged = Signal(tuple)
|
|
105
|
+
valueChanged = Signal(int)
|
|
106
|
+
sliderPressed = Signal()
|
|
107
|
+
sliderReleased = Signal()
|
|
108
|
+
sliderMoved = Signal()
|
|
109
|
+
|
|
110
|
+
# REPLACED<<
|
|
111
|
+
# def __init__(self, orient: Qt.Orientation, parent: QAbstractScrollArea):
|
|
112
|
+
def __init__(self, orient: Qt.Orientation, parent: QWidget):
|
|
113
|
+
# >>
|
|
114
|
+
super().__init__(parent)
|
|
115
|
+
self.groove = ScrollBarGroove(orient, self)
|
|
116
|
+
self.handle = ScrollBarHandle(orient, self)
|
|
117
|
+
self.timer = QTimer(self)
|
|
118
|
+
|
|
119
|
+
self._orientation = orient
|
|
120
|
+
self._singleStep = 1
|
|
121
|
+
self._pageStep = 50
|
|
122
|
+
self._padding = 14
|
|
123
|
+
|
|
124
|
+
self._minimum = 0
|
|
125
|
+
self._maximum = 0
|
|
126
|
+
self._value = 0
|
|
127
|
+
|
|
128
|
+
self._isPressed = False
|
|
129
|
+
self._isEnter = False
|
|
130
|
+
self._isExpanded = False
|
|
131
|
+
self._pressedPos = QPoint()
|
|
132
|
+
self._isForceHidden = False
|
|
133
|
+
|
|
134
|
+
# DELETED<<
|
|
135
|
+
"""
|
|
136
|
+
if orient == Qt.Orientation.Vertical:
|
|
137
|
+
self.partnerBar = parent.verticalScrollBar()
|
|
138
|
+
QAbstractScrollArea.setVerticalScrollBarPolicy(parent, Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
139
|
+
else:
|
|
140
|
+
self.partnerBar = parent.horizontalScrollBar()
|
|
141
|
+
QAbstractScrollArea.setHorizontalScrollBarPolicy(parent, Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
142
|
+
"""
|
|
143
|
+
# >>
|
|
144
|
+
self.__initWidget(parent)
|
|
145
|
+
|
|
146
|
+
def __initWidget(self, parent):
|
|
147
|
+
self.groove.upButton.clicked.connect(self._onPageUp)
|
|
148
|
+
self.groove.downButton.clicked.connect(self._onPageDown)
|
|
149
|
+
self.groove.opacityAni.valueChanged.connect(self._onOpacityAniValueChanged)
|
|
150
|
+
# DELETED<<
|
|
151
|
+
# self.partnerBar.rangeChanged.connect(self.setRange)
|
|
152
|
+
# self.partnerBar.valueChanged.connect(self._onValueChanged)
|
|
153
|
+
# self.valueChanged.connect(self.partnerBar.setValue)
|
|
154
|
+
# >>
|
|
155
|
+
if parent is not None:
|
|
156
|
+
parent.installEventFilter(self)
|
|
157
|
+
|
|
158
|
+
# DELETED<<
|
|
159
|
+
# self.setRange(self.partnerBar.minimum(), self.partnerBar.maximum())
|
|
160
|
+
# self.setVisible(self.maximum() > 0 and not self._isForceHidden)
|
|
161
|
+
# >>
|
|
162
|
+
# self._adjustPos(self.parent().size())
|
|
163
|
+
# ADDED<<
|
|
164
|
+
if self._orientation == Qt.Orientation.Vertical:
|
|
165
|
+
self.setFixedWidth(12)
|
|
166
|
+
self.setMinimumHeight(50)
|
|
167
|
+
else:
|
|
168
|
+
self.setFixedHeight(12)
|
|
169
|
+
self.setMinimumWidth(50)
|
|
170
|
+
|
|
171
|
+
# >>
|
|
172
|
+
|
|
173
|
+
def _onPageUp(self):
|
|
174
|
+
self.setValue(self.value() - self.pageStep())
|
|
175
|
+
|
|
176
|
+
def _onPageDown(self):
|
|
177
|
+
self.setValue(self.value() + self.pageStep())
|
|
178
|
+
|
|
179
|
+
def _onValueChanged(self, value):
|
|
180
|
+
self.val = value
|
|
181
|
+
|
|
182
|
+
def value(self):
|
|
183
|
+
return self._value
|
|
184
|
+
|
|
185
|
+
@Property(int, notify=valueChanged)
|
|
186
|
+
def val(self):
|
|
187
|
+
return self._value
|
|
188
|
+
|
|
189
|
+
@val.setter
|
|
190
|
+
def val(self, value: int):
|
|
191
|
+
if value == self.value():
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
value = max(self.minimum(), min(value, self.maximum()))
|
|
195
|
+
self._value = value
|
|
196
|
+
self.valueChanged.emit(value)
|
|
197
|
+
|
|
198
|
+
# adjust the position of handle
|
|
199
|
+
self._adjustHandlePos()
|
|
200
|
+
|
|
201
|
+
def minimum(self):
|
|
202
|
+
return self._minimum
|
|
203
|
+
|
|
204
|
+
def maximum(self):
|
|
205
|
+
return self._maximum
|
|
206
|
+
|
|
207
|
+
def orientation(self):
|
|
208
|
+
return self._orientation
|
|
209
|
+
|
|
210
|
+
def pageStep(self):
|
|
211
|
+
return self._pageStep
|
|
212
|
+
|
|
213
|
+
def singleStep(self):
|
|
214
|
+
return self._singleStep
|
|
215
|
+
|
|
216
|
+
def isSliderDown(self):
|
|
217
|
+
return self._isPressed
|
|
218
|
+
|
|
219
|
+
def setValue(self, value: int):
|
|
220
|
+
self.val = value
|
|
221
|
+
# ADDED<<
|
|
222
|
+
self._adjustHandleSize()
|
|
223
|
+
self._adjustHandlePos()
|
|
224
|
+
# >>
|
|
225
|
+
|
|
226
|
+
def setMinimum(self, min: int):
|
|
227
|
+
if min == self.minimum():
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
self._minimum = min
|
|
231
|
+
self.rangeChanged.emit((min, self.maximum()))
|
|
232
|
+
|
|
233
|
+
def setMaximum(self, max: int):
|
|
234
|
+
if max == self.maximum():
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
self._maximum = max
|
|
238
|
+
self.rangeChanged.emit((self.minimum(), max))
|
|
239
|
+
|
|
240
|
+
def setRange(self, min: int, max: int):
|
|
241
|
+
if min > max or (min == self.minimum() and max == self.maximum()):
|
|
242
|
+
return
|
|
243
|
+
|
|
244
|
+
self.setMinimum(min)
|
|
245
|
+
self.setMaximum(max)
|
|
246
|
+
|
|
247
|
+
self._adjustHandleSize()
|
|
248
|
+
self._adjustHandlePos()
|
|
249
|
+
# self.setVisible(max > 0 and not self._isForceHidden)
|
|
250
|
+
|
|
251
|
+
self.rangeChanged.emit((min, max))
|
|
252
|
+
|
|
253
|
+
def setPageStep(self, step: int):
|
|
254
|
+
if step >= 1:
|
|
255
|
+
self._pageStep = step
|
|
256
|
+
|
|
257
|
+
def setSingleStep(self, step: int):
|
|
258
|
+
if step >= 1:
|
|
259
|
+
self._singleStep = step
|
|
260
|
+
|
|
261
|
+
def setSliderDown(self, isDown: bool):
|
|
262
|
+
self._isPressed = True
|
|
263
|
+
if isDown:
|
|
264
|
+
self.sliderPressed.emit()
|
|
265
|
+
else:
|
|
266
|
+
self.sliderReleased.emit()
|
|
267
|
+
|
|
268
|
+
def expand(self):
|
|
269
|
+
"""expand scroll bar"""
|
|
270
|
+
if self._isExpanded or not self.isEnter:
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
self._isExpanded = True
|
|
274
|
+
self.groove.fadeIn()
|
|
275
|
+
|
|
276
|
+
def collapse(self):
|
|
277
|
+
"""collapse scroll bar"""
|
|
278
|
+
if not self._isExpanded or self.isEnter:
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
self._isExpanded = False
|
|
282
|
+
self.groove.fadeOut()
|
|
283
|
+
|
|
284
|
+
def enterEvent(self, e):
|
|
285
|
+
if self.isEnabled():
|
|
286
|
+
self.isEnter = True
|
|
287
|
+
self.timer.stop()
|
|
288
|
+
self.timer.singleShot(200, self.expand)
|
|
289
|
+
|
|
290
|
+
def leaveEvent(self, e):
|
|
291
|
+
if self.isEnabled():
|
|
292
|
+
self.isEnter = False
|
|
293
|
+
self.timer.stop()
|
|
294
|
+
self.timer.singleShot(200, self.collapse)
|
|
295
|
+
|
|
296
|
+
# ADDED<<
|
|
297
|
+
def showEvent(self, e):
|
|
298
|
+
self._adjustHandleSize()
|
|
299
|
+
self._adjustHandlePos()
|
|
300
|
+
|
|
301
|
+
# >>
|
|
302
|
+
def eventFilter(self, obj, e: QEvent):
|
|
303
|
+
if obj is not self.parent():
|
|
304
|
+
return super().eventFilter(obj, e)
|
|
305
|
+
|
|
306
|
+
# adjust the position of slider
|
|
307
|
+
if e.type() == QEvent.Type.Resize:
|
|
308
|
+
self._adjustPos(e.size())
|
|
309
|
+
|
|
310
|
+
return super().eventFilter(obj, e)
|
|
311
|
+
|
|
312
|
+
def resizeEvent(self, e):
|
|
313
|
+
self.groove.resize(self.size())
|
|
314
|
+
# ADDED<<
|
|
315
|
+
self._adjustHandleSize()
|
|
316
|
+
self._adjustHandlePos()
|
|
317
|
+
# >>
|
|
318
|
+
|
|
319
|
+
def mousePressEvent(self, e: QMouseEvent):
|
|
320
|
+
super().mousePressEvent(e)
|
|
321
|
+
self._isPressed = True
|
|
322
|
+
self._pressedPos = e.pos()
|
|
323
|
+
|
|
324
|
+
if self.childAt(e.pos()) is self.handle or not self._isSlideResion(e.pos()):
|
|
325
|
+
return
|
|
326
|
+
|
|
327
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
328
|
+
if e.pos().y() > self.handle.geometry().bottom():
|
|
329
|
+
value = e.pos().y() - self.handle.height() - self._padding
|
|
330
|
+
else:
|
|
331
|
+
value = e.pos().y() - self._padding
|
|
332
|
+
else:
|
|
333
|
+
if e.pos().x() > self.handle.geometry().right():
|
|
334
|
+
value = e.pos().x() - self.handle.width() - self._padding
|
|
335
|
+
else:
|
|
336
|
+
value = e.pos().x() - self._padding
|
|
337
|
+
|
|
338
|
+
self.setValue(int(value / max(self._slideLength(), 1) * self.maximum()))
|
|
339
|
+
self.sliderPressed.emit()
|
|
340
|
+
|
|
341
|
+
def mouseReleaseEvent(self, e):
|
|
342
|
+
super().mouseReleaseEvent(e)
|
|
343
|
+
self._isPressed = False
|
|
344
|
+
self.sliderReleased.emit()
|
|
345
|
+
|
|
346
|
+
def mouseMoveEvent(self, e: QMouseEvent):
|
|
347
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
348
|
+
dv = e.pos().y() - self._pressedPos.y()
|
|
349
|
+
else:
|
|
350
|
+
dv = e.pos().x() - self._pressedPos.x()
|
|
351
|
+
|
|
352
|
+
# don't use `self.setValue()`, because it could be reimplemented
|
|
353
|
+
dv = int(dv / max(self._slideLength(), 1) * (self.maximum() - self.minimum()))
|
|
354
|
+
# REPLCAED<<
|
|
355
|
+
# ScrollBar.setValue(self, self.value() + dv)
|
|
356
|
+
FluentScrollBar.setValue(self, self.value() + dv)
|
|
357
|
+
# >>
|
|
358
|
+
self._pressedPos = e.pos()
|
|
359
|
+
self.sliderMoved.emit()
|
|
360
|
+
|
|
361
|
+
def _adjustPos(self, size):
|
|
362
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
363
|
+
self.resize(12, size.height() - 2)
|
|
364
|
+
self.move(size.width() - 13, 1)
|
|
365
|
+
else:
|
|
366
|
+
self.resize(size.width() - 2, 12)
|
|
367
|
+
self.move(1, size.height() - 13)
|
|
368
|
+
|
|
369
|
+
def _adjustHandleSize(self):
|
|
370
|
+
p = self.parent()
|
|
371
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
372
|
+
total = self.maximum() - self.minimum() + p.height()
|
|
373
|
+
s = int(self._grooveLength() * p.height() / max(total, 1))
|
|
374
|
+
self.handle.setFixedHeight(max(30, s))
|
|
375
|
+
else:
|
|
376
|
+
total = self.maximum() - self.minimum() + p.width()
|
|
377
|
+
s = int(self._grooveLength() * p.width() / max(total, 1))
|
|
378
|
+
self.handle.setFixedWidth(max(30, s))
|
|
379
|
+
|
|
380
|
+
def _adjustHandlePos(self):
|
|
381
|
+
total = max(self.maximum() - self.minimum(), 1)
|
|
382
|
+
delta = int(self.value() / total * self._slideLength())
|
|
383
|
+
|
|
384
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
385
|
+
x = self.width() - self.handle.width() - 3
|
|
386
|
+
self.handle.move(x, self._padding + delta)
|
|
387
|
+
else:
|
|
388
|
+
y = self.height() - self.handle.height() - 3
|
|
389
|
+
self.handle.move(self._padding + delta, y)
|
|
390
|
+
|
|
391
|
+
def _grooveLength(self):
|
|
392
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
393
|
+
return self.height() - 2 * self._padding
|
|
394
|
+
|
|
395
|
+
return self.width() - 2 * self._padding
|
|
396
|
+
|
|
397
|
+
def _slideLength(self):
|
|
398
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
399
|
+
return self._grooveLength() - self.handle.height()
|
|
400
|
+
|
|
401
|
+
return self._grooveLength() - self.handle.width()
|
|
402
|
+
|
|
403
|
+
def _isSlideResion(self, pos: QPoint):
|
|
404
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
405
|
+
return self._padding <= pos.y() <= self.height() - self._padding
|
|
406
|
+
|
|
407
|
+
return self._padding <= pos.x() <= self.width() - self._padding
|
|
408
|
+
|
|
409
|
+
def _onOpacityAniValueChanged(self):
|
|
410
|
+
opacity = self.groove.opacityEffect.opacity()
|
|
411
|
+
if self.orientation() == Qt.Orientation.Vertical:
|
|
412
|
+
self.handle.setFixedWidth(int(3 + opacity * 3))
|
|
413
|
+
else:
|
|
414
|
+
self.handle.setFixedHeight(int(3 + opacity * 3))
|
|
415
|
+
|
|
416
|
+
self._adjustHandlePos()
|
|
417
|
+
|
|
418
|
+
def setForceHidden(self, isHidden: bool):
|
|
419
|
+
"""whether to force the scrollbar to be hidden"""
|
|
420
|
+
self._isForceHidden = isHidden
|
|
421
|
+
self.setVisible(self.maximum() > 0 and not isHidden)
|
|
422
|
+
|
|
423
|
+
def wheelEvent(self, e):
|
|
424
|
+
QApplication.sendEvent(self.parent().viewport(), e)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class VerticalFluentAdaptiveScroller(FluentScrollBar, QWidget):
|
|
428
|
+
def __init__(self, parent: QWidget):
|
|
429
|
+
super().__init__(Qt.Orientation.Vertical, parent)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
class HorizontalFluentAdaptiveScroller(FluentScrollBar):
|
|
433
|
+
def __init__(self, parent: QWidget):
|
|
434
|
+
super().__init__(Qt.Orientation.Horizontal, parent)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class VerticalFluentScroller(VerticalFluentAdaptiveScroller):
|
|
438
|
+
def __init__(self, parent: QWidget):
|
|
439
|
+
super().__init__(parent)
|
|
440
|
+
|
|
441
|
+
def _adjustPos(self, size):
|
|
442
|
+
pass
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class HorizontalFluentScroller(HorizontalFluentAdaptiveScroller):
|
|
446
|
+
def __init__(self, parent: QWidget):
|
|
447
|
+
super().__init__(parent)
|
|
448
|
+
|
|
449
|
+
def _adjustPos(self, size):
|
|
450
|
+
pass
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from PySide6.QtGui import QPainter, QPixmap, QPen, QResizeEvent, QColor
|
|
2
|
+
from PySide6.QtCore import Qt
|
|
3
|
+
from PySide6.QtWidgets import QLabel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LineCard(QLabel):
|
|
7
|
+
"""
|
|
8
|
+
A custom QLabel widget that displays a horizontal line.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
line_color (Qt.GlobalColor): The color of the line. Defaults to Qt.GlobalColor.black.
|
|
12
|
+
line_width (int): The width of the line. Defaults to 2.
|
|
13
|
+
dash_type (list): The dash pattern of the line. Defaults to [3, 10, 1, 10, 1, 10].
|
|
14
|
+
width (int): The width of the widget. Defaults to 200.
|
|
15
|
+
height (int): The height of the widget. Defaults to 10.
|
|
16
|
+
parent (QWidget): The parent widget. Defaults to None.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
line_color=Qt.GlobalColor.black,
|
|
22
|
+
line_width=2,
|
|
23
|
+
dash_type=(3, 10, 1, 10, 1, 10),
|
|
24
|
+
width=200,
|
|
25
|
+
height=10,
|
|
26
|
+
parent=None,
|
|
27
|
+
) -> None:
|
|
28
|
+
self.dash_type = list(dash_type)
|
|
29
|
+
self.line_width = line_width
|
|
30
|
+
self.line_color = line_color
|
|
31
|
+
super().__init__(parent=parent)
|
|
32
|
+
self.resize(width, height)
|
|
33
|
+
|
|
34
|
+
def __draw_line(self):
|
|
35
|
+
"""
|
|
36
|
+
Internal method to draw the line on the widget.
|
|
37
|
+
"""
|
|
38
|
+
canvas = QPixmap(self.width(), self.height())
|
|
39
|
+
canvas.fill(QColor(0, 0, 0, 0))
|
|
40
|
+
painter = QPainter(canvas)
|
|
41
|
+
pen = QPen(self.line_color, self.line_width)
|
|
42
|
+
pen.setDashPattern(self.dash_type)
|
|
43
|
+
painter.setPen(pen)
|
|
44
|
+
painter.drawLine(0, int(self.height() / 2), self.width(), int(self.height() / 2))
|
|
45
|
+
painter.end()
|
|
46
|
+
self.setPixmap(canvas)
|
|
47
|
+
|
|
48
|
+
def set_dash_type(self, dash_type):
|
|
49
|
+
"""
|
|
50
|
+
Set the dash pattern of the line.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
dash_type (list): The dash pattern of the line.
|
|
54
|
+
"""
|
|
55
|
+
self.dash_type = dash_type
|
|
56
|
+
self.__draw_line()
|
|
57
|
+
|
|
58
|
+
def set_line_width(self, line_width):
|
|
59
|
+
"""
|
|
60
|
+
Set the width of the line.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
line_width (int): The width of the line.
|
|
64
|
+
"""
|
|
65
|
+
self.lineWidth = line_width
|
|
66
|
+
self.__draw_line()
|
|
67
|
+
|
|
68
|
+
def set_line_color(self, line_color):
|
|
69
|
+
"""
|
|
70
|
+
Set the color of the line.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
line_color (Qt.GlobalColor): The color of the line.
|
|
74
|
+
"""
|
|
75
|
+
self.line_color = line_color
|
|
76
|
+
self.__draw_line()
|
|
77
|
+
|
|
78
|
+
def resizeEvent(self, a0: QResizeEvent) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Reimplemented from QLabel.resizeEvent().
|
|
81
|
+
Redraws the line when the widget is resized.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
a0 (QResizeEvent): The resize event.
|
|
85
|
+
"""
|
|
86
|
+
self.__draw_line()
|
|
87
|
+
return super().resizeEvent(a0)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# class DashTypeAction(Action):
|
|
91
|
+
#
|
|
92
|
+
# def __init__(self, dash_type, dash_type_name=None, parent=None):
|
|
93
|
+
# self.dash_type=dash_type
|
|
94
|
+
# self.dash_type_name=dash_type_name
|
|
95
|
+
# super().__init__(text=" ", parent=parent)
|
|
96
|
+
#
|
|
97
|
+
# class DashTypeRoundMenu(RoundMenu):
|
|
98
|
+
#
|
|
99
|
+
# def __init__(self, title="", line_width=2,line_color=Qt.GlobalColor.black,parent=None):
|
|
100
|
+
# self.line_width=line_width
|
|
101
|
+
# self.line_color=line_color
|
|
102
|
+
# super().__init__(title, parent)
|
|
103
|
+
#
|
|
104
|
+
# def add_dash_type_action(self, action: DashTypeAction):
|
|
105
|
+
# item = self._createActionItem(action)
|
|
106
|
+
# self.view.addItem(item)
|
|
107
|
+
# line_card=LineCard(line_color=self.line_color,line_width=self.line_width,dash_type=action.dash_type)
|
|
108
|
+
# self.view.setItemWidget(item, line_card)
|
|
109
|
+
# line_card.sigClicked.connect(lambda:self._onItemClicked(item))
|
|
110
|
+
# self.adjustSize()
|
|
111
|
+
#
|
|
112
|
+
# def add_dash_type_actions(self, actions: list[DashTypeAction]):
|
|
113
|
+
# for action in actions:
|
|
114
|
+
# self.add_dash_type_action(action)
|
|
115
|
+
#
|
|
116
|
+
# class DashTypeCheckableMenu(CheckableMenu):
|
|
117
|
+
#
|
|
118
|
+
# def __init__(self, title="", parent=None,indicatorType=MenuIndicatorType.RADIO,line_width=2,line_color=Qt.GlobalColor.black):
|
|
119
|
+
# self.line_width=line_width
|
|
120
|
+
# self.line_color=line_color
|
|
121
|
+
# super().__init__(title, parent,indicatorType=MenuIndicatorType.RADIO)
|
|
122
|
+
#
|
|
123
|
+
# def add_dash_type_action(self, action: DashTypeAction):
|
|
124
|
+
# item = self._createActionItem(action)
|
|
125
|
+
# item.setIcon(toQIcon(FluentIcon.ADD))
|
|
126
|
+
# self.view.addItem(item)
|
|
127
|
+
# line_card=LineCard(line_color=self.line_color,line_width=self.line_width,dash_type=action.dash_type)
|
|
128
|
+
# self.view.setItemWidget(item, line_card)
|
|
129
|
+
# def _onItemClicked():
|
|
130
|
+
# action.trigger()
|
|
131
|
+
# self._closeParentMenu()
|
|
132
|
+
# self.adjustSize()
|
|
133
|
+
# line_card.sigClicked.connect(_onItemClicked)
|
|
134
|
+
# self.adjustSize()
|
|
135
|
+
#
|
|
136
|
+
# def add_dash_type_actions(self, actions: list[DashTypeAction]):
|
|
137
|
+
# for action in actions:
|
|
138
|
+
# self.add_dash_type_action(action)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Modify from PySide6-fluent-widgets
|
|
2
|
+
from PySide6.QtCore import Qt
|
|
3
|
+
from PySide6.QtWidgets import QWidget, QStackedWidget, QVBoxLayout
|
|
4
|
+
from qfluentwidgets import Pivot, qrouter, SegmentedWidget
|
|
5
|
+
from ..libs.style import StyleSheet
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PivotInterface(QWidget):
|
|
9
|
+
"""Pivot interface"""
|
|
10
|
+
|
|
11
|
+
Nav = Pivot
|
|
12
|
+
|
|
13
|
+
def __init__(self, parent=None):
|
|
14
|
+
super().__init__(parent=parent)
|
|
15
|
+
self.pivot = self.Nav(self)
|
|
16
|
+
self.stackedWidget = QStackedWidget(self)
|
|
17
|
+
self.vBoxLayout = QVBoxLayout(self)
|
|
18
|
+
self.vBoxLayout.addWidget(self.pivot, 0, Qt.AlignmentFlag.AlignLeft)
|
|
19
|
+
self.vBoxLayout.addWidget(self.stackedWidget)
|
|
20
|
+
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
|
21
|
+
StyleSheet.NAVIGATION_VIEW_INTERFACE.apply(self)
|
|
22
|
+
self.stackedWidget.currentChanged.connect(self.onCurrentIndexChanged)
|
|
23
|
+
|
|
24
|
+
def set_current_item(self, widget):
|
|
25
|
+
self.stackedWidget.setCurrentWidget(widget)
|
|
26
|
+
self.pivot.setCurrentItem(widget.objectName())
|
|
27
|
+
qrouter.setDefaultRouteKey(self.stackedWidget, widget.objectName())
|
|
28
|
+
|
|
29
|
+
def addSubInterface(self, widget, objectName, text):
|
|
30
|
+
widget.setObjectName(objectName)
|
|
31
|
+
# widget.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)
|
|
32
|
+
self.stackedWidget.addWidget(widget)
|
|
33
|
+
self.pivot.addItem(routeKey=objectName, text=text, onClick=lambda: self.stackedWidget.setCurrentWidget(widget))
|
|
34
|
+
if len(self.pivot.items) == 1:
|
|
35
|
+
self.set_current_item(widget)
|
|
36
|
+
|
|
37
|
+
def onCurrentIndexChanged(self, index):
|
|
38
|
+
widget = self.stackedWidget.widget(index)
|
|
39
|
+
self.pivot.setCurrentItem(widget.objectName())
|
|
40
|
+
qrouter.push(self.stackedWidget, widget.objectName())
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SegmentedInterface(PivotInterface):
|
|
44
|
+
Nav = SegmentedWidget
|
|
45
|
+
|
|
46
|
+
def __init__(self, parent=None):
|
|
47
|
+
super().__init__(parent)
|
|
48
|
+
self.vBoxLayout.removeWidget(self.pivot)
|
|
49
|
+
self.vBoxLayout.insertWidget(0, self.pivot)
|