1 /*
2     SPDX-FileCopyrightText: 2019 Harald Sitter <sitter@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "kbusyindicatorwidget.h"
8 
9 #include <QApplication>
10 #include <QIcon>
11 #include <QPainter>
12 #include <QResizeEvent>
13 #include <QStyle>
14 #include <QVariantAnimation>
15 
16 class KBusyIndicatorWidgetPrivate
17 {
18 public:
KBusyIndicatorWidgetPrivate(KBusyIndicatorWidget * parent)19     KBusyIndicatorWidgetPrivate(KBusyIndicatorWidget *parent)
20         : q(parent)
21     {
22         animation.setLoopCount(-1);
23         animation.setDuration(2000);
24         animation.setStartValue(0);
25         animation.setEndValue(360);
26         QObject::connect(&animation, &QVariantAnimation::valueChanged, q, [=](QVariant value) {
27             rotation = value.toReal();
28             q->update(); // repaint new rotation
29         });
30     }
31 
32     KBusyIndicatorWidget *const q;
33     QVariantAnimation animation;
34     QIcon icon = QIcon::fromTheme(QStringLiteral("view-refresh"));
35     qreal rotation = 0;
36     QPointF paintCenter;
37 };
38 
KBusyIndicatorWidget(QWidget * parent)39 KBusyIndicatorWidget::KBusyIndicatorWidget(QWidget *parent)
40     : QWidget(parent)
41     , d(new KBusyIndicatorWidgetPrivate(this))
42 {
43 }
44 
45 KBusyIndicatorWidget::~KBusyIndicatorWidget() = default;
46 
minimumSizeHint() const47 QSize KBusyIndicatorWidget::minimumSizeHint() const
48 {
49     const auto extent = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
50     return QSize(extent, extent);
51 }
52 
showEvent(QShowEvent * event)53 void KBusyIndicatorWidget::showEvent(QShowEvent *event)
54 {
55     QWidget::showEvent(event);
56     d->animation.start();
57 }
58 
hideEvent(QHideEvent * event)59 void KBusyIndicatorWidget::hideEvent(QHideEvent *event)
60 {
61     QWidget::hideEvent(event);
62     d->animation.pause();
63 }
64 
resizeEvent(QResizeEvent * event)65 void KBusyIndicatorWidget::resizeEvent(QResizeEvent *event)
66 {
67     QWidget::resizeEvent(event);
68     d->paintCenter = QPointF(event->size().width() / 2.0, //
69                              event->size().height() / 2.0);
70 }
71 
paintEvent(QPaintEvent *)72 void KBusyIndicatorWidget::paintEvent(QPaintEvent *)
73 {
74     QPainter painter(this);
75     painter.setRenderHint(QPainter::SmoothPixmapTransform);
76 
77     // Rotate around the center and then reset back to origin for icon painting.
78     painter.translate(d->paintCenter);
79     painter.rotate(d->rotation);
80     painter.translate(-d->paintCenter);
81 
82     d->icon.paint(&painter, rect());
83 }
84 
event(QEvent * event)85 bool KBusyIndicatorWidget::event(QEvent *event)
86 {
87     // Only overridden to be flexible WRT binary compatible in the future.
88     // Overriding later has potential to change the call going through
89     // the vtable or not.
90     return QWidget::event(event);
91 }
92