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 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.

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();