diff --git a/src/controls/QskProgressBar.cpp b/src/controls/QskProgressBar.cpp index 638bf5e6..fe00c77b 100644 --- a/src/controls/QskProgressBar.cpp +++ b/src/controls/QskProgressBar.cpp @@ -8,18 +8,73 @@ #include "QskIntervalF.h" #include "QskGradient.h" #include "QskFunctions.h" +#include "QskAnimator.h" #include "QskAspect.h" QSK_SUBCONTROL( QskProgressBar, Groove ) QSK_SUBCONTROL( QskProgressBar, Bar ) +namespace +{ + class PositionAnimator : public QskAnimator + { + public: + PositionAnimator( QskProgressBar* progressBar ) + : m_progressBar( progressBar ) + { + setAutoRepeat( true ); + setDuration( 1300 ); + + setWindow( progressBar->window() ); + } + + void advance( qreal value ) override + { + const auto aspect = QskProgressBar::Bar | QskAspect::Position; + + m_progressBar->setMetric( aspect, value ); + m_progressBar->update(); + } + + private: + QskProgressBar* m_progressBar; + }; +} + class QskProgressBar::PrivateData { public: - qreal value = 0.0; + void updateIndeterminateAnimator( QskProgressBar* progressBar ) + { + if ( !isIndeterminate ) + { + delete animator; + animator = nullptr; + return; + } + + if ( progressBar->window() && progressBar->isVisible() ) + { + if ( animator == nullptr ) + animator = new PositionAnimator( progressBar ); + + animator->start(); + } + else + { + if ( animator ) + animator->stop(); + } + } + + PositionAnimator* animator = nullptr; + + qreal value = 0.0; qreal origin = 0.0; + bool hasOrigin = false; + bool isIndeterminate = false; Qt::Orientation orientation; }; @@ -63,6 +118,7 @@ QskProgressBar::QskProgressBar( QQuickItem* parent ) QskProgressBar::~QskProgressBar() { + delete m_data->animator; } Qt::Orientation QskProgressBar::orientation() const @@ -84,6 +140,23 @@ void QskProgressBar::setOrientation( Qt::Orientation orientation ) } } +bool QskProgressBar::isIndeterminate() const +{ + return m_data->isIndeterminate; +} + +void QskProgressBar::setIndeterminate( bool on ) +{ + if ( on == m_data->isIndeterminate ) + return; + + m_data->isIndeterminate = on; + m_data->updateIndeterminateAnimator( this ); + + update(); + Q_EMIT indeterminateChanged( on ); +} + QskAspect::Placement QskProgressBar::effectivePlacement() const { // so you can define different hints depending on the orientation @@ -228,4 +301,20 @@ void QskProgressBar::setValueInternal( qreal value ) } } +void QskProgressBar::itemChange( QQuickItem::ItemChange change, + const QQuickItem::ItemChangeData& value ) +{ + switch( static_cast< int >( change ) ) + { + case QQuickItem::ItemVisibleHasChanged: + case QQuickItem::ItemSceneChange: + { + m_data->updateIndeterminateAnimator( this ); + break; + } + } + + Inherited::itemChange( change, value ); +} + #include "moc_QskProgressBar.cpp" diff --git a/src/controls/QskProgressBar.h b/src/controls/QskProgressBar.h index 5df98e58..4fe72504 100644 --- a/src/controls/QskProgressBar.h +++ b/src/controls/QskProgressBar.h @@ -17,6 +17,9 @@ class QSK_EXPORT QskProgressBar : public QskBoundedControl Q_PROPERTY( Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged ) + Q_PROPERTY( bool indeterminate READ isIndeterminate + WRITE setIndeterminate NOTIFY indeterminateChanged ) + Q_PROPERTY( qreal origin READ origin WRITE setOrigin RESET resetOrigin NOTIFY originChanged ) @@ -40,6 +43,9 @@ class QSK_EXPORT QskProgressBar : public QskBoundedControl Qt::Orientation orientation() const; void setOrientation( Qt::Orientation orientation ); + bool isIndeterminate() const; + void setIndeterminate( bool on = true ); + QskAspect::Placement effectivePlacement() const override; void setBarGradient( const QskGradient & ); @@ -63,12 +69,14 @@ class QSK_EXPORT QskProgressBar : public QskBoundedControl Q_SIGNALS: void orientationChanged( Qt::Orientation ); + void indeterminateChanged( bool ); void valueChanged( qreal ); void originChanged( qreal ); protected: QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override; void componentComplete() override; + void itemChange( ItemChange, const ItemChangeData& ) override; private: void setValueInternal( qreal value ); diff --git a/src/controls/QskProgressBarSkinlet.cpp b/src/controls/QskProgressBarSkinlet.cpp index 8d3770b5..856bb2e1 100644 --- a/src/controls/QskProgressBarSkinlet.cpp +++ b/src/controls/QskProgressBarSkinlet.cpp @@ -8,12 +8,29 @@ #include "QskIntervalF.h" #include "QskBoxBorderMetrics.h" +#include #include static inline QskIntervalF qskBarInterval( const QskProgressBar* bar ) { - auto pos1 = bar->valueAsRatio( bar->origin() ); - auto pos2 = bar->valueAsRatio( bar->value() ); + qreal pos1, pos2; + + if ( bar->isIndeterminate() ) + { + const auto pos = bar->metric( QskProgressBar::Bar | QskAspect::Position ); + + static const QEasingCurve curve( QEasingCurve::InOutCubic ); + + const qreal off = 0.15; + + pos1 = curve.valueForProgress( qMax( pos - off, 0.0 ) ); + pos2 = curve.valueForProgress( qMin( pos + off, 1.0 ) ); + } + else + { + pos1 = bar->valueAsRatio( bar->origin() ); + pos2 = bar->valueAsRatio( bar->value() ); + } if( bar->orientation() == Qt::Horizontal ) {