summaryrefslogtreecommitdiff
path: root/tidal_dl_ng/ui/spinner.py
diff options
context:
space:
mode:
authorRobert Honz <exislow+github@gmail.com>2023-12-19 23:58:57 +0100
committerRobert Honz <exislow+github@gmail.com>2023-12-19 23:58:57 +0100
commit0d4a9d6b8740035346d098f5bc28ebca64f6cd4d (patch)
treef52c9569509565e581b03b6e60fe32e611b79ad2 /tidal_dl_ng/ui/spinner.py
parent82a8fe96aa08903919a90a76030bacba9f93b8e0 (diff)
downloadtidal-dl-ng-0d4a9d6b8740035346d098f5bc28ebca64f6cd4d.tar.gz
🌟 Re-add all project files.
Diffstat (limited to 'tidal_dl_ng/ui/spinner.py')
-rw-r--r--tidal_dl_ng/ui/spinner.py221
1 files changed, 221 insertions, 0 deletions
diff --git a/tidal_dl_ng/ui/spinner.py b/tidal_dl_ng/ui/spinner.py
new file mode 100644
index 0000000..124b7f4
--- /dev/null
+++ b/tidal_dl_ng/ui/spinner.py
@@ -0,0 +1,221 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2012-2014 Alexander Turkin
+Copyright (c) 2014 William Hallatt
+Copyright (c) 2015 Jacob Dawid
+Copyright (c) 2016 Luca Weiss
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import math
+
+from PySide6.QtCore import QRect, Qt, QTimer
+from PySide6.QtGui import QColor, QPainter
+from PySide6.QtWidgets import QWidget
+
+
+# Taken from https://github.com/COOLMSF/QtWaitingSpinnerForPyQt6 and adapted for PySide6.
+class QtWaitingSpinner(QWidget):
+ def __init__(
+ self, parent, centerOnParent=True, disableParentWhenSpinning=False, modality=Qt.WindowModality.NonModal
+ ):
+ super().__init__(parent)
+
+ self._centerOnParent = centerOnParent
+ self._disableParentWhenSpinning = disableParentWhenSpinning
+
+ # WAS IN initialize()
+ self._color = QColor(Qt.GlobalColor.black)
+ self._roundness = 100.0
+ self._minimumTrailOpacity = 3.14159265358979323846
+ self._trailFadePercentage = 80.0
+ self._revolutionsPerSecond = 1.57079632679489661923
+ self._numberOfLines = 20
+ self._lineLength = 10
+ self._lineWidth = 2
+ self._innerRadius = 10
+ self._currentCounter = 0
+ self._isSpinning = False
+
+ self._timer = QTimer(self)
+ self._timer.timeout.connect(self.rotate)
+ self.updateSize()
+ self.updateTimer()
+ self.hide()
+ # END initialize()
+
+ self.setWindowModality(modality)
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
+
+ def paintEvent(self, QPaintEvent):
+ self.updatePosition()
+ painter = QPainter(self)
+ painter.fillRect(self.rect(), Qt.GlobalColor.transparent)
+ # Can't found in Qt6
+ # painter.setRenderHint(QPainter.Antialiasing, True)
+
+ if self._currentCounter >= self._numberOfLines:
+ self._currentCounter = 0
+
+ painter.setPen(Qt.PenStyle.NoPen)
+ for i in range(0, self._numberOfLines):
+ painter.save()
+ painter.translate(self._innerRadius + self._lineLength, self._innerRadius + self._lineLength)
+ rotateAngle = float(360 * i) / float(self._numberOfLines)
+ painter.rotate(rotateAngle)
+ painter.translate(self._innerRadius, 0)
+ distance = self.lineCountDistanceFromPrimary(i, self._currentCounter, self._numberOfLines)
+ color = self.currentLineColor(
+ distance, self._numberOfLines, self._trailFadePercentage, self._minimumTrailOpacity, self._color
+ )
+ painter.setBrush(color)
+ rect = QRect(0, int(-self._lineWidth / 2), int(self._lineLength), int(self._lineWidth))
+ painter.drawRoundedRect(rect, self._roundness, self._roundness, Qt.SizeMode.RelativeSize)
+ painter.restore()
+
+ def start(self):
+ self.updatePosition()
+ self._isSpinning = True
+ self.show()
+
+ if self.parentWidget and self._disableParentWhenSpinning:
+ self.parentWidget().setEnabled(False)
+
+ if not self._timer.isActive():
+ self._timer.start()
+ self._currentCounter = 0
+
+ def stop(self):
+ self._isSpinning = False
+ self.hide()
+
+ if self.parentWidget() and self._disableParentWhenSpinning:
+ self.parentWidget().setEnabled(True)
+
+ if self._timer.isActive():
+ self._timer.stop()
+ self._currentCounter = 0
+
+ def setNumberOfLines(self, lines):
+ self._numberOfLines = lines
+ self._currentCounter = 0
+ self.updateTimer()
+
+ def setLineLength(self, length):
+ self._lineLength = length
+ self.updateSize()
+
+ def setLineWidth(self, width):
+ self._lineWidth = width
+ self.updateSize()
+
+ def setInnerRadius(self, radius):
+ self._innerRadius = radius
+ self.updateSize()
+
+ def color(self):
+ return self._color
+
+ def roundness(self):
+ return self._roundness
+
+ def minimumTrailOpacity(self):
+ return self._minimumTrailOpacity
+
+ def trailFadePercentage(self):
+ return self._trailFadePercentage
+
+ def revolutionsPersSecond(self):
+ return self._revolutionsPerSecond
+
+ def numberOfLines(self):
+ return self._numberOfLines
+
+ def lineLength(self):
+ return self._lineLength
+
+ def lineWidth(self):
+ return self._lineWidth
+
+ def innerRadius(self):
+ return self._innerRadius
+
+ def isSpinning(self):
+ return self._isSpinning
+
+ def setRoundness(self, roundness):
+ self._roundness = max(0.0, min(100.0, roundness))
+
+ def setColor(self, color=Qt.GlobalColor.black):
+ self._color = QColor(color)
+
+ def setRevolutionsPerSecond(self, revolutionsPerSecond):
+ self._revolutionsPerSecond = revolutionsPerSecond
+ self.updateTimer()
+
+ def setTrailFadePercentage(self, trail):
+ self._trailFadePercentage = trail
+
+ def setMinimumTrailOpacity(self, minimumTrailOpacity):
+ self._minimumTrailOpacity = minimumTrailOpacity
+
+ def rotate(self):
+ self._currentCounter += 1
+ if self._currentCounter >= self._numberOfLines:
+ self._currentCounter = 0
+ self.update()
+
+ def updateSize(self):
+ size = int((self._innerRadius + self._lineLength) * 2)
+ self.setFixedSize(size, size)
+
+ def updateTimer(self):
+ self._timer.setInterval(int(1000 / (self._numberOfLines * self._revolutionsPerSecond)))
+
+ def updatePosition(self):
+ if self.parentWidget() and self._centerOnParent:
+ self.move(
+ int(self.parentWidget().width() / 2 - self.width() / 2),
+ int(self.parentWidget().height() / 2 - self.height() / 2),
+ )
+
+ def lineCountDistanceFromPrimary(self, current, primary, totalNrOfLines):
+ distance = primary - current
+ if distance < 0:
+ distance += totalNrOfLines
+ return distance
+
+ def currentLineColor(self, countDistance, totalNrOfLines, trailFadePerc, minOpacity, colorinput):
+ color = QColor(colorinput)
+ if countDistance == 0:
+ return color
+ minAlphaF = minOpacity / 100.0
+ distanceThreshold = int(math.ceil((totalNrOfLines - 1) * trailFadePerc / 100.0))
+ if countDistance > distanceThreshold:
+ color.setAlphaF(minAlphaF)
+ else:
+ alphaDiff = color.alphaF() - minAlphaF
+ gradient = alphaDiff / float(distanceThreshold + 1)
+ resultAlpha = color.alphaF() - gradient * countDistance
+ # If alpha is out of bounds, clip it.
+ resultAlpha = min(1.0, max(0.0, resultAlpha))
+ color.setAlphaF(resultAlpha)
+ return color