diff --git a/components/circularprogress.cpp b/components/circularprogress.cpp index b0145d4..3f1cf79 100644 --- a/components/circularprogress.cpp +++ b/components/circularprogress.cpp @@ -1,9 +1,18 @@ #include "circularprogress.h" #include +#include +#include +#include #include "circularprogress_p.h" +#include "circularprogress_internal.h" +#include "lib/style.h" CircularProgressPrivate::CircularProgressPrivate(CircularProgress *q) - : q_ptr(q) + : q_ptr(q), + size(64), + angle(0), + penWidth(6.25), + useThemeColors(true) { } @@ -13,10 +22,51 @@ CircularProgressPrivate::~CircularProgressPrivate() void CircularProgressPrivate::init() { + Q_Q(CircularProgress); + + delegate = new CircularProgressDelegate(q); + + QSizePolicy policy(QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding); + q->setSizePolicy(policy); + q->startTimer(4); + + QParallelAnimationGroup *group = new QParallelAnimationGroup(q); + group->setLoopCount(-1); + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(q); + animation->setPropertyName("dashLength"); + animation->setTargetObject(delegate); + animation->setEasingCurve(QEasingCurve::InOutQuad); + animation->setStartValue(0.1); + animation->setKeyValueAt(0.15, 0.2); + animation->setKeyValueAt(0.6, 20); + animation->setKeyValueAt(0.7, 20); + animation->setEndValue(20); + animation->setDuration(2050); + + group->addAnimation(animation); + + animation = new QPropertyAnimation(q); + animation->setPropertyName("dashOffset"); + animation->setTargetObject(delegate); + animation->setEasingCurve(QEasingCurve::InOutSine); + animation->setStartValue(0); + animation->setKeyValueAt(0.15, 0); + animation->setKeyValueAt(0.6, -7); + animation->setKeyValueAt(0.7, -7); + animation->setEndValue(-25); + animation->setDuration(2050); + + group->addAnimation(animation); + + group->start(); } CircularProgress::CircularProgress(QWidget *parent) - : QWidget(parent), + : QProgressBar(parent), d_ptr(new CircularProgressPrivate(this)) { d_func()->init(); @@ -26,9 +76,134 @@ CircularProgress::~CircularProgress() { } +void CircularProgress::setProgressType(Material::ProgressType type) +{ + Q_D(CircularProgress); + + d->progressType = type; + update(); +} + +Material::ProgressType CircularProgress::progressType() const +{ + Q_D(const CircularProgress); + + return d->progressType; +} + + +void CircularProgress::setUseThemeColors(bool state) +{ + Q_D(CircularProgress); + + d->useThemeColors = state; + update(); +} + +bool CircularProgress::useThemeColors() const +{ + Q_D(const CircularProgress); + + return d->useThemeColors; +} + + +void CircularProgress::setLineWidth(qreal width) +{ + Q_D(CircularProgress); + + d->penWidth = width; + update(); +} + +qreal CircularProgress::lineWidth() const +{ + Q_D(const CircularProgress); + + return d->penWidth; +} + +void CircularProgress::setSize(int size) +{ + Q_D(CircularProgress); + + d->size = size; + update(); +} + +int CircularProgress::size() const +{ + Q_D(const CircularProgress); + + return d->size; +} + +void CircularProgress::setColor(const QColor &color) +{ + Q_D(CircularProgress); + + d->color = color; + setUseThemeColors(false); +} + +QColor CircularProgress::color() const +{ + Q_D(const CircularProgress); + + if (d->useThemeColors || !d->color.isValid()) { + return Style::instance().themeColor("primary1"); + } else { + return d->color; + } + return d->color; +} + +QSize CircularProgress::sizeHint() const +{ + Q_D(const CircularProgress); + + const qreal s = d->size+d->penWidth+8; + return QSize(s, s); +} + void CircularProgress::paintEvent(QPaintEvent *event) { + Q_UNUSED(event) + + Q_D(CircularProgress); + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); painter.drawRect(rect()); + + painter.translate(width()/2, height()/2); + painter.rotate(d->angle); + + QPen pen; + pen.setCapStyle(Qt::RoundCap); + pen.setWidthF(d->penWidth); + pen.setColor(color()); + + QVector pattern; + pattern << d->delegate->dashLength()*d->size/50 << 30*d->size/50; + + pen.setDashOffset(d->delegate->dashOffset()*d->size/50); + pen.setDashPattern(pattern); + + painter.setPen(pen); + + painter.drawEllipse(QPoint(0, 0), d->size/2, d->size/2); +} + +void CircularProgress::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event) + + Q_D(CircularProgress); + + if (++d->angle > 360) { + d->angle -= 360; + } + update(); } diff --git a/components/circularprogress.h b/components/circularprogress.h index dd7754e..1472881 100644 --- a/components/circularprogress.h +++ b/components/circularprogress.h @@ -1,20 +1,43 @@ #ifndef CIRCULAR_PROGRESS_H #define CIRCULAR_PROGRESS_H -#include +#include +#include "lib/theme.h" class CircularProgressPrivate; -class CircularProgress : public QWidget +class CircularProgress : public QProgressBar { Q_OBJECT + Q_PROPERTY(qreal lineWidth WRITE setLineWidth READ lineWidth) + Q_PROPERTY(qreal size WRITE setSize READ size) + Q_PROPERTY(QColor color WRITE setColor READ color) + public: explicit CircularProgress(QWidget *parent = 0); ~CircularProgress(); + void setProgressType(Material::ProgressType type); + Material::ProgressType progressType() const; + + void setUseThemeColors(bool state); + bool useThemeColors() const; + + void setLineWidth(qreal width); + qreal lineWidth() const; + + void setSize(int size); + int size() const; + + void setColor(const QColor &color); + QColor color() const; + + QSize sizeHint() const; + protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; const QScopedPointer d_ptr; diff --git a/components/circularprogress_internal.cpp b/components/circularprogress_internal.cpp index e69de29..263f8e4 100644 --- a/components/circularprogress_internal.cpp +++ b/components/circularprogress_internal.cpp @@ -0,0 +1,35 @@ +#include "circularprogress_internal.h" +#include "circularprogress.h" + +CircularProgressDelegate::CircularProgressDelegate(CircularProgress *parent) + : progress(parent), + _dashOffset(0), + _dashLength(89) +{ +} + +CircularProgressDelegate::~CircularProgressDelegate() +{ +} + +void CircularProgressDelegate::setDashOffset(qreal offset) +{ + _dashOffset = offset; + progress->update(); +} + +qreal CircularProgressDelegate::dashOffset() const +{ + return _dashOffset; +} + +void CircularProgressDelegate::setDashLength(qreal value) +{ + _dashLength = value; + progress->update(); +} + +qreal CircularProgressDelegate::dashLength() const +{ + return _dashLength; +} diff --git a/components/circularprogress_internal.h b/components/circularprogress_internal.h index 37f559d..363019e 100644 --- a/components/circularprogress_internal.h +++ b/components/circularprogress_internal.h @@ -1,4 +1,33 @@ #ifndef CIRCULARPROGRESS_INTERNAL_H #define CIRCULARPROGRESS_INTERNAL_H +#include + +class CircularProgress; + +class CircularProgressDelegate : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal dashOffset WRITE setDashOffset READ dashOffset) + Q_PROPERTY(qreal dashLength WRITE setDashLength READ dashLength) + +public: + CircularProgressDelegate(CircularProgress *parent = 0); + ~CircularProgressDelegate(); + + void setDashOffset(qreal offset); + qreal dashOffset() const; + + void setDashLength(qreal value); + qreal dashLength() const; + +private: + Q_DISABLE_COPY(CircularProgressDelegate) + + CircularProgress *const progress; + qreal _dashOffset; + qreal _dashLength; +}; + #endif // CIRCULARPROGRESS_INTERNAL_H diff --git a/components/circularprogress_p.h b/components/circularprogress_p.h index a312cbe..d7387a6 100644 --- a/components/circularprogress_p.h +++ b/components/circularprogress_p.h @@ -2,8 +2,10 @@ #define CIRCULARPROGRESS_P_H #include +#include "lib/theme.h" class CircularProgress; +class CircularProgressDelegate; class CircularProgressPrivate { @@ -17,6 +19,13 @@ public: void init(); CircularProgress *const q_ptr; + CircularProgressDelegate *delegate; + Material::ProgressType progressType; + int size; + int angle; + qreal penWidth; + QColor color; + bool useThemeColors; }; #endif // CIRCULARPROGRESS_P_H