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 <jaroslaw.kobus@qt.io>
This commit is contained in:
Alessandro Portale
2024-03-14 15:51:39 +01:00
parent 45de53d353
commit e0cf25fb55
4 changed files with 45 additions and 4 deletions

View File

@@ -72,6 +72,8 @@ public:
void setUpdateCallback(const UpdateCallback &cb) { m_callback = cb; } void setUpdateCallback(const UpdateCallback &cb) { m_callback = cb; }
void setColor(const QColor &color);
QSize size() const { return m_pixmap.size() / m_pixmap.devicePixelRatio(); } QSize size() const { return m_pixmap.size() / m_pixmap.devicePixelRatio(); }
void paint(QPainter &painter, const QRect &rect) const; void paint(QPainter &painter, const QRect &rect) const;
void startAnimation() { m_timer.start(); } void startAnimation() { m_timer.start(); }
@@ -87,6 +89,7 @@ private:
QTimer m_timer; QTimer m_timer;
mutable QPixmap m_pixmap; mutable QPixmap m_pixmap;
UpdateCallback m_callback; UpdateCallback m_callback;
QColor m_color;
}; };
static QString imageFileNameForSpinnerSize(SpinnerSize size) static QString imageFileNameForSpinnerSize(SpinnerSize size)
@@ -102,12 +105,12 @@ static QString imageFileNameForSpinnerSize(SpinnerSize size)
return {}; 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)); QImage mask(qt_findAtNxFile(imageFileNameForSpinnerSize(size), dpr));
mask.invertPixels(); mask.invertPixels();
QImage themedImage(mask.size(), QImage::Format_ARGB32); QImage themedImage(mask.size(), QImage::Format_ARGB32);
themedImage.fill(qApp->palette().text().color()); themedImage.fill(color);
themedImage.setAlphaChannel(mask); themedImage.setAlphaChannel(mask);
QPixmap themedPixmap = QPixmap::fromImage(themedImage); QPixmap themedPixmap = QPixmap::fromImage(themedImage);
themedPixmap.setDevicePixelRatio(mask.devicePixelRatio()); themedPixmap.setDevicePixelRatio(mask.devicePixelRatio());
@@ -115,6 +118,7 @@ static QPixmap themedPixmapForSpinnerSize(SpinnerSize size, qreal dpr)
} }
SpinnerPainter::SpinnerPainter(SpinnerSize size) SpinnerPainter::SpinnerPainter(SpinnerSize size)
: m_color(qApp->palette().text().color())
{ {
m_timer.setSingleShot(false); m_timer.setSingleShot(false);
QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] { QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] {
@@ -130,14 +134,20 @@ void SpinnerPainter::setSize(SpinnerSize size)
m_size = size; m_size = size;
m_rotationStep = size == SpinnerSize::Small ? 45 : 30; m_rotationStep = size == SpinnerSize::Small ? 45 : 30;
m_timer.setInterval(size == SpinnerSize::Small ? 100 : 80); 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 void SpinnerPainter::paint(QPainter &painter, const QRect &rect) const
{ {
const qreal dpr = painter.device()->devicePixelRatioF(); const qreal dpr = painter.device()->devicePixelRatioF();
if (!qFuzzyCompare(m_pixmap.devicePixelRatio(), dpr)) if (!qFuzzyCompare(m_pixmap.devicePixelRatio(), dpr))
m_pixmap = themedPixmapForSpinnerSize(m_size, dpr); m_pixmap = themedPixmapForSpinnerSize(m_size, m_color, dpr);
painter.save(); painter.save();
painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::SmoothPixmapTransform);
QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); 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(); } QSize sizeHint() const final { return m_paint.size(); }
void setColor(const QColor &color)
{
m_paint.setColor(color);
}
protected: protected:
void showEvent(QShowEvent *) final { m_paint.startAnimation(); } void showEvent(QShowEvent *) final { m_paint.startAnimation(); }
void hideEvent(QHideEvent *) final { m_paint.stopAnimation(); } void hideEvent(QHideEvent *) final { m_paint.stopAnimation(); }
@@ -231,6 +246,14 @@ void Spinner::setSize(SpinnerSize size)
m_widget->setSize(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 Shows the animated spinner as an overlay for the parent widget
set previously in the constructor. set previously in the constructor.

View File

@@ -27,6 +27,7 @@ class SPINNER_EXPORT Spinner : public QObject
public: public:
explicit Spinner(SpinnerSize size, QWidget *parent = nullptr); explicit Spinner(SpinnerSize size, QWidget *parent = nullptr);
void setSize(SpinnerSize size); void setSize(SpinnerSize size);
void setColor(const QColor &color);
void show(); void show();
void hide(); void hide();
bool isVisible() const; bool isVisible() const;

View File

@@ -86,6 +86,7 @@ public:
}); });
m_spinner = new SpinnerSolution::Spinner(SpinnerSolution::SpinnerSize::Medium, this); m_spinner = new SpinnerSolution::Spinner(SpinnerSolution::SpinnerSize::Medium, this);
m_spinner->setColor(creatorTheme()->color(Theme::IconsBaseColor));
m_spinner->hide(); m_spinner->hide();
layout()->setSizeConstraint(QLayout::SetFixedSize); layout()->setSizeConstraint(QLayout::SetFixedSize);

View File

@@ -50,6 +50,20 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget)
return groupBox; 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() static QWidget *hr()
{ {
auto frame = new QFrame; auto frame = new QFrame;
@@ -91,6 +105,8 @@ int main(int argc, char *argv[])
QGroupBox *largeGroupBox = createGroupBox(SpinnerSize::Large, largeWidget); QGroupBox *largeGroupBox = createGroupBox(SpinnerSize::Large, largeWidget);
mainLayout->addWidget(largeGroupBox); mainLayout->addWidget(largeGroupBox);
mainLayout->addWidget(createColorsGroupBox());
mainWidget.show(); mainWidget.show();
return app.exec(); return app.exec();