b89621a3d4
* add QskArcNode and QskArcRenderer * IOT example: Use QskArcNode instead of own arc node * move some functionality to the arc renderer * add QskArcMetrics * add methods to QskSkinlet * remove circular bar graph node We can now use updateArcNode() and don't need our own method. * support linear gradients in the arc renderer * clean up * incorporate Uwe's changes * add overloads for updateArcNode() when the angles are set dynamically The angles don't always come from the style, so we need overloads in QskSkinlet to set them dynamically.
197 lines
4.3 KiB
C++
197 lines
4.3 KiB
C++
/******************************************************************************
|
|
* Copyright (C) 2021 Edelhirsch Software GmbH
|
|
* This file may be used under the terms of the 3-clause BSD License
|
|
*****************************************************************************/
|
|
|
|
#include "CircularProgressBar.h"
|
|
|
|
#include <QskAnimator.h>
|
|
#include <QskArcMetrics.h>
|
|
#include <QskFunctions.h>
|
|
|
|
QSK_SUBCONTROL( CircularProgressBar, Groove )
|
|
QSK_SUBCONTROL( CircularProgressBar, Bar )
|
|
|
|
namespace
|
|
{
|
|
class PositionAnimator : public QskAnimator
|
|
{
|
|
public:
|
|
PositionAnimator( CircularProgressBar* progressBar )
|
|
: m_progressBar( progressBar )
|
|
{
|
|
setAutoRepeat( true );
|
|
setDuration( 1300 );
|
|
|
|
setWindow( progressBar->window() );
|
|
}
|
|
|
|
void advance( qreal value ) override
|
|
{
|
|
const auto aspect = CircularProgressBar::Bar | QskAspect::Position;
|
|
|
|
m_progressBar->setMetric( aspect, value );
|
|
m_progressBar->update();
|
|
}
|
|
|
|
private:
|
|
CircularProgressBar* m_progressBar;
|
|
};
|
|
}
|
|
|
|
class CircularProgressBar::PrivateData
|
|
{
|
|
public:
|
|
void updateIndeterminateAnimator( CircularProgressBar* 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;
|
|
};
|
|
|
|
CircularProgressBar::CircularProgressBar( qreal min, qreal max, QQuickItem* parent )
|
|
: QskBoundedControl( min, max, parent )
|
|
, m_data( new PrivateData )
|
|
{
|
|
m_data->value = minimum();
|
|
|
|
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding );
|
|
|
|
connect( this, &QskBoundedControl::boundariesChanged,
|
|
this, &CircularProgressBar::adjustValue );
|
|
}
|
|
|
|
CircularProgressBar::CircularProgressBar( QQuickItem* parent )
|
|
: CircularProgressBar( 0.0, 100.0, parent )
|
|
{
|
|
}
|
|
|
|
bool CircularProgressBar::isIndeterminate() const
|
|
{
|
|
return m_data->isIndeterminate;
|
|
}
|
|
|
|
void CircularProgressBar::setIndeterminate( bool on )
|
|
{
|
|
if ( on == m_data->isIndeterminate )
|
|
return;
|
|
|
|
m_data->isIndeterminate = on;
|
|
m_data->updateIndeterminateAnimator( this );
|
|
|
|
update();
|
|
Q_EMIT indeterminateChanged( on );
|
|
}
|
|
|
|
void CircularProgressBar::resetOrigin()
|
|
{
|
|
if ( m_data->hasOrigin )
|
|
{
|
|
m_data->hasOrigin = false;
|
|
|
|
update();
|
|
Q_EMIT originChanged( origin() );
|
|
}
|
|
}
|
|
|
|
qreal CircularProgressBar::origin() const
|
|
{
|
|
if ( m_data->hasOrigin )
|
|
{
|
|
return boundedValue( m_data->origin );
|
|
}
|
|
|
|
return minimum();
|
|
}
|
|
|
|
qreal CircularProgressBar::value() const
|
|
{
|
|
return m_data->value;
|
|
}
|
|
|
|
qreal CircularProgressBar::valueAsRatio() const
|
|
{
|
|
return QskBoundedControl::valueAsRatio( m_data->value );
|
|
}
|
|
|
|
void CircularProgressBar::setValue( qreal value )
|
|
{
|
|
if ( isComponentComplete() )
|
|
value = boundedValue( value );
|
|
|
|
setValueInternal( value );
|
|
}
|
|
|
|
void CircularProgressBar::setValueAsRatio( qreal ratio )
|
|
{
|
|
ratio = qBound( 0.0, ratio, 1.0 );
|
|
setValue( minimum() + ratio * boundaryLength() );
|
|
}
|
|
|
|
void CircularProgressBar::setOrigin( qreal origin )
|
|
{
|
|
if ( isComponentComplete() )
|
|
origin = boundedValue( origin );
|
|
|
|
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
|
|
{
|
|
m_data->hasOrigin = true;
|
|
m_data->origin = origin;
|
|
|
|
update();
|
|
Q_EMIT originChanged( origin );
|
|
}
|
|
}
|
|
|
|
void CircularProgressBar::componentComplete()
|
|
{
|
|
Inherited::componentComplete();
|
|
adjustValue();
|
|
}
|
|
|
|
void CircularProgressBar::setValueInternal( qreal value )
|
|
{
|
|
if ( !qskFuzzyCompare( value, m_data->value ) )
|
|
{
|
|
m_data->value = value;
|
|
|
|
Q_EMIT valueChanged( value );
|
|
|
|
update();
|
|
}
|
|
}
|
|
|
|
void CircularProgressBar::adjustValue()
|
|
{
|
|
if ( isComponentComplete() )
|
|
setValueInternal( boundedValue( m_data->value ) );
|
|
}
|
|
|
|
#include "moc_CircularProgressBar.cpp"
|