2020-07-31 16:57:22 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
#include "QskProgressBar.h"
|
2020-07-31 16:57:22 +02:00
|
|
|
|
|
|
|
#include "QskIntervalF.h"
|
|
|
|
#include "QskGradient.h"
|
|
|
|
#include "QskFunctions.h"
|
2020-08-09 10:49:32 +02:00
|
|
|
#include "QskAnimator.h"
|
2020-07-31 16:57:22 +02:00
|
|
|
#include "QskAspect.h"
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QSK_SUBCONTROL( QskProgressBar, Groove )
|
2020-08-03 08:02:13 +02:00
|
|
|
QSK_SUBCONTROL( QskProgressBar, Bar )
|
2020-07-31 16:57:22 +02:00
|
|
|
|
2020-08-09 10:49:32 +02:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
class QskProgressBar::PrivateData
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
public:
|
2020-08-09 10:49:32 +02:00
|
|
|
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;
|
2020-07-31 16:57:22 +02:00
|
|
|
|
2020-08-09 10:49:32 +02:00
|
|
|
qreal value = 0.0;
|
2020-07-31 16:57:22 +02:00
|
|
|
qreal origin = 0.0;
|
2020-08-09 10:49:32 +02:00
|
|
|
|
2020-07-31 16:57:22 +02:00
|
|
|
bool hasOrigin = false;
|
2020-08-09 10:49:32 +02:00
|
|
|
bool isIndeterminate = false;
|
2020-07-31 16:57:22 +02:00
|
|
|
|
|
|
|
Qt::Orientation orientation;
|
|
|
|
};
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::QskProgressBar( Qt::Orientation orientation,
|
2020-07-31 16:57:22 +02:00
|
|
|
qreal min, qreal max, QQuickItem* parent )
|
|
|
|
: QskBoundedControl( min, max, parent )
|
|
|
|
, m_data( new PrivateData )
|
|
|
|
{
|
|
|
|
m_data->orientation = orientation;
|
|
|
|
m_data->value = minimum();
|
|
|
|
|
|
|
|
if ( orientation == Qt::Horizontal )
|
|
|
|
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed );
|
|
|
|
else
|
|
|
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::MinimumExpanding );
|
|
|
|
|
|
|
|
connect( this, &QskBoundedControl::boundariesChanged,
|
2020-08-09 11:50:34 +02:00
|
|
|
this, &QskProgressBar::adjustValue );
|
2020-07-31 16:57:22 +02:00
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::QskProgressBar( Qt::Orientation orientation, QQuickItem* parent )
|
|
|
|
: QskProgressBar( orientation, 0.0, 100.0, parent )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::QskProgressBar( const QskIntervalF& boundaries, QQuickItem* parent )
|
|
|
|
: QskProgressBar( boundaries.lowerBound(), boundaries.upperBound(), parent )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::QskProgressBar( qreal min, qreal max, QQuickItem* parent )
|
|
|
|
: QskProgressBar( Qt::Horizontal, min, max, parent )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::QskProgressBar( QQuickItem* parent )
|
|
|
|
: QskProgressBar( Qt::Horizontal, parent )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskProgressBar::~QskProgressBar()
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
2020-08-09 10:49:32 +02:00
|
|
|
delete m_data->animator;
|
2020-07-31 16:57:22 +02:00
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
Qt::Orientation QskProgressBar::orientation() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
return m_data->orientation;
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::setOrientation( Qt::Orientation orientation )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( orientation != m_data->orientation )
|
|
|
|
{
|
|
|
|
m_data->orientation = orientation;
|
|
|
|
setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) );
|
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT orientationChanged( m_data->orientation );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-09 10:49:32 +02:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
QskAspect::Placement QskProgressBar::effectivePlacement() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
// so you can define different hints depending on the orientation
|
|
|
|
return static_cast< QskAspect::Placement >( m_data->orientation );
|
|
|
|
}
|
|
|
|
|
2020-08-03 08:02:13 +02:00
|
|
|
void QskProgressBar::setBarGradient( const QskGradient& gradient )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
2020-08-03 08:02:13 +02:00
|
|
|
// An API where we set the stops only would be more accurate TODO ...
|
|
|
|
auto g = gradient;
|
|
|
|
|
|
|
|
g.setOrientation( Qt::Horizontal );
|
2020-12-27 16:31:07 +01:00
|
|
|
setGradientHint( Bar | QskAspect::Horizontal, g );
|
2020-08-03 08:02:13 +02:00
|
|
|
|
|
|
|
g.setOrientation( Qt::Vertical );
|
2020-12-27 16:31:07 +01:00
|
|
|
setGradientHint( Bar | QskAspect::Vertical, g );
|
2020-08-03 08:02:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskProgressBar::resetBarGradient()
|
|
|
|
{
|
2020-12-27 16:31:07 +01:00
|
|
|
resetColor( Bar | QskAspect::Vertical );
|
|
|
|
resetColor( Bar | QskAspect::Horizontal );
|
2020-07-31 16:57:22 +02:00
|
|
|
}
|
|
|
|
|
2020-08-03 08:02:13 +02:00
|
|
|
QskGradient QskProgressBar::barGradient() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
2020-08-03 08:02:13 +02:00
|
|
|
return gradientHint( QskProgressBar::Bar );
|
2020-07-31 16:57:22 +02:00
|
|
|
}
|
|
|
|
|
2020-12-17 08:52:30 +01:00
|
|
|
void QskProgressBar::setExtent( qreal extent )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
2020-12-27 16:31:07 +01:00
|
|
|
if ( extent < 0.0 )
|
|
|
|
extent = 0.0;
|
2020-12-17 08:52:30 +01:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
if ( setMetric( Groove | QskAspect::Size, extent ) )
|
2020-12-17 08:52:30 +01:00
|
|
|
Q_EMIT extentChanged( extent );
|
2020-07-31 16:57:22 +02:00
|
|
|
}
|
|
|
|
|
2020-12-17 08:52:30 +01:00
|
|
|
void QskProgressBar::resetExtent()
|
|
|
|
{
|
|
|
|
if ( resetMetric( Groove | QskAspect::Size ) )
|
|
|
|
Q_EMIT extentChanged( extent() );
|
2020-12-27 16:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskProgressBar::extent() const
|
|
|
|
{
|
|
|
|
return metric( Groove | QskAspect::Size );
|
2020-12-17 08:52:30 +01:00
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::setOrigin( qreal origin )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::resetOrigin()
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( m_data->hasOrigin )
|
|
|
|
{
|
|
|
|
m_data->hasOrigin = false;
|
2020-12-27 16:31:07 +01:00
|
|
|
|
2020-07-31 16:57:22 +02:00
|
|
|
update();
|
|
|
|
Q_EMIT originChanged( origin() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
qreal QskProgressBar::origin() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( m_data->hasOrigin )
|
|
|
|
{
|
|
|
|
return boundedValue( m_data->origin );
|
|
|
|
}
|
|
|
|
|
|
|
|
return minimum();
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::setValue( qreal value )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( isComponentComplete() )
|
|
|
|
value = boundedValue( value );
|
|
|
|
|
|
|
|
setValueInternal( value );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
qreal QskProgressBar::value() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
return m_data->value;
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::setValueAsRatio( qreal ratio )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
ratio = qBound( 0.0, ratio, 1.0 );
|
|
|
|
setValue( minimum() + ratio * boundaryLength() );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
qreal QskProgressBar::valueAsRatio() const
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
return valueAsRatio( m_data->value );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::componentComplete()
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
Inherited::componentComplete();
|
|
|
|
adjustValue();
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::adjustValue()
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( isComponentComplete() )
|
|
|
|
setValueInternal( boundedValue( m_data->value ) );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
void QskProgressBar::setValueInternal( qreal value )
|
2020-07-31 16:57:22 +02:00
|
|
|
{
|
|
|
|
if ( !qskFuzzyCompare( value, m_data->value ) )
|
|
|
|
{
|
|
|
|
m_data->value = value;
|
|
|
|
Q_EMIT valueChanged( value );
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-09 10:49:32 +02:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:51:45 +02:00
|
|
|
#include "moc_QskProgressBar.cpp"
|