-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspinner.py
142 lines (105 loc) · 3.89 KB
/
spinner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: Sam Schott (ss2151@cam.ac.uk)
(c) Sam Schott; This work is licensed under a Creative Commons
Attribution-NonCommercial-NoDerivs 2.0 UK: England & Wales License.
"""
# external packages
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter
from .dark_mode_support import isDarkWindow
class QProgressIndicator(QtWidgets.QWidget):
"""
A macOS style spinning progress indicator. ``QProgressIndicator`` automatically
detects and adjusts to "dark mode" appearances.
"""
m_angle = None
m_timerId = None
m_delay = None
m_displayedWhenStopped = None
m_color = None
m_light_color = QtGui.QColor(170, 170, 170)
m_dark_color = QtGui.QColor(40, 40, 40)
def __init__(self, parent=None):
# Call parent class constructor first
super(QProgressIndicator, self).__init__(parent)
# Initialize instance variables
self.m_angle = 0
self.m_timerId = -1
self.m_delay = 5/60*1000
self.m_displayedWhenStopped = False
self.m_color = self.m_dark_color
self.update_dark_mode()
# Set size and focus policy
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.setFocusPolicy(Qt.NoFocus)
def animationDelay(self):
return self.m_delay
def isAnimated(self):
return self.m_timerId != -1
def isDisplayedWhenStopped(self):
return self.m_displayedWhenStopped
def getColor(self):
return self.m_color
def sizeHint(self):
return QtCore.QSize(20, 20)
def startAnimation(self):
self.m_angle = 0
if self.m_timerId == -1:
self.m_timerId = self.startTimer(int(self.m_delay))
def stopAnimation(self):
if self.m_timerId != -1:
self.killTimer(self.m_timerId)
self.m_timerId = -1
self.update()
def setAnimationDelay(self, delay):
if self.m_timerId != -1:
self.killTimer(self.m_timerId)
self.m_delay = delay
if self.m_timerId != -1:
self.m_timerId = self.startTimer(self.m_delay)
def setDisplayedWhenStopped(self, state):
self.m_displayedWhenStopped = state
self.update()
def setColor(self, color):
self.m_color = color
self.update()
def timerEvent(self, event):
self.m_angle = (self.m_angle + 30) % 360
self.update()
def paintEvent(self, event):
if (not self.m_displayedWhenStopped) and (not self.isAnimated()):
return
width = min(self.width(), self.height())
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
outerRadius = (width - 1) * 0.5
innerRadius = (width - 1) * 0.5 * 0.4375
capsuleHeight = outerRadius - innerRadius
capsuleWidth = width * 3/32
capsuleRadius = capsuleWidth / 2
for i in range(0, 12):
color = QtGui.QColor(self.m_color)
if self.isAnimated():
color.setAlphaF(1.0 - (i / 12.0))
else:
color.setAlphaF(0.2)
painter.setPen(Qt.NoPen)
painter.setBrush(color)
painter.save()
painter.translate(self.rect().center())
painter.rotate(self.m_angle - (i * 30.0))
painter.drawRoundedRect(capsuleWidth * -0.5,
(innerRadius + capsuleHeight) * -1, capsuleWidth,
capsuleHeight, capsuleRadius, capsuleRadius)
painter.restore()
def changeEvent(self, QEvent):
if QEvent.type() == QtCore.QEvent.PaletteChange:
self.update_dark_mode()
def update_dark_mode(self):
if isDarkWindow():
self.setColor(self.m_light_color)
else:
self.setColor(self.m_dark_color)