From e0cf25fb55176d5607087241cdd800ca24f974f4 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 14 Mar 2024 15:51:39 +0100 Subject: [PATCH] Spinner: Allow setting the spinner color Deeply under the hood, the color for ther Spinner was determined by the QApplication palette, color role "Text". In order to run the spinner on a dark toolbar (in a non-dark theme), though, the color needs to be bright. It is the case for the ScreenRecorder. This change adds a color setter to the Spinner classes, adds colored Spinners to tst_spinner and makes use of the feature in the ScreenRecorder. The default color of the Spinner remains QApplication palette, color role "Text". Change-Id: Ia75758707f225b1f994e73c5a314478101c80f5e Reviewed-by: Jarek Kobus --- src/libs/solutions/spinner/spinner.cpp | 31 ++++++++++++++++--- src/libs/solutions/spinner/spinner.h | 1 + .../screenrecorder/screenrecorderplugin.cpp | 1 + tests/manual/spinner/main.cpp | 16 ++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/libs/solutions/spinner/spinner.cpp b/src/libs/solutions/spinner/spinner.cpp index b56684720bb..9c1c43b4401 100644 --- a/src/libs/solutions/spinner/spinner.cpp +++ b/src/libs/solutions/spinner/spinner.cpp @@ -72,6 +72,8 @@ public: void setUpdateCallback(const UpdateCallback &cb) { m_callback = cb; } + void setColor(const QColor &color); + QSize size() const { return m_pixmap.size() / m_pixmap.devicePixelRatio(); } void paint(QPainter &painter, const QRect &rect) const; void startAnimation() { m_timer.start(); } @@ -87,6 +89,7 @@ private: QTimer m_timer; mutable QPixmap m_pixmap; UpdateCallback m_callback; + QColor m_color; }; static QString imageFileNameForSpinnerSize(SpinnerSize size) @@ -102,12 +105,12 @@ static QString imageFileNameForSpinnerSize(SpinnerSize size) return {}; } -static QPixmap themedPixmapForSpinnerSize(SpinnerSize size, qreal dpr) +static QPixmap themedPixmapForSpinnerSize(SpinnerSize size, const QColor &color, qreal dpr) { QImage mask(qt_findAtNxFile(imageFileNameForSpinnerSize(size), dpr)); mask.invertPixels(); QImage themedImage(mask.size(), QImage::Format_ARGB32); - themedImage.fill(qApp->palette().text().color()); + themedImage.fill(color); themedImage.setAlphaChannel(mask); QPixmap themedPixmap = QPixmap::fromImage(themedImage); themedPixmap.setDevicePixelRatio(mask.devicePixelRatio()); @@ -115,6 +118,7 @@ static QPixmap themedPixmapForSpinnerSize(SpinnerSize size, qreal dpr) } SpinnerPainter::SpinnerPainter(SpinnerSize size) + : m_color(qApp->palette().text().color()) { m_timer.setSingleShot(false); QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] { @@ -130,14 +134,20 @@ void SpinnerPainter::setSize(SpinnerSize size) m_size = size; m_rotationStep = size == SpinnerSize::Small ? 45 : 30; m_timer.setInterval(size == SpinnerSize::Small ? 100 : 80); - m_pixmap = themedPixmapForSpinnerSize(size, qApp->devicePixelRatio()); + m_pixmap = themedPixmapForSpinnerSize(size, m_color, qApp->devicePixelRatio()); +} + +void SpinnerPainter::setColor(const QColor &color) +{ + m_color = color; + m_pixmap = themedPixmapForSpinnerSize(m_size, m_color, qApp->devicePixelRatio()); } void SpinnerPainter::paint(QPainter &painter, const QRect &rect) const { const qreal dpr = painter.device()->devicePixelRatioF(); if (!qFuzzyCompare(m_pixmap.devicePixelRatio(), dpr)) - m_pixmap = themedPixmapForSpinnerSize(m_size, dpr); + m_pixmap = themedPixmapForSpinnerSize(m_size, m_color, dpr); painter.save(); painter.setRenderHint(QPainter::SmoothPixmapTransform); QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); @@ -173,6 +183,11 @@ public: } QSize sizeHint() const final { return m_paint.size(); } + void setColor(const QColor &color) + { + m_paint.setColor(color); + } + protected: void showEvent(QShowEvent *) final { m_paint.startAnimation(); } void hideEvent(QHideEvent *) final { m_paint.stopAnimation(); } @@ -231,6 +246,14 @@ void Spinner::setSize(SpinnerSize size) m_widget->setSize(size); } +/*! + Sets the color of the spinner to the given color. +*/ +void Spinner::setColor(const QColor &color) +{ + m_widget->setColor(color); +} + /*! Shows the animated spinner as an overlay for the parent widget set previously in the constructor. diff --git a/src/libs/solutions/spinner/spinner.h b/src/libs/solutions/spinner/spinner.h index 8ab7cb84d9a..8dd166a8640 100644 --- a/src/libs/solutions/spinner/spinner.h +++ b/src/libs/solutions/spinner/spinner.h @@ -27,6 +27,7 @@ class SPINNER_EXPORT Spinner : public QObject public: explicit Spinner(SpinnerSize size, QWidget *parent = nullptr); void setSize(SpinnerSize size); + void setColor(const QColor &color); void show(); void hide(); bool isVisible() const; diff --git a/src/plugins/screenrecorder/screenrecorderplugin.cpp b/src/plugins/screenrecorder/screenrecorderplugin.cpp index 662e8cc24c3..f0ad0405d33 100644 --- a/src/plugins/screenrecorder/screenrecorderplugin.cpp +++ b/src/plugins/screenrecorder/screenrecorderplugin.cpp @@ -86,6 +86,7 @@ public: }); m_spinner = new SpinnerSolution::Spinner(SpinnerSolution::SpinnerSize::Medium, this); + m_spinner->setColor(creatorTheme()->color(Theme::IconsBaseColor)); m_spinner->hide(); layout()->setSizeConstraint(QLayout::SetFixedSize); diff --git a/tests/manual/spinner/main.cpp b/tests/manual/spinner/main.cpp index ac98284fb8e..6aab09f0c74 100644 --- a/tests/manual/spinner/main.cpp +++ b/tests/manual/spinner/main.cpp @@ -50,6 +50,20 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget) return groupBox; } +QGroupBox *createColorsGroupBox() +{ + QGroupBox *groupBox = new QGroupBox("Spinner::setColor(const QColor &color)"); + auto layout = new QHBoxLayout(groupBox); + for (auto color : {Qt::red, Qt::darkGreen, Qt::blue, Qt::darkYellow}) { + auto widget = new QWidget; + widget->setFixedSize(30, 30); + auto spinner = new Spinner(SpinnerSize::Medium, widget); + spinner->setColor(color); + layout->addWidget(widget); + } + return groupBox; +} + static QWidget *hr() { auto frame = new QFrame; @@ -91,6 +105,8 @@ int main(int argc, char *argv[]) QGroupBox *largeGroupBox = createGroupBox(SpinnerSize::Large, largeWidget); mainLayout->addWidget(largeGroupBox); + mainLayout->addWidget(createColorsGroupBox()); + mainWidget.show(); return app.exec();