Source code for spinner_widget.spinner_widget
# Copyright (c) 2015 Shotgun Software Inc.
#
# CONFIDENTIAL AND PROPRIETARY
#
# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit
# Source Code License included in this distribution package. See LICENSE.
# By accessing, using, copying or modifying this work you indicate your
# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights
# not expressly granted therein are reserved by Shotgun Software Inc.
import sgtk
from sgtk.platform.qt import QtCore, QtGui
import time
import math
[docs]class SpinnerWidget(QtGui.QWidget):
"""
A simple widget that draws an animated spinner that spins whilst visible.
"""
def __init__(self, parent=None):
"""
:param parent: The parent widget
:type parent: :class:`~PySide.QtGui.QWidget`
"""
QtGui.QWidget.__init__(self, parent)
# public properties:
self.fps = 20
self.border = 2
self.line_width = 2
self.arc_length = 300
self.seconds_per_spin = 3
# timer used to force a repaint:
self._timer = QtCore.QTimer(self)
self._timer.timeout.connect(self._on_timer_timeout)
# keep track of the current start angle to avoid
# unnecessary repaints
self._start_angle = 0
def paintEvent(self, event):
"""
Paint the widget
:param event: The QPaintEvent event
"""
# call the base paint event:
QtGui.QWidget.paintEvent(self, event)
painter = QtGui.QPainter()
painter.begin(self)
try:
painter.setRenderHint(QtGui.QPainter.Antialiasing)
# use the foreground colour to paint with:
fg_col = self.palette().color(self.foregroundRole())
pen = QtGui.QPen(fg_col)
pen.setWidth(self.line_width)
painter.setPen(pen)
border = self.border + int(math.ceil(self.line_width / 2.0))
r = QtCore.QRect(0, 0, self.width(), self.height())
r.adjust(border, border, -border, -border)
# draw the arc:
painter.drawArc(r, -self._start_angle * 16, self.arc_length * 16)
r = None
finally:
painter.end()
painter = None
def showEvent(self, event):
"""
Called when the widget is being shown - ensures the timer is running
so that the animation plays
:param event: The event
"""
if not self._timer.isActive():
self._timer.start(1000 / max(1, self.fps))
QtGui.QWidget.showEvent(self, event)
def hideEvent(self, event):
"""
Called when the widget is being hidden - ensures the timer is stopped
to avoid unnecessary painting
:param even: The event
"""
self._timer.stop()
QtGui.QWidget.hideEvent(self, event)
def closeEvent(self, event):
"""
Called when the widget is being closed - ensures the timer is stopped
to avoid unnecessary painting
:param even: The event
"""
self._timer.stop()
QtGui.QWidget.closeEvent(self, event)
def _on_timer_timeout(self):
"""
Slot triggered when the timer times out and used to trigger a repaint of
the widget.
"""
if not self.isVisible():
# nothing to do!
return
# calculate the spin angle as a function of the current time so that all
# spinners appear in sync!
t = time.time()
whole_seconds = int(t)
p = (whole_seconds % self.seconds_per_spin) + (t - whole_seconds)
angle = int((360 * p) / self.seconds_per_spin)
if angle == self._start_angle:
# angle hasn't changed!
return
self._start_angle = angle
# trigger a repaint for the widget:
self.update()