diff --git a/src/chatlog/content/broken.cpp b/src/chatlog/content/broken.cpp index 170002ed7..2dcd8a849 100644 --- a/src/chatlog/content/broken.cpp +++ b/src/chatlog/content/broken.cpp @@ -50,11 +50,6 @@ void Broken::setWidth(qreal width) Q_UNUSED(width) } -void Broken::visibilityChanged(bool visible) -{ - Q_UNUSED(visible) -} - qreal Broken::getAscent() const { return 0.0; diff --git a/src/chatlog/content/broken.h b/src/chatlog/content/broken.h index 7197b3531..4fdff2681 100644 --- a/src/chatlog/content/broken.h +++ b/src/chatlog/content/broken.h @@ -33,7 +33,6 @@ public: void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; void setWidth(qreal width) override; - void visibilityChanged(bool visible) override; qreal getAscent() const override; private: diff --git a/src/chatlog/content/notificationicon.cpp b/src/chatlog/content/notificationicon.cpp index 5efd13775..8144c6ae0 100644 --- a/src/chatlog/content/notificationicon.cpp +++ b/src/chatlog/content/notificationicon.cpp @@ -30,13 +30,12 @@ NotificationIcon::NotificationIcon(QSize Size) { pmap = PixmapCache::getInstance().get(Style::getImagePath("chatArea/typing.svg"), size); - updateTimer = new QTimer(this); - updateTimer->setInterval(1000 / 30); - updateTimer->setSingleShot(false); + // Timer for the animation, if the Widget is not redrawn, no paint events will + // arrive and the timer will not be restarted, so this stops automatically + updateTimer.setInterval(1000 / framerate); + updateTimer.setSingleShot(true); - updateTimer->start(); - - connect(updateTimer, &QTimer::timeout, this, &NotificationIcon::updateGradient); + connect(&updateTimer, &QTimer::timeout, this, &NotificationIcon::updateGradient); } QRectF NotificationIcon::boundingRect() const @@ -54,6 +53,10 @@ void NotificationIcon::paint(QPainter* painter, const QStyleOptionGraphicsItem* painter->fillRect(QRect(0, 0, size.width(), size.height()), grad); painter->drawPixmap(0, 0, size.width(), size.height(), pmap); + if (!updateTimer.isActive()) { + updateTimer.start(); + } + Q_UNUSED(option) Q_UNUSED(widget) } @@ -70,10 +73,12 @@ qreal NotificationIcon::getAscent() const void NotificationIcon::updateGradient() { + // Update for next frame alpha += 0.01; - if (alpha + dotWidth >= 1.0) + if (alpha + dotWidth >= 1.0) { alpha = 0.0; + } grad = QLinearGradient(QPointF(-0.5 * size.width(), 0), QPointF(3.0 / 2.0 * size.width(), 0)); grad.setColorAt(0, Qt::lightGray); @@ -82,6 +87,7 @@ void NotificationIcon::updateGradient() grad.setColorAt(qMin(1.0, alpha + dotWidth), Qt::lightGray); grad.setColorAt(1, Qt::lightGray); - if (scene() && isVisible()) + if (scene() && isVisible()) { scene()->invalidate(sceneBoundingRect()); + } } diff --git a/src/chatlog/content/notificationicon.h b/src/chatlog/content/notificationicon.h index 18395e331..f7fa04526 100644 --- a/src/chatlog/content/notificationicon.h +++ b/src/chatlog/content/notificationicon.h @@ -23,8 +23,7 @@ #include #include - -class QTimer; +#include class NotificationIcon : public ChatLineContent { @@ -42,10 +41,12 @@ private slots: void updateGradient(); private: + static constexpr int framerate = 30; // 30Hz + QSize size; QPixmap pmap; QLinearGradient grad; - QTimer* updateTimer = nullptr; + QTimer updateTimer; qreal dotWidth = 0.2; qreal alpha = 0.0; diff --git a/src/chatlog/content/spinner.cpp b/src/chatlog/content/spinner.cpp index 2c60dabf9..3d08d46a7 100644 --- a/src/chatlog/content/spinner.cpp +++ b/src/chatlog/content/spinner.cpp @@ -26,14 +26,18 @@ #include #include +#include + Spinner::Spinner(const QString& img, QSize Size, qreal speed) : size(Size) , rotSpeed(speed) { pmap = PixmapCache::getInstance().get(img, size); - timer.setInterval(1000 / 30); // 30Hz - timer.setSingleShot(false); + // Timer for the animation, if the Widget is not redrawn, no paint events will + // arrive and the timer will not be restarted, so this stops automatically + timer.setInterval(1000 / framerate); + timer.setSingleShot(true); blendAnimation = new QVariantAnimation(this); blendAnimation->setStartValue(0.0); @@ -56,14 +60,17 @@ void Spinner::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, Q { painter->setClipRect(boundingRect()); - QTransform trans = QTransform() - .rotate(QTime::currentTime().msecsSinceStartOfDay() / 1000.0 * rotSpeed) + QTransform trans = QTransform().rotate(curRot) .translate(-size.width() / 2.0, -size.height() / 2.0); painter->setOpacity(alpha); painter->setTransform(trans, true); painter->setRenderHint(QPainter::SmoothPixmapTransform); painter->drawPixmap(0, 0, pmap); + if (!timer.isActive()) { + timer.start(); // update bounding rectangle for next frame + } + Q_UNUSED(option) Q_UNUSED(widget) } @@ -73,14 +80,6 @@ void Spinner::setWidth(qreal width) Q_UNUSED(width) } -void Spinner::visibilityChanged(bool visible) -{ - if (visible) - timer.start(); - else - timer.stop(); -} - qreal Spinner::getAscent() const { return 0.0; @@ -88,6 +87,12 @@ qreal Spinner::getAscent() const void Spinner::timeout() { - if (scene()) + // Use global time, so the animations are synced + float angle = QTime::currentTime().msecsSinceStartOfDay() / 1000.0f * rotSpeed; + // limit to the range [0.0 - 360.0] + curRot = remainderf(angle, 360.0f); + + if (scene()) { scene()->invalidate(sceneBoundingRect()); + } } diff --git a/src/chatlog/content/spinner.h b/src/chatlog/content/spinner.h index 48abd9fdf..1da01e335 100644 --- a/src/chatlog/content/spinner.h +++ b/src/chatlog/content/spinner.h @@ -37,16 +37,17 @@ public: void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; void setWidth(qreal width) override; - void visibilityChanged(bool visible) override; qreal getAscent() const override; private slots: void timeout(); private: + static constexpr int framerate = 30; // 30Hz QSize size; QPixmap pmap; qreal rotSpeed; + qreal curRot; QTimer timer; qreal alpha = 0.0; QVariantAnimation* blendAnimation;