Work on a new spin animation

This commit is contained in:
Kovid Goyal 2020-12-04 18:13:40 +05:30
parent cdca0c8c29
commit 4ce301c1b0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 126 additions and 0 deletions

View File

@ -1,9 +1,87 @@
#pragma once
#include <QtWidgets/QWidget>
#include <QObject>
#include <QColor>
#include <QHash>
#include <QPainter>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
class SpinAnimator: public QObject {
Q_OBJECT
Q_PROPERTY(float arc_length READ get_arc_length WRITE set_arc_length)
Q_PROPERTY(int arc_rotation READ get_arc_rotation WRITE set_arc_rotation)
Q_PROPERTY(int overall_rotation READ get_overall_rotation WRITE set_overall_rotation)
public:
SpinAnimator(QObject* parent = 0) :
QObject(parent),
m_arc_length(0),
m_arc_rotation(0),
m_overall_rotation(0),
m_has_pending_updates(false),
m_animation(this)
{
QPropertyAnimation *a;
#define S(property, duration) a = new QPropertyAnimation(this, QByteArray(#property), this); a->setEasingCurve(QEasingCurve::InOutCubic); a->setDuration(duration); a->setLoopCount(-1); m_animation.addAnimation(a);
S(arc_length, 1400);
const float arc_length_max = 0.734f, arc_length_min = 0.01f;
a->setStartValue(arc_length_min);
a->setKeyValueAt(0.25, arc_length_min);
a->setKeyValueAt(0.5, arc_length_max);
a->setKeyValueAt(0.75, arc_length_max);
a->setEndValue(arc_length_min);
S(arc_rotation, 1400);
a->setStartValue(0);
a->setKeyValueAt(0.25, 0);
a->setKeyValueAt(0.5, 45);
a->setKeyValueAt(0.75, 45);
a->setEndValue(360);
S(overall_rotation, 2000);
a->setStartValue(0);
a->setEndValue(360);
#undef S
}
~SpinAnimator() { m_animation.stop(); m_animation.clear(); }
void start() { m_animation.start(); }
void stop() { m_animation.stop(); }
bool is_running() { return m_animation.state() == QAbstractAnimation::Running; }
void draw(QPainter &painter, QRect bounds, const QColor &color) {
m_has_pending_updates = false;
painter.save();
painter.setRenderHint(QPainter::Antialiasing);
QRectF rect(bounds);
float thickness = std::max(3.f, std::min((float)rect.width() / 10.f, 24.f));
QPen pen(color);
pen.setWidthF(thickness);
float ht = thickness / 2 + 1;
rect.adjust(ht, ht, -ht, -ht);
pen.setCapStyle(Qt::RoundCap);
painter.setPen(pen);
int rotated_by = (m_overall_rotation + m_arc_rotation) * 16;
int arc_length = (int)(m_arc_length * 360 * 16);
painter.drawArc(rect, -rotated_by, -arc_length);
painter.restore();
}
float get_arc_length() const { return m_arc_length; }
int get_arc_rotation() const { return m_arc_rotation; }
int get_overall_rotation() const { return m_overall_rotation; }
public slots:
void set_arc_length(float val) { m_arc_length = val; notify_of_update(); }
void set_arc_rotation(int val) { m_arc_rotation = val; notify_of_update(); }
void set_overall_rotation(int val) { m_overall_rotation = val; notify_of_update(); }
signals:
void updated();
private:
float m_arc_length;
int m_arc_rotation, m_overall_rotation;
bool m_has_pending_updates;
void notify_of_update() { if (!m_has_pending_updates) { m_has_pending_updates = true; emit updated(); } }
QParallelAnimationGroup m_animation;
};
/*!
\class QProgressIndicator

View File

@ -12,6 +12,29 @@ void set_no_activate_on_click(QWidget *widget);
void draw_snake_spinner(QPainter &painter, QRect rect, int angle, const QColor & light, const QColor & dark);
%End
class SpinAnimator : QObject {
%TypeHeaderCode
#include <QProgressIndicator.h>
%End
public:
SpinAnimator(QWidget *parent /TransferThis/ = 0);
float get_arc_length() const ;
int get_arc_rotation() const ;
int get_overall_rotation() const ;
void draw(QPainter &painter, QRect bounds, const QColor &color);
void start();
void stop();
bool is_running();
public slots:
void set_arc_length(float val) ;
void set_arc_rotation(int val) ;
void set_overall_rotation(int val) ;
signals:
void updated();
};
class QProgressIndicator : QWidget {
%TypeHeaderCode

View File

@ -94,6 +94,31 @@ class WaitLayout(QStackedLayout):
self.wp.msg = val
def develop():
from PyQt5.Qt import QPalette, QPainter, QRect
from calibre.gui2 import Application
from calibre_extensions.progress_indicator import SpinAnimator
class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.a = SpinAnimator(self)
self.a.updated.connect(self.update)
def paintEvent(self, ev):
p = QPainter(self)
pal = self.palette()
self.a.draw(p, QRect(0, 0, 64, 64), pal.color(QPalette.ColorRole.WindowText))
p.end()
app = Application([])
w = Widget()
w.show()
w.a.start()
app.exec_()
if __name__ == '__main__':
from calibre.gui2 import Application
app = Application([])