File indexing completed on 2024-05-12 05:46:52

0001 /*
0002     Copyright 2019 Harald Sitter <sitter@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) version 3, or any
0008     later version accepted by the membership of KDE e.V. (or its
0009     successor approved by the membership of KDE e.V.), which shall
0010     act as a proxy defined in Section 6 of version 3 of the license.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Lesser General Public License for more details.
0016 
0017     You should have received a copy of the GNU Lesser General Public
0018     License along with this library.  If not, see <https://www.gnu.org/licenses/>.
0019 */
0020 
0021 #include "kbusyindicatorwidget.h"
0022 
0023 #include <QApplication>
0024 #include <QIcon>
0025 #include <QPainter>
0026 #include <QResizeEvent>
0027 #include <QStyle>
0028 #include <QVariantAnimation>
0029 
0030 class KBusyIndicatorWidgetPrivate
0031 {
0032 public:
0033     KBusyIndicatorWidgetPrivate(KBusyIndicatorWidget *parent)
0034         : q(parent)
0035     {
0036         animation.setLoopCount(-1);
0037         animation.setDuration(2000);
0038         animation.setStartValue(0);
0039         animation.setEndValue(360);
0040         QObject::connect(&animation, &QVariantAnimation::valueChanged,
0041                 q, [=](QVariant value) {
0042             rotation = value.toReal();
0043             q->update(); // repaint new rotation
0044         });
0045     }
0046 
0047     KBusyIndicatorWidget *q = nullptr;
0048     QVariantAnimation animation;
0049     QIcon icon = QIcon::fromTheme(QStringLiteral("view-refresh"));
0050     qreal rotation = 0;
0051     QPointF paintCenter;
0052 };
0053 
0054 KBusyIndicatorWidget::KBusyIndicatorWidget(QWidget *parent)
0055     : QWidget(parent)
0056     , d(new KBusyIndicatorWidgetPrivate(this))
0057 {
0058 }
0059 
0060 KBusyIndicatorWidget::~KBusyIndicatorWidget()
0061 {
0062     delete d;
0063 }
0064 
0065 QSize KBusyIndicatorWidget::minimumSizeHint() const
0066 {
0067     const auto extent = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
0068     return QSize(extent, extent);
0069 }
0070 
0071 void KBusyIndicatorWidget::showEvent(QShowEvent *event)
0072 {
0073     QWidget::showEvent(event);
0074     d->animation.start();
0075 }
0076 
0077 void KBusyIndicatorWidget::hideEvent(QHideEvent *event)
0078 {
0079     QWidget::hideEvent(event);
0080     d->animation.pause();
0081 }
0082 
0083 void KBusyIndicatorWidget::resizeEvent(QResizeEvent *event)
0084 {
0085     QWidget::resizeEvent(event);
0086     d->paintCenter = QPointF(event->size().width() / 2.0,
0087                              event->size().height() / 2.0);
0088 }
0089 
0090 void KBusyIndicatorWidget::paintEvent(QPaintEvent *)
0091 {
0092     QPainter painter(this);
0093     painter.setRenderHint(QPainter::SmoothPixmapTransform);
0094 
0095     // Rotate around the center and then reset back to origin for icon painting.
0096     painter.translate(d->paintCenter);
0097     painter.rotate(d->rotation);
0098     painter.translate(-d->paintCenter);
0099 
0100     d->icon.paint(&painter, rect());
0101 }
0102 
0103 bool KBusyIndicatorWidget::event(QEvent *event)
0104 {
0105     // Only overridden to be flexible WRT binary compatible in the future.
0106     // Overriding later has potential to change the call going through
0107     // the vtable or not.
0108     return QWidget::event(event);
0109 }