qskinny/src/controls/QskProgressBar.cpp

320 lines
7.3 KiB
C++
Raw Normal View History

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 );
setGradientHint( QskProgressBar::Bar | QskAspect::Horizontal, g );
g.setOrientation( Qt::Vertical );
setGradientHint( QskProgressBar::Bar | QskAspect::Vertical, g );
}
void QskProgressBar::resetBarGradient()
{
using namespace QskAspect;
2020-12-15 18:12:48 +01:00
if ( resetColor( Bar | Vertical ) || resetHint( Bar | Horizontal ) )
2020-08-03 08:02:13 +02:00
update();
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-08-01 17:51:45 +02:00
void QskProgressBar::setThickness( qreal thickness )
2020-07-31 16:57:22 +02:00
{
2020-08-01 17:51:45 +02:00
// effectiveSubcontrol( QskProgressBar::Groove ) ???
const auto aspect = QskProgressBar::Groove | QskAspect::Size;
2020-07-31 16:57:22 +02:00
if ( thickness != metric( aspect ) )
{
setMetric( aspect, thickness );
resetImplicitSize();
update();
}
}
2020-08-01 17:51:45 +02:00
qreal QskProgressBar::thickness() const
2020-07-31 16:57:22 +02:00
{
return metric( Groove | QskAspect::Size );
}
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;
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
QSizeF QskProgressBar::contentsSizeHint( Qt::SizeHint which, const QSizeF& ) const
2020-07-31 16:57:22 +02:00
{
if ( which != Qt::PreferredSize )
return QSizeF();
if ( orientation() == Qt::Horizontal )
return QSizeF( -1, thickness() );
else
return QSizeF( thickness(), -1 );
}
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"