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,319 @@
1
+ # coding:utf-8
2
+ from PySide6.QtCore import Qt, Signal, QSize, QPropertyAnimation, QPoint
3
+ from PySide6.QtGui import QPixmap, QPainter, QColor
4
+ from PySide6.QtWidgets import QWidget, QGraphicsOpacityEffect, QHBoxLayout, QVBoxLayout
5
+
6
+ from ..common.icon import FluentIcon
7
+ from ..common.style_sheet import isDarkTheme, FluentStyleSheet
8
+ from ..components.widgets.button import TransparentToolButton
9
+ from ..components.widgets.tool_tip import ToolTipFilter
10
+ from ..components.widgets.slider import Slider
11
+ from ..components.widgets.label import CaptionLabel
12
+ from ..components.widgets.flyout import Flyout, FlyoutViewBase, PullUpFlyoutAnimationManager
13
+ from .media_player import MediaPlayer, MediaPlayerBase
14
+
15
+
16
+ class MediaPlayBarButton(TransparentToolButton):
17
+ """ Media play bar button """
18
+
19
+ def _postInit(self):
20
+ super()._postInit()
21
+ self.installEventFilter(ToolTipFilter(self, 1000))
22
+ self.setFixedSize(30, 30)
23
+ self.setIconSize(QSize(16, 16))
24
+
25
+
26
+ class PlayButton(MediaPlayBarButton):
27
+ """ Play button """
28
+
29
+ def _postInit(self):
30
+ super()._postInit()
31
+ self.setIconSize(QSize(14, 14))
32
+ self.setPlay(False)
33
+
34
+ def setPlay(self, isPlay: bool):
35
+ if isPlay:
36
+ self.setIcon(FluentIcon.PAUSE_BOLD)
37
+ self.setToolTip(self.tr('Pause'))
38
+ else:
39
+ self.setIcon(FluentIcon.PLAY_SOLID)
40
+ self.setToolTip(self.tr('Play'))
41
+
42
+
43
+ class VolumeView(FlyoutViewBase):
44
+ """ Volume view """
45
+
46
+ def __init__(self, parent=None):
47
+ super().__init__(parent)
48
+ self.muteButton = MediaPlayBarButton(FluentIcon.VOLUME, self)
49
+ self.volumeSlider = Slider(Qt.Horizontal, self)
50
+ self.volumeLabel = CaptionLabel('30', self)
51
+
52
+ self.volumeSlider.setRange(0, 100)
53
+ self.volumeSlider.setFixedWidth(208)
54
+ self.setFixedSize(295, 64)
55
+
56
+ h = self.height()
57
+ self.muteButton.move(10, h//2-self.muteButton.height()//2)
58
+ self.volumeSlider.move(45, 21)
59
+
60
+ def setMuted(self, isMute: bool):
61
+ if isMute:
62
+ self.muteButton.setIcon(FluentIcon.MUTE)
63
+ self.muteButton.setToolTip(self.tr('Unmute'))
64
+ else:
65
+ self.muteButton.setIcon(FluentIcon.VOLUME)
66
+ self.muteButton.setToolTip(self.tr('Mute'))
67
+
68
+ def setVolume(self, volume: int):
69
+ self.volumeSlider.setValue(volume)
70
+
71
+ self.volumeLabel.setNum(volume)
72
+ self.volumeLabel.adjustSize()
73
+
74
+ tr = self.volumeLabel.fontMetrics().boundingRect(str(volume))
75
+ self.volumeLabel.move(self.width() - 20 - tr.width(), self.height()//2 - tr.height()//2)
76
+
77
+ def paintEvent(self, e):
78
+ painter = QPainter(self)
79
+ painter.setRenderHints(QPainter.Antialiasing)
80
+
81
+ if isDarkTheme():
82
+ painter.setBrush(QColor(46, 46, 46))
83
+ painter.setPen(QColor(0, 0, 0, 20))
84
+ else:
85
+ painter.setBrush(QColor(248, 248, 248))
86
+ painter.setPen(QColor(0, 0, 0, 10))
87
+
88
+ painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), 8, 8)
89
+
90
+
91
+ class VolumeButton(MediaPlayBarButton):
92
+ """ Volume button """
93
+
94
+ volumeChanged = Signal(int)
95
+ mutedChanged = Signal(bool)
96
+
97
+ def _postInit(self):
98
+ super()._postInit()
99
+ self.volumeView = VolumeView(self)
100
+ self.volumeFlyout = Flyout(self.volumeView, self.window(), False)
101
+ self.setMuted(False)
102
+
103
+ self.volumeFlyout.hide()
104
+ self.volumeView.muteButton.clicked.connect(lambda: self.mutedChanged.emit(not self.isMuted))
105
+ self.volumeView.volumeSlider.valueChanged.connect(self.volumeChanged)
106
+ self.clicked.connect(self._showVolumeFlyout)
107
+
108
+ def setMuted(self, isMute: bool):
109
+ self.isMuted = isMute
110
+ self.volumeView.setMuted(isMute)
111
+
112
+ if isMute:
113
+ self.setIcon(FluentIcon.MUTE)
114
+ else:
115
+ self.setIcon(FluentIcon.VOLUME)
116
+
117
+ def setVolume(self, volume: int):
118
+ self.volumeView.setVolume(volume)
119
+
120
+ def _showVolumeFlyout(self):
121
+ if self.volumeFlyout.isVisible():
122
+ return
123
+
124
+ pos = PullUpFlyoutAnimationManager(self.volumeFlyout).position(self)
125
+ self.volumeFlyout.exec(pos)
126
+
127
+
128
+
129
+ class MediaPlayBarBase(QWidget):
130
+ """ Play bar base class """
131
+
132
+ def __init__(self, parent=None):
133
+ super().__init__(parent=parent)
134
+ self.player = None # type: MediaPlayerBase
135
+
136
+ self.playButton = PlayButton(self)
137
+ self.volumeButton = VolumeButton(self)
138
+ self.progressSlider = Slider(Qt.Horizontal, self)
139
+
140
+ self.opacityEffect = QGraphicsOpacityEffect(self)
141
+ self.opacityAni = QPropertyAnimation(self.opacityEffect, b'opacity')
142
+ self.opacityEffect.setOpacity(1)
143
+ self.opacityAni.setDuration(250)
144
+
145
+ self.setGraphicsEffect(self.opacityEffect)
146
+ FluentStyleSheet.MEDIA_PLAYER.apply(self)
147
+
148
+ self.playButton.clicked.connect(self.togglePlayState)
149
+
150
+ def setMediaPlayer(self, player: MediaPlayerBase):
151
+ """ set media player """
152
+ self.player = player
153
+
154
+ self.player.durationChanged.connect(self.progressSlider.setMaximum)
155
+ self.player.positionChanged.connect(self._onPositionChanged)
156
+ self.player.mediaStatusChanged.connect(self._onMediaStatusChanged)
157
+ self.player.volumeChanged.connect(self.volumeButton.setVolume)
158
+ self.player.mutedChanged.connect(self.volumeButton.setMuted)
159
+
160
+ # don't use valueChanged, otherwise the sound will be interupted
161
+ self.progressSlider.sliderMoved.connect(self.player.setPosition)
162
+ self.progressSlider.clicked.connect(self.player.setPosition)
163
+ self.volumeButton.volumeChanged.connect(self.player.setVolume)
164
+ self.volumeButton.mutedChanged.connect(self.player.setMuted)
165
+
166
+ self.player.setVolume(30)
167
+
168
+ def fadeIn(self):
169
+ self.opacityAni.setStartValue(self.opacityEffect.opacity())
170
+ self.opacityAni.setEndValue(1)
171
+ self.opacityAni.start()
172
+
173
+ def fadeOut(self):
174
+ self.opacityAni.setStartValue(self.opacityEffect.opacity())
175
+ self.opacityAni.setEndValue(0)
176
+ self.opacityAni.start()
177
+
178
+ def play(self):
179
+ self.player.play()
180
+
181
+ def pause(self):
182
+ self.player.pause()
183
+
184
+ def stop(self):
185
+ self.player.stop()
186
+
187
+ def setVolume(self, volume: int):
188
+ """ Sets the volume of player """
189
+ self.player.setVolume(volume)
190
+
191
+ def setPosition(self, position: int):
192
+ """ Sets the position of media in ms """
193
+ self.player.setPosition(position)
194
+
195
+ def _onPositionChanged(self, position: int):
196
+ self.progressSlider.setValue(position)
197
+
198
+ def _onMediaStatusChanged(self, status):
199
+ self.playButton.setPlay(self.player.isPlaying())
200
+
201
+ def togglePlayState(self):
202
+ """ toggle the play state of media player """
203
+ if self.player.isPlaying():
204
+ self.player.pause()
205
+ else:
206
+ self.player.play()
207
+
208
+ self.playButton.setPlay(self.player.isPlaying())
209
+
210
+ def paintEvent(self, e):
211
+ painter = QPainter(self)
212
+ painter.setRenderHints(QPainter.Antialiasing)
213
+
214
+ if isDarkTheme():
215
+ painter.setBrush(QColor(46, 46, 46))
216
+ painter.setPen(QColor(0, 0, 0, 20))
217
+ else:
218
+ painter.setBrush(QColor(248, 248, 248))
219
+ painter.setPen(QColor(0, 0, 0, 10))
220
+
221
+ painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), 8, 8)
222
+
223
+
224
+
225
+ class SimpleMediaPlayBar(MediaPlayBarBase):
226
+ """ simple media play bar """
227
+
228
+ def __init__(self, parent=None):
229
+ super().__init__(parent)
230
+ self.hBoxLayout = QHBoxLayout(self)
231
+
232
+ self.hBoxLayout.setContentsMargins(10, 4, 10, 4)
233
+ self.hBoxLayout.setSpacing(6)
234
+ self.hBoxLayout.addWidget(self.playButton, 0, Qt.AlignLeft)
235
+ self.hBoxLayout.addWidget(self.progressSlider, 1)
236
+ self.hBoxLayout.addWidget(self.volumeButton, 0)
237
+
238
+ self.setFixedHeight(48)
239
+ self.setMediaPlayer(MediaPlayer(self))
240
+
241
+ def addButton(self, button: MediaPlayBarButton):
242
+ """ add button to the right side of play bar """
243
+ self.hBoxLayout.addWidget(button, 0)
244
+
245
+
246
+ class StandardMediaPlayBar(MediaPlayBarBase):
247
+ """ Standard media play bar """
248
+
249
+ def __init__(self, parent=None):
250
+ super().__init__(parent)
251
+ self.vBoxLayout = QVBoxLayout(self)
252
+ self.timeLayout = QHBoxLayout()
253
+ self.buttonLayout = QHBoxLayout()
254
+ self.leftButtonContainer = QWidget()
255
+ self.centerButtonContainer = QWidget()
256
+ self.rightButtonContainer = QWidget()
257
+ self.leftButtonLayout = QHBoxLayout(self.leftButtonContainer)
258
+ self.centerButtonLayout = QHBoxLayout(self.centerButtonContainer)
259
+ self.rightButtonLayout = QHBoxLayout(self.rightButtonContainer)
260
+
261
+ self.skipBackButton = MediaPlayBarButton(FluentIcon.SKIP_BACK, self)
262
+ self.skipForwardButton = MediaPlayBarButton(FluentIcon.SKIP_FORWARD, self)
263
+
264
+ self.currentTimeLabel = CaptionLabel('0:00:00', self)
265
+ self.remainTimeLabel = CaptionLabel('0:00:00', self)
266
+
267
+ self.__initWidgets()
268
+
269
+ def __initWidgets(self):
270
+ self.setFixedHeight(102)
271
+ self.vBoxLayout.setSpacing(6)
272
+ self.vBoxLayout.setContentsMargins(5, 9, 5, 9)
273
+ self.vBoxLayout.addWidget(self.progressSlider, 1, Qt.AlignTop)
274
+
275
+ self.vBoxLayout.addLayout(self.timeLayout)
276
+ self.timeLayout.setContentsMargins(10, 0, 10, 0)
277
+ self.timeLayout.addWidget(self.currentTimeLabel, 0, Qt.AlignLeft)
278
+ self.timeLayout.addWidget(self.remainTimeLabel, 0, Qt.AlignRight)
279
+
280
+ self.vBoxLayout.addStretch(1)
281
+ self.vBoxLayout.addLayout(self.buttonLayout, 1)
282
+ self.buttonLayout.setContentsMargins(0, 0, 0, 0)
283
+ self.leftButtonLayout.setContentsMargins(4, 0, 0, 0)
284
+ self.centerButtonLayout.setContentsMargins(0, 0, 0, 0)
285
+ self.rightButtonLayout.setContentsMargins(0, 0, 4, 0)
286
+
287
+ self.leftButtonLayout.addWidget(self.volumeButton, 0, Qt.AlignLeft)
288
+ self.centerButtonLayout.addWidget(self.skipBackButton)
289
+ self.centerButtonLayout.addWidget(self.playButton)
290
+ self.centerButtonLayout.addWidget(self.skipForwardButton)
291
+
292
+ self.buttonLayout.addWidget(self.leftButtonContainer, 0, Qt.AlignLeft)
293
+ self.buttonLayout.addWidget(self.centerButtonContainer, 0, Qt.AlignHCenter)
294
+ self.buttonLayout.addWidget(self.rightButtonContainer, 0, Qt.AlignRight)
295
+
296
+ self.setMediaPlayer(MediaPlayer(self))
297
+
298
+ self.skipBackButton.clicked.connect(lambda: self.skipBack(10000))
299
+ self.skipForwardButton.clicked.connect(lambda: self.skipForward(30000))
300
+
301
+ def skipBack(self, ms: int):
302
+ """ Back up for specified milliseconds """
303
+ self.player.setPosition(self.player.position()-ms)
304
+
305
+ def skipForward(self, ms: int):
306
+ """ Fast forward specified milliseconds """
307
+ self.player.setPosition(self.player.position()+ms)
308
+
309
+ def _onPositionChanged(self, position: int):
310
+ super()._onPositionChanged(position)
311
+ self.currentTimeLabel.setText(self._formatTime(position))
312
+ self.remainTimeLabel.setText(self._formatTime(self.player.duration() - position))
313
+
314
+ def _formatTime(self, time: int):
315
+ time = int(time / 1000)
316
+ s = time % 60
317
+ m = int(time / 60) % 60
318
+ h = int(time / 3600)
319
+ return f'{h}:{m:02}:{s:02}'
@@ -0,0 +1,124 @@
1
+ # coding:utf-8
2
+ from PySide6.QtCore import Qt, Signal, QObject, QUrl
3
+ from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
4
+
5
+
6
+ class MediaPlayerBase(QObject):
7
+ """ Media player base class """
8
+
9
+ mediaStatusChanged = Signal(QMediaPlayer.MediaStatus)
10
+ playbackRateChanged = Signal(float)
11
+ positionChanged = Signal(int)
12
+ durationChanged = Signal(int)
13
+ sourceChanged = Signal(QUrl)
14
+ volumeChanged = Signal(int)
15
+ mutedChanged = Signal(bool)
16
+
17
+ def __init__(self, parent=None):
18
+ super().__init__(parent=parent)
19
+
20
+ def isPlaying(self):
21
+ """ Whether the media is playing """
22
+ raise NotImplementedError
23
+
24
+ def mediaStatus(self) -> QMediaPlayer.MediaStatus:
25
+ """ Return the status of the current media stream """
26
+ raise NotImplementedError
27
+
28
+ def playbackState(self) -> QMediaPlayer.PlaybackState:
29
+ """ Return the playback status of the current media stream """
30
+ raise NotImplementedError
31
+
32
+ def duration(self):
33
+ """ Returns the duration of the current media in ms """
34
+ raise NotImplementedError
35
+
36
+ def position(self):
37
+ """ Returns the current position inside the media being played back in ms """
38
+ raise NotImplementedError
39
+
40
+ def volume(self):
41
+ """ Return the volume of player """
42
+ raise NotImplementedError
43
+
44
+ def source(self) -> QUrl:
45
+ """ Return the active media source being used """
46
+ raise NotImplementedError
47
+
48
+ def pause(self):
49
+ """ Pause playing the current source """
50
+ raise NotImplementedError
51
+
52
+ def play(self):
53
+ """ Start or resume playing the current source """
54
+ raise NotImplementedError
55
+
56
+ def stop(self):
57
+ """ Stop playing, and reset the play position to the beginning """
58
+ raise NotImplementedError
59
+
60
+ def playbackRate(self) -> float:
61
+ """ Return the playback rate of the current media """
62
+ raise NotImplementedError
63
+
64
+ def setPosition(self, position: int):
65
+ """ Sets the position of media in ms """
66
+ raise NotImplementedError
67
+
68
+ def setSource(self, media: QUrl):
69
+ """ Sets the current source """
70
+ raise NotImplementedError
71
+
72
+ def setPlaybackRate(self, rate: float):
73
+ """ Sets the playback rate of player """
74
+ raise NotImplementedError
75
+
76
+ def setVolume(self, volume: int):
77
+ """ Sets the volume of player """
78
+ raise NotImplementedError
79
+
80
+ def setMuted(self, isMuted: bool):
81
+ raise NotImplementedError
82
+
83
+ def videoOutput(self) -> QObject:
84
+ """ Return the video output to be used by the media player """
85
+ raise NotImplementedError
86
+
87
+ def setVideoOutput(self, output: QObject) -> None:
88
+ """ Sets the video output to be used by the media player """
89
+ raise NotImplementedError
90
+
91
+
92
+ class MediaPlayer(QMediaPlayer):
93
+ """ Media player """
94
+
95
+ sourceChanged = Signal(QUrl)
96
+ mutedChanged = Signal(bool)
97
+ volumeChanged = Signal(int)
98
+
99
+ def __init__(self, parent=None):
100
+ super().__init__(parent=parent)
101
+ self._audioOutput = QAudioOutput(parent)
102
+ self.setAudioOutput(self._audioOutput)
103
+
104
+ def isPlaying(self):
105
+ return self.playbackState() == QMediaPlayer.PlayingState
106
+
107
+ def volume(self):
108
+ """ Return the volume of player """
109
+ return int(self.audioOutput().volume() * 100)
110
+
111
+ def setVolume(self, volume: int):
112
+ """ Sets the volume of player """
113
+ if volume == self.volume():
114
+ return
115
+
116
+ self.audioOutput().setVolume(volume / 100)
117
+ self.volumeChanged.emit(volume)
118
+
119
+ def setMuted(self, isMuted: bool):
120
+ if isMuted == self.audioOutput().isMuted():
121
+ return
122
+
123
+ self.audioOutput().setMuted(isMuted)
124
+ self.mutedChanged.emit(isMuted)
@@ -0,0 +1,93 @@
1
+ # coding:utf-8
2
+ from PySide6.QtCore import Qt, Signal, QUrl, QSizeF, QTimer
3
+ from PySide6.QtGui import QPainter
4
+ from PySide6.QtMultimediaWidgets import QGraphicsVideoItem
5
+ from PySide6.QtWidgets import QWidget, QGraphicsView, QVBoxLayout, QGraphicsScene
6
+
7
+ from ..common.style_sheet import FluentStyleSheet
8
+ from .media_play_bar import StandardMediaPlayBar
9
+
10
+
11
+ class GraphicsVideoItem(QGraphicsVideoItem):
12
+ """ Graphics video item """
13
+
14
+ def paint(self, painter: QPainter, option, widget):
15
+ painter.setCompositionMode(QPainter.CompositionMode_Difference)
16
+ super().paint(painter, option, widget)
17
+
18
+
19
+ class VideoWidget(QGraphicsView):
20
+ """ Video widget """
21
+
22
+ def __init__(self, parent=None):
23
+ super().__init__(parent)
24
+ self.isHover = False
25
+ self.timer = QTimer(self)
26
+
27
+ self.vBoxLayout = QVBoxLayout(self)
28
+ self.videoItem = QGraphicsVideoItem()
29
+ self.graphicsScene = QGraphicsScene(self)
30
+ self.playBar = StandardMediaPlayBar(self)
31
+
32
+ self.setMouseTracking(True)
33
+ self.setScene(self.graphicsScene)
34
+ self.graphicsScene.addItem(self.videoItem)
35
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
36
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
37
+ self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
38
+
39
+ self.player.setVideoOutput(self.videoItem)
40
+ FluentStyleSheet.MEDIA_PLAYER.apply(self)
41
+
42
+ self.timer.timeout.connect(self._onHideTimeOut)
43
+
44
+ def setVideo(self, url: QUrl):
45
+ """ set the video to play """
46
+ self.player.setSource(url)
47
+ self.fitInView(self.videoItem, Qt.KeepAspectRatio)
48
+
49
+ def hideEvent(self, e):
50
+ self.pause()
51
+ e.accept()
52
+
53
+ def wheelEvent(self, e):
54
+ return
55
+
56
+ def enterEvent(self, e):
57
+ self.isHover = True
58
+ self.playBar.fadeIn()
59
+
60
+ def leaveEvent(self, e):
61
+ self.isHover = False
62
+ self.timer.start(3000)
63
+
64
+ def _onHideTimeOut(self):
65
+ if not self.isHover:
66
+ self.playBar.fadeOut()
67
+
68
+ def play(self):
69
+ self.playBar.play()
70
+
71
+ def pause(self):
72
+ self.playBar.pause()
73
+
74
+ def stop(self):
75
+ self.playBar.stop()
76
+
77
+ def togglePlayState(self):
78
+ """ toggle play state """
79
+ if self.player.isPlaying():
80
+ self.pause()
81
+ else:
82
+ self.play()
83
+
84
+ def resizeEvent(self, e):
85
+ super().resizeEvent(e)
86
+ self.videoItem.setSize(QSizeF(self.size()))
87
+ self.fitInView(self.videoItem, Qt.KeepAspectRatio)
88
+ self.playBar.move(11, self.height() - self.playBar.height() - 11)
89
+ self.playBar.setFixedSize(self.width() - 22, self.playBar.height())
90
+
91
+ @property
92
+ def player(self):
93
+ return self.playBar.player
@@ -0,0 +1,2 @@
1
+ from .fluent_window import FluentWindow, MSFluentWindow, SplitFluentWindow, FluentTitleBar, MSFluentTitleBar, SplitTitleBar, FluentBackgroundTheme
2
+ from .splash_screen import SplashScreen