forked from qt-creator/qt-creator
Spinner: Add SpinnerWidget
Move it from spinner example and make it a reusable widget. Change-Id: I3d74ec491f5d1cb7d012551f624cff2c618952ca Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -5,19 +5,21 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <QLabel>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
namespace SpinnerSolution {
|
namespace SpinnerSolution {
|
||||||
|
|
||||||
class OverlayWidget : public QWidget
|
class WidgetOverlay : public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using PaintFunction = std::function<void(QWidget *, QPainter &, QPaintEvent *)>;
|
using PaintFunction = std::function<void(QWidget *, QPainter &, QPaintEvent *)>;
|
||||||
|
|
||||||
explicit OverlayWidget(QWidget *parent = nullptr)
|
explicit WidgetOverlay(QWidget *parent = nullptr)
|
||||||
{
|
{
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
if (parent)
|
if (parent)
|
||||||
@@ -151,11 +153,11 @@ void SpinnerPainter::paint(QPainter &painter, const QRect &rect) const
|
|||||||
painter.restore();
|
painter.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpinnerWidget : public OverlayWidget
|
class SpinnerOverlay : public WidgetOverlay
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SpinnerWidget(SpinnerSize size, QWidget *parent = nullptr)
|
explicit SpinnerOverlay(SpinnerSize size, QWidget *parent = nullptr)
|
||||||
: OverlayWidget(parent)
|
: WidgetOverlay(parent)
|
||||||
, m_paint(size)
|
, m_paint(size)
|
||||||
{
|
{
|
||||||
setPaintFunction(
|
setPaintFunction(
|
||||||
@@ -219,7 +221,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
Spinner::Spinner(SpinnerSize size, QWidget *parent)
|
Spinner::Spinner(SpinnerSize size, QWidget *parent)
|
||||||
: QObject(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.
|
Sets the size of the spinner to the given \a size.
|
||||||
@@ -263,4 +265,83 @@ void Spinner::setVisible(bool visible)
|
|||||||
m_widget->setVisible(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
|
} // namespace SpinnerSolution
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "spinner_global.h"
|
#include "spinner_global.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QWidget>
|
||||||
|
|
||||||
namespace SpinnerSolution {
|
namespace SpinnerSolution {
|
||||||
|
|
||||||
@@ -15,11 +15,15 @@ Q_NAMESPACE_EXPORT(SPINNER_EXPORT)
|
|||||||
enum class SpinnerSize { Small, Medium, Large };
|
enum class SpinnerSize { Small, Medium, Large };
|
||||||
Q_ENUM_NS(SpinnerSize)
|
Q_ENUM_NS(SpinnerSize)
|
||||||
|
|
||||||
|
enum class SpinnerState { NotRunning, Running };
|
||||||
|
Q_ENUM_NS(SpinnerState)
|
||||||
|
|
||||||
// TODO: SpinnerOverlay and SpinnerWidget?
|
// TODO: SpinnerOverlay and SpinnerWidget?
|
||||||
|
|
||||||
class SPINNER_EXPORT Spinner : public QObject
|
class SPINNER_EXPORT Spinner : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Spinner(SpinnerSize size, QWidget *parent = nullptr);
|
explicit Spinner(SpinnerSize size, QWidget *parent = nullptr);
|
||||||
void setSize(SpinnerSize size);
|
void setSize(SpinnerSize size);
|
||||||
@@ -29,7 +33,20 @@ public:
|
|||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
|
|
||||||
private:
|
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
|
} // namespace SpinnerSolution
|
||||||
|
@@ -14,82 +14,12 @@
|
|||||||
|
|
||||||
using namespace SpinnerSolution;
|
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)
|
QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget)
|
||||||
{
|
{
|
||||||
const QMetaEnum spinnerSize = QMetaEnum::fromType<SpinnerSize>();
|
const QMetaEnum spinnerSize = QMetaEnum::fromType<SpinnerSize>();
|
||||||
QGroupBox *groupBox = new QGroupBox(spinnerSize.valueToKey(int(size)));
|
QGroupBox *groupBox = new QGroupBox(spinnerSize.valueToKey(int(size)));
|
||||||
|
|
||||||
StateWidget *stateWidget = new StateWidget;
|
SpinnerWidget *spinnerWidget = new SpinnerWidget;
|
||||||
QToolButton *startButton = new QToolButton;
|
QToolButton *startButton = new QToolButton;
|
||||||
startButton->setText("Start");
|
startButton->setText("Start");
|
||||||
QToolButton *stopButton = new QToolButton;
|
QToolButton *stopButton = new QToolButton;
|
||||||
@@ -97,7 +27,7 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget)
|
|||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout(groupBox);
|
QVBoxLayout *mainLayout = new QVBoxLayout(groupBox);
|
||||||
QHBoxLayout *topLayout = new QHBoxLayout();
|
QHBoxLayout *topLayout = new QHBoxLayout();
|
||||||
topLayout->addWidget(stateWidget);
|
topLayout->addWidget(spinnerWidget);
|
||||||
topLayout->addWidget(startButton);
|
topLayout->addWidget(startButton);
|
||||||
topLayout->addWidget(stopButton);
|
topLayout->addWidget(stopButton);
|
||||||
topLayout->addStretch();
|
topLayout->addStretch();
|
||||||
@@ -108,12 +38,12 @@ QGroupBox *createGroupBox(SpinnerSize size, QWidget *widget)
|
|||||||
spinner->hide(); // TODO: make the default hidden?
|
spinner->hide(); // TODO: make the default hidden?
|
||||||
|
|
||||||
QObject::connect(startButton, &QAbstractButton::clicked, groupBox, [=] {
|
QObject::connect(startButton, &QAbstractButton::clicked, groupBox, [=] {
|
||||||
stateWidget->setState(State::Running);
|
spinnerWidget->setState(SpinnerState::Running);
|
||||||
spinner->show();
|
spinner->show();
|
||||||
widget->setEnabled(false);
|
widget->setEnabled(false);
|
||||||
});
|
});
|
||||||
QObject::connect(stopButton, &QAbstractButton::clicked, groupBox, [=] {
|
QObject::connect(stopButton, &QAbstractButton::clicked, groupBox, [=] {
|
||||||
stateWidget->setState(State::NotRunning);
|
spinnerWidget->setState(SpinnerState::NotRunning);
|
||||||
spinner->hide();
|
spinner->hide();
|
||||||
widget->setEnabled(true);
|
widget->setEnabled(true);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user