# Copyright (C) 2020-2025 Soleta Networks # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the # Free Software Foundation; either version 3 of the License, or # (at your option) any later version. from PyQt6.QtCore import Qt, QTimer, QRect from PyQt6.QtGui import QPainter, QPen from PyQt6.QtWidgets import QApplication, QWidget class LoadSpinner(QWidget): OFFSET = 5 def __init__(self, parent=None): super().__init__(parent) self.span = 0 self.growing = True self.color = Qt.GlobalColor.blue self.start_angle = 0 self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) size = 50 self.setFixedSize(size, size) self.updateFrame() self.timer = QTimer(self) self.timer.timeout.connect(self.rotate) self.timer.setInterval(30) def setColor(self, color): self.color = color def setWidth(self, w): self.setFixedSize(w, w) self.updateFrame() def setHeight(self, h): self.setFixedSize(h, h) self.updateFrame() def start(self): self.timer.start() def stop(self): self.timer.stop() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) pen = QPen(self.color) pen.setWidth(self.height() // 10) painter.setPen(pen) painter.setOpacity(0.2) painter.drawArc(self.frame, 0, 5760) painter.setOpacity(1.0) painter.drawArc(self.frame, self.start_angle * 16, self.span * 16) def rotate(self): advance = 3 grow = 8 if self.growing: self.start_angle = (self.start_angle + advance) % 360 self.span += grow if self.span > 260: self.growing = False else: self.start_angle = (self.start_angle + grow) % 360 self.span = self.span + advance - grow if self.span < 10: self.growing = True self.update() def updateFrame(self): self.frame = QRect( self.OFFSET, self.OFFSET, self.width() - self.OFFSET * 2, self.height() - self.OFFSET * 2, )