From 0890ad05b210a66e843a0ede8e20352ddbd99a2c Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 27 Jan 2024 19:38:09 +0100 Subject: [PATCH] Spinner: Add SpinnerWidget Move it from spinner example and make it a reusable widget. Change-Id: I3d74ec491f5d1cb7d012551f624cff2c618952ca Reviewed-by: hjk --- src/libs/solutions/spinner/spinner.cpp | 93 ++++++++++++++++++++++++-- src/libs/solutions/spinner/spinner.h | 21 +++++- tests/manual/spinner/main.cpp | 78 ++------------------- 3 files changed, 110 insertions(+), 82 deletions(-) diff --git a/src/libs/solutions/spinner/spinner.cpp b/src/libs/solutions/spinner/spinner.cpp index 114fea537da..b56684720bb 100644 --- a/src/libs/solutions/spinner/spinner.cpp +++ b/src/libs/solutions/spinner/spinner.cpp @@ -5,19 +5,21 @@ #include #include +#include #include +#include #include #include #include namespace SpinnerSolution { -class OverlayWidget : public QWidget +class WidgetOverlay : public QWidget { public: using PaintFunction = std::function; - explicit OverlayWidget(QWidget *parent = nullptr) + explicit WidgetOverlay(QWidget *parent = nullptr) { setAttribute(Qt::WA_TransparentForMouseEvents); if (parent) @@ -151,11 +153,11 @@ void SpinnerPainter::paint(QPainter &painter, const QRect &rect) const painter.restore(); } -class SpinnerWidget : public OverlayWidget +class SpinnerOverlay : public WidgetOverlay { public: - explicit SpinnerWidget(SpinnerSize size, QWidget *parent = nullptr) - : OverlayWidget(parent) + explicit SpinnerOverlay(SpinnerSize size, QWidget *parent = nullptr) + : WidgetOverlay(parent) , m_paint(size) { setPaintFunction( @@ -219,7 +221,7 @@ private: */ Spinner::Spinner(SpinnerSize size, QWidget *parent) : QObject(parent) - , m_widget(new SpinnerWidget(size, parent)) {} + , m_widget(new SpinnerOverlay(size, parent)) {} /*! Sets the size of the spinner to the given \a size. @@ -263,4 +265,83 @@ void Spinner::setVisible(bool visible) m_widget->setVisible(visible); } +static QString colorButtonStyleSheet(const QColor &bgColor) +{ + QString rc("border-width: 1px; border-radius: 1px; border-color: black; "); + rc += bgColor.isValid() ? "border-style: solid; background:" + bgColor.name() + ";" + : QString("border-style: dotted;"); + return rc; +} + +static QColor stateToColor(SpinnerState state) +{ + switch (state) { + case SpinnerState::NotRunning: return Qt::gray; + case SpinnerState::Running: return Qt::yellow; + } + return {}; +} + +class SpinnerWidgetPrivate : public QLabel +{ +public: + SpinnerWidgetPrivate(QWidget *parent = nullptr) + : QLabel(parent) + , m_spinner(new Spinner(SpinnerSize::Small, this)) + { + updateState(); + } + + void setState(SpinnerState state) + { + if (m_state == state) + return; + m_state = state; + updateState(); + } + + void setDecorated(bool on) + { + if (m_decorated == on) + return; + m_decorated = on; + updateState(); + } + +private: + void updateState() + { + const int size = m_decorated ? 26 : 24; + setFixedSize(size, size); + setStyleSheet(m_decorated ? colorButtonStyleSheet(stateToColor(m_state)) : QString()); + if (m_state == SpinnerState::Running) + m_spinner->show(); + else + m_spinner->hide(); + } + bool m_decorated = true; + SpinnerState m_state = SpinnerState::NotRunning; + Spinner *m_spinner = nullptr; +}; + +SpinnerWidget::SpinnerWidget(QWidget *parent) + : QWidget(parent) + , d(new SpinnerWidgetPrivate(this)) +{ + QBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(d); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +void SpinnerWidget::setState(SpinnerState state) +{ + d->setState(state); +} + +void SpinnerWidget::setDecorated(bool on) +{ + d->setDecorated(on); +} + } // namespace SpinnerSolution diff --git a/src/libs/solutions/spinner/spinner.h b/src/libs/solutions/spinner/spinner.h index 16ec6bb71db..8ab7cb84d9a 100644 --- a/src/libs/solutions/spinner/spinner.h +++ b/src/libs/solutions/spinner/spinner.h @@ -6,7 +6,7 @@ #include "spinner_global.h" -#include +#include namespace SpinnerSolution { @@ -15,11 +15,15 @@ Q_NAMESPACE_EXPORT(SPINNER_EXPORT) enum class SpinnerSize { Small, Medium, Large }; Q_ENUM_NS(SpinnerSize) +enum class SpinnerState { NotRunning, Running }; +Q_ENUM_NS(SpinnerState) + // TODO: SpinnerOverlay and SpinnerWidget? class SPINNER_EXPORT Spinner : public QObject { Q_OBJECT + public: explicit Spinner(SpinnerSize size, QWidget *parent = nullptr); void setSize(SpinnerSize size); @@ -29,7 +33,20 @@ public: void setVisible(bool visible); private: - class SpinnerWidget *m_widget = nullptr; + class SpinnerOverlay *m_widget = nullptr; +}; + +class SPINNER_EXPORT SpinnerWidget : public QWidget +{ + Q_OBJECT + +public: + explicit SpinnerWidget(QWidget *parent = nullptr); + void setState(SpinnerState state); + void setDecorated(bool on); + +private: + class SpinnerWidgetPrivate *d; }; } // namespace SpinnerSolution diff --git a/tests/manual/spinner/main.cpp b/tests/manual/spinner/main.cpp index 918fd47b356..ac98284fb8e 100644 --- a/tests/manual/spinner/main.cpp +++ b/tests/manual/spinner/main.cpp @@ -14,82 +14,12 @@ using namespace SpinnerSolution; -enum class State { - NotRunning, - Running -}; - -static QString colorButtonStyleSheet(const QColor &bgColor) -{ - QString rc("border-width: 2px; border-radius: 2px; border-color: black; "); - rc += bgColor.isValid() ? "border-style: solid; background:" + bgColor.name() + ";" - : QString("border-style: dotted;"); - return rc; -} - -static QColor stateToColor(State state) -{ - switch (state) { - case State::NotRunning: return Qt::gray; - case State::Running: return Qt::yellow; - } - return {}; -} - -class StateIndicator : public QLabel -{ -public: - StateIndicator(QWidget *parent = nullptr) - : QLabel(parent) - { - setFixedSize(30, 30); - m_spinner = new Spinner(SpinnerSize::Small, this); - m_spinner->hide(); - updateState(); - } - - void setState(State state) - { - if (m_state == state) - return; - m_state = state; - updateState(); - } - -private: - void updateState() - { - setStyleSheet(colorButtonStyleSheet(stateToColor(m_state))); - if (m_state == State::Running) - m_spinner->show(); - else - m_spinner->hide(); - } - State m_state = State::NotRunning; - Spinner *m_spinner = nullptr; -}; - -class StateWidget : public QWidget -{ -public: - StateWidget() : m_stateIndicator(new StateIndicator(this)) { - QBoxLayout *layout = new QHBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(m_stateIndicator); - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - } - void setState(State state) { m_stateIndicator->setState(state); } - -protected: - StateIndicator *m_stateIndicator = nullptr; -}; - QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget) { const QMetaEnum spinnerSize = QMetaEnum::fromType(); QGroupBox *groupBox = new QGroupBox(spinnerSize.valueToKey(int(size))); - StateWidget *stateWidget = new StateWidget; + SpinnerWidget *spinnerWidget = new SpinnerWidget; QToolButton *startButton = new QToolButton; startButton->setText("Start"); QToolButton *stopButton = new QToolButton; @@ -97,7 +27,7 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget) QVBoxLayout *mainLayout = new QVBoxLayout(groupBox); QHBoxLayout *topLayout = new QHBoxLayout(); - topLayout->addWidget(stateWidget); + topLayout->addWidget(spinnerWidget); topLayout->addWidget(startButton); topLayout->addWidget(stopButton); topLayout->addStretch(); @@ -108,12 +38,12 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget) spinner->hide(); // TODO: make the default hidden? QObject::connect(startButton, &QAbstractButton::clicked, groupBox, [=] { - stateWidget->setState(State::Running); + spinnerWidget->setState(SpinnerState::Running); spinner->show(); widget->setEnabled(false); }); QObject::connect(stopButton, &QAbstractButton::clicked, groupBox, [=] { - stateWidget->setState(State::NotRunning); + spinnerWidget->setState(SpinnerState::NotRunning); spinner->hide(); widget->setEnabled(true); });