From 16dcddd0f23e6935856c7c93a18b4fb6e5ffc3c8 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 4 Sep 2024 15:46:33 +0200 Subject: [PATCH 1/6] unused code/definitions removed --- examples/iotdashboard/DashboardPage.cpp | 11 ----------- examples/iotdashboard/LightDisplay.cpp | 11 ----------- examples/iotdashboard/LightDisplay.h | 9 --------- examples/iotdashboard/Skin.h | 1 - examples/iotdashboard/TopBar.cpp | 4 ++-- 5 files changed, 2 insertions(+), 34 deletions(-) diff --git a/examples/iotdashboard/DashboardPage.cpp b/examples/iotdashboard/DashboardPage.cpp index a91291bf..3c7f5028 100644 --- a/examples/iotdashboard/DashboardPage.cpp +++ b/examples/iotdashboard/DashboardPage.cpp @@ -14,17 +14,6 @@ #include "TopBar.h" #include "UsageBox.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include - QSK_SUBCONTROL( DashboardPage, Panel ) namespace diff --git a/examples/iotdashboard/LightDisplay.cpp b/examples/iotdashboard/LightDisplay.cpp index 9f305b51..8ef43ea3 100644 --- a/examples/iotdashboard/LightDisplay.cpp +++ b/examples/iotdashboard/LightDisplay.cpp @@ -51,17 +51,6 @@ bool LightDisplay::isPressed() const return hasSkinState( Pressed ); } -void LightDisplay::setGradient( const QskGradient& gradient ) -{ - m_gradient = gradient; - update(); -} - -const QskGradient& LightDisplay::gradient() const -{ - return m_gradient; -} - void LightDisplay::mousePressEvent( QMouseEvent* event ) { QRectF handleRect = subControlRect( LightDisplay::Knob ); diff --git a/examples/iotdashboard/LightDisplay.h b/examples/iotdashboard/LightDisplay.h index bddd5f47..8c7728a5 100644 --- a/examples/iotdashboard/LightDisplay.h +++ b/examples/iotdashboard/LightDisplay.h @@ -6,7 +6,6 @@ #pragma once #include -#include #include class LightDisplay : public QskBoundedValueInput @@ -22,9 +21,6 @@ class LightDisplay : public QskBoundedValueInput bool isPressed() const; - void setGradient( const QskGradient& ); - const QskGradient& gradient() const; - protected: void mousePressEvent( QMouseEvent* e ) override; void mouseMoveEvent( QMouseEvent* e ) override; @@ -33,9 +29,4 @@ class LightDisplay : public QskBoundedValueInput private: qreal angleFromPoint( const QRectF&, const QPointF& ) const; bool arcContainsPoint( const QRectF&, const QPointF& ) const; - - QskShadowMetrics m_shadow; - QColor m_shadowColor = Qt::black; - - QskGradient m_gradient; }; diff --git a/examples/iotdashboard/Skin.h b/examples/iotdashboard/Skin.h index 1b2cd7f1..1a06c446 100644 --- a/examples/iotdashboard/Skin.h +++ b/examples/iotdashboard/Skin.h @@ -34,5 +34,4 @@ class Skin : public QskSkin void initHints() override; Palette palette( ColorScheme ) const; - void initHints( const Palette& ); }; diff --git a/examples/iotdashboard/TopBar.cpp b/examples/iotdashboard/TopBar.cpp index 9deb9089..31b6d932 100644 --- a/examples/iotdashboard/TopBar.cpp +++ b/examples/iotdashboard/TopBar.cpp @@ -62,9 +62,9 @@ TopBarItem::TopBarItem( const auto subcontrol = subcontrolForIndex( index ); const auto textColor = color( subcontrol | QskAspect::TextColor ); - auto pieChart = new EnergyMeter( + auto meter = new EnergyMeter( textColor, gradient, progress, pieChartAndDisplay ); - pieChart->setSizePolicy( Qt::Horizontal, QskSizePolicy::Constrained ); + meter->setSizePolicy( Qt::Horizontal, QskSizePolicy::Constrained ); auto display = new QskLinearBox( Qt::Vertical, pieChartAndDisplay ); display->setSpacing( 0 ); From 11df0bb694a29324164e85e9372fd85ffb95af1e Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 4 Sep 2024 16:30:05 +0200 Subject: [PATCH 2/6] code duplication eliminated --- examples/iotdashboard/CircularProgressBar.cpp | 180 +----------------- examples/iotdashboard/CircularProgressBar.h | 48 +---- .../CircularProgressBarSkinlet.cpp | 2 +- examples/iotdashboard/EnergyMeter.cpp | 2 +- examples/iotdashboard/Skin.cpp | 2 +- examples/iotdashboard/StorageMeter.cpp | 2 +- 6 files changed, 9 insertions(+), 227 deletions(-) diff --git a/examples/iotdashboard/CircularProgressBar.cpp b/examples/iotdashboard/CircularProgressBar.cpp index 479c5668..8bb873ab 100644 --- a/examples/iotdashboard/CircularProgressBar.cpp +++ b/examples/iotdashboard/CircularProgressBar.cpp @@ -5,87 +5,10 @@ #include "CircularProgressBar.h" -#include -#include - -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() = default; - CircularProgressBar::CircularProgressBar( qreal min, qreal max, QQuickItem* parent ) - : QskBoundedControl( min, max, parent ) - , m_data( new PrivateData ) + : Inherited( min, max, parent ) { - m_data->value = minimum(); - initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding ); - - connect( this, &QskBoundedControl::boundariesChanged, - this, &CircularProgressBar::adjustValue ); } CircularProgressBar::CircularProgressBar( QQuickItem* parent ) @@ -93,105 +16,4 @@ CircularProgressBar::CircularProgressBar( QQuickItem* 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" diff --git a/examples/iotdashboard/CircularProgressBar.h b/examples/iotdashboard/CircularProgressBar.h index 9cd84898..67359722 100644 --- a/examples/iotdashboard/CircularProgressBar.h +++ b/examples/iotdashboard/CircularProgressBar.h @@ -5,57 +5,17 @@ #pragma once -#include +#include -class CircularProgressBar : public QskBoundedControl +class CircularProgressBar : public QskProgressIndicator { Q_OBJECT - Q_PROPERTY( bool indeterminate READ isIndeterminate - WRITE setIndeterminate NOTIFY indeterminateChanged ) - - Q_PROPERTY( qreal origin READ origin - WRITE setOrigin RESET resetOrigin NOTIFY originChanged ) - - Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged ) - Q_PROPERTY( qreal valueAsRatio READ valueAsRatio - WRITE setValueAsRatio NOTIFY valueChanged ) - - using Inherited = QskBoundedControl; + using Inherited = QskProgressIndicator; public: - QSK_SUBCONTROLS( Groove, Bar ) - CircularProgressBar( qreal min, qreal max, QQuickItem* parent = nullptr ); CircularProgressBar( QQuickItem* parent = nullptr ); - ~CircularProgressBar() override; - bool isIndeterminate() const; - void setIndeterminate( bool on = true ); - - void resetOrigin(); - qreal origin() const; - - qreal value() const; - qreal valueAsRatio() const; // [0.0, 1.0] - - public Q_SLOTS: - void setValue( qreal ); - void setValueAsRatio( qreal ); - void setOrigin( qreal ); - - Q_SIGNALS: - void indeterminateChanged( bool ); - void valueChanged( qreal ); - void originChanged( qreal ); - - protected: - void componentComplete() override; - - private: - void setValueInternal( qreal value ); - void adjustValue(); - - class PrivateData; - std::unique_ptr< PrivateData > m_data; + ~CircularProgressBar() override = default; }; diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.cpp b/examples/iotdashboard/CircularProgressBarSkinlet.cpp index 0bd5f418..8b9f7a5c 100644 --- a/examples/iotdashboard/CircularProgressBarSkinlet.cpp +++ b/examples/iotdashboard/CircularProgressBarSkinlet.cpp @@ -39,7 +39,7 @@ QSGNode* CircularProgressBarSkinlet::updateSubNode( const qreal spanAngle = 360.0 * bar->valueAsRatio(); return updateArcNode( skinnable, node, startAngle, -spanAngle, - CircularProgressBar::Bar ); + CircularProgressBar::Fill ); } } diff --git a/examples/iotdashboard/EnergyMeter.cpp b/examples/iotdashboard/EnergyMeter.cpp index f9d20537..dae877ba 100644 --- a/examples/iotdashboard/EnergyMeter.cpp +++ b/examples/iotdashboard/EnergyMeter.cpp @@ -36,7 +36,7 @@ EnergyMeter::EnergyMeter( const QColor& textColor, setAutoLayoutChildren( true ); auto valueBar = new CircularProgressBar( this ); - valueBar->setGradientHint( CircularProgressBar::Bar, gradient ); + valueBar->setGradientHint( CircularProgressBar::Fill, gradient ); valueBar->setValue( value ); auto valueLabel = new ValueLabel( this ); diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index 5e7b56e3..2495d744 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -131,7 +131,7 @@ void Skin::initHints() ed.setArcMetrics( CircularProgressBar::Groove, 90, -360, 8.53 ); // the span angle will be set in the progress bar, we just give a dummy // value here: - ed.setArcMetrics( CircularProgressBar::Bar, 90, -180, 8.53 ); + ed.setArcMetrics( CircularProgressBar::Fill, 90, -180, 8.53 ); ed.setFontRole( TimeTitleLabel::Text, { QskFontRole::Caption, QskFontRole::High } ); diff --git a/examples/iotdashboard/StorageMeter.cpp b/examples/iotdashboard/StorageMeter.cpp index af9d528b..38b9c3fd 100644 --- a/examples/iotdashboard/StorageMeter.cpp +++ b/examples/iotdashboard/StorageMeter.cpp @@ -35,7 +35,7 @@ void StorageMeter::setValue( const qreal value ) { const auto gradient = gradientHint( StorageMeter::Status ); const auto color = gradient.extracted( value / 100.0, value / 100.0 ).startColor(); - setGradientHint( StorageMeter::Bar, { color, color.lighter() } ); + setGradientHint( StorageMeter::Fill, { color, color.lighter() } ); CircularProgressBar::setValue( value ); label->setTextColor( color ); label->setText( make_text( locale(), value ) ); From 86942d4226952fe0b582c81148bd355033b4b13a Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 4 Sep 2024 17:08:40 +0200 Subject: [PATCH 3/6] code duplication eliminated --- examples/iotdashboard/CircularProgressBar.h | 6 +- .../CircularProgressBarSkinlet.cpp | 29 +------ .../iotdashboard/CircularProgressBarSkinlet.h | 19 +---- examples/iotdashboard/Skin.cpp | 11 ++- src/controls/QskProgressBarSkinlet.cpp | 15 ++-- src/controls/QskProgressRingSkinlet.cpp | 82 +++++++++---------- src/controls/QskProgressRingSkinlet.h | 4 +- 7 files changed, 63 insertions(+), 103 deletions(-) diff --git a/examples/iotdashboard/CircularProgressBar.h b/examples/iotdashboard/CircularProgressBar.h index 67359722..810a18e5 100644 --- a/examples/iotdashboard/CircularProgressBar.h +++ b/examples/iotdashboard/CircularProgressBar.h @@ -5,13 +5,13 @@ #pragma once -#include +#include -class CircularProgressBar : public QskProgressIndicator +class CircularProgressBar : public QskProgressRing { Q_OBJECT - using Inherited = QskProgressIndicator; + using Inherited = QskProgressRing; public: CircularProgressBar( qreal min, qreal max, QQuickItem* parent = nullptr ); diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.cpp b/examples/iotdashboard/CircularProgressBarSkinlet.cpp index 8b9f7a5c..4f8eafe0 100644 --- a/examples/iotdashboard/CircularProgressBarSkinlet.cpp +++ b/examples/iotdashboard/CircularProgressBarSkinlet.cpp @@ -4,12 +4,11 @@ *****************************************************************************/ #include "CircularProgressBarSkinlet.h" -#include "CircularProgressBar.h" +#include CircularProgressBarSkinlet::CircularProgressBarSkinlet( QskSkin* skin ) - : QskSkinlet( skin ) + : Inherited( skin ) { - setNodeRoles( { GrooveRole, BarRole } ); } CircularProgressBarSkinlet::~CircularProgressBarSkinlet() @@ -22,28 +21,4 @@ QRectF CircularProgressBarSkinlet::subControlRect( return contentsRect; } -QSGNode* CircularProgressBarSkinlet::updateSubNode( - const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const -{ - switch( nodeRole ) - { - case GrooveRole: - { - return updateArcNode( skinnable, node, CircularProgressBar::Groove ); - } - case BarRole: - { - const auto bar = static_cast< const CircularProgressBar* >( skinnable ); - - const qreal startAngle = 90.0; - const qreal spanAngle = 360.0 * bar->valueAsRatio(); - - return updateArcNode( skinnable, node, startAngle, -spanAngle, - CircularProgressBar::Fill ); - } - } - - return Inherited::updateSubNode( skinnable, nodeRole, node ); -} - #include "moc_CircularProgressBarSkinlet.cpp" diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.h b/examples/iotdashboard/CircularProgressBarSkinlet.h index 9075fbb3..92434b85 100644 --- a/examples/iotdashboard/CircularProgressBarSkinlet.h +++ b/examples/iotdashboard/CircularProgressBarSkinlet.h @@ -5,32 +5,19 @@ #pragma once -#include +#include -class CircularProgressBar; - -class CircularProgressBarSkinlet : public QskSkinlet +class CircularProgressBarSkinlet : public QskProgressRingSkinlet { Q_GADGET - using Inherited = QskSkinlet; + using Inherited = QskProgressRingSkinlet; public: - enum NodeRole - { - GrooveRole, - BarRole, - - RoleCount, - }; Q_INVOKABLE CircularProgressBarSkinlet( QskSkin* = nullptr ); ~CircularProgressBarSkinlet() override; QRectF subControlRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol ) const override; - - protected: - QSGNode* updateSubNode( const QskSkinnable*, - quint8 nodeRole, QSGNode* ) const override; }; diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index 2495d744..b6f8cd8f 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -121,17 +121,16 @@ void Skin::initHints() ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 ); ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff ); - // arcs are counterclockwise, so specify the 2nd color first: - ed.setGradient( TopBarItem::Item1, 0xffff3122, 0xffff5c00 ); - ed.setGradient( TopBarItem::Item2, 0xff6100ff, 0xff6776ff ); - ed.setGradient( TopBarItem::Item3, 0xffff3122, 0xffffce50 ); - ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff ); + ed.setGradient( TopBarItem::Item1, 0xffff5c00, 0xffff3122 ); + ed.setGradient( TopBarItem::Item2, 0xff6776ff, 0xff6100ff ); + ed.setGradient( TopBarItem::Item3, 0xffffce50, 0xffff3122 ); + ed.setGradient( TopBarItem::Item4, 0xff6776ff, 0xff6100ff ); // the bar gradient is defined through the top bar items above ed.setArcMetrics( CircularProgressBar::Groove, 90, -360, 8.53 ); // the span angle will be set in the progress bar, we just give a dummy // value here: - ed.setArcMetrics( CircularProgressBar::Fill, 90, -180, 8.53 ); + ed.setArcMetrics( CircularProgressBar::Fill, 90, -360, 8.53 ); ed.setFontRole( TimeTitleLabel::Text, { QskFontRole::Caption, QskFontRole::High } ); diff --git a/src/controls/QskProgressBarSkinlet.cpp b/src/controls/QskProgressBarSkinlet.cpp index 74fe9e69..225fb44c 100644 --- a/src/controls/QskProgressBarSkinlet.cpp +++ b/src/controls/QskProgressBarSkinlet.cpp @@ -15,13 +15,13 @@ using Q = QskProgressBar; namespace { - QskIntervalF qskFillInterval( const Q* bar ) + QskIntervalF qskFillInterval( const QskProgressIndicator* indicator ) { qreal pos1, pos2; - if ( bar->isIndeterminate() ) + if ( indicator->isIndeterminate() ) { - const auto pos = bar->positionHint( QskProgressIndicator::Fill ); + const auto pos = indicator->positionHint( QskProgressIndicator::Fill ); static const QEasingCurve curve( QEasingCurve::InOutCubic ); @@ -32,10 +32,11 @@ namespace } else { - pos1 = bar->valueAsRatio( bar->origin() ); - pos2 = bar->valueAsRatio( bar->value() ); + pos1 = indicator->valueAsRatio( indicator->origin() ); + pos2 = indicator->valueAsRatio( indicator->value() ); } + auto bar = static_cast< const QskProgressBar* >( indicator ); if( bar->orientation() == Qt::Horizontal ) { if ( bar->layoutMirroring() ) @@ -107,11 +108,11 @@ QSGNode* QskProgressBarSkinlet::updateFillNode( const auto subControl = Q::Fill; - const auto rect = bar->subControlRect( subControl ); + const auto rect = indicator->subControlRect( subControl ); if ( rect.isEmpty() ) return nullptr; - auto gradient = bar->gradientHint( subControl ); + auto gradient = indicator->gradientHint( subControl ); if ( !gradient.isVisible() ) return nullptr; diff --git a/src/controls/QskProgressRingSkinlet.cpp b/src/controls/QskProgressRingSkinlet.cpp index 86e90329..ce611eef 100644 --- a/src/controls/QskProgressRingSkinlet.cpp +++ b/src/controls/QskProgressRingSkinlet.cpp @@ -10,31 +10,6 @@ using Q = QskProgressRing; -namespace -{ - QskIntervalF qskFillInterval( const Q* ring ) - { - qreal pos1, pos2; - - if ( ring->isIndeterminate() ) - { - const auto pos = ring->positionHint( QskProgressIndicator::Fill ); - - pos1 = pos2 = pos; - } - else - { - pos1 = ring->valueAsRatio( ring->origin() ); - pos2 = ring->valueAsRatio( ring->value() ); - } - - if ( pos1 > pos2 ) - std::swap( pos1, pos2 ); - - return QskIntervalF( pos1, pos2 ); - } -} - QskProgressRingSkinlet::QskProgressRingSkinlet( QskSkin* skin ) : Inherited( skin ) { @@ -48,21 +23,17 @@ QRectF QskProgressRingSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { - const auto ring = static_cast< const Q* >( skinnable ); - if( subControl == Q::Groove || subControl == Q::Fill ) { - auto rect = contentsRect; + const auto ring = static_cast< const Q* >( skinnable ); + const auto size = ring->strutSizeHint( Q::Fill ); + auto rect = contentsRect; if( ring->layoutMirroring() ) - { rect.setLeft( rect.right() - size.width() ); - } else - { rect.setWidth( size.width() ); - } rect.setTop( rect.top() + 0.5 * ( rect.height() - size.height() ) ); rect.setHeight( size.height() ); @@ -90,22 +61,29 @@ QSGNode* QskProgressRingSkinlet::updateFillNode( if ( rect.isEmpty() ) return nullptr; + const auto metrics = ring->arcMetricsHint( subControl ); + if ( metrics.isNull() ) + return nullptr; + auto gradient = ring->gradientHint( subControl ); if ( !gradient.isVisible() ) return nullptr; + const auto intv = fillInterval( ring ); + if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() ) { - const auto center = rect.center(); - const auto arcMetrics = ring->arcMetricsHint( Q::Fill ); - gradient.setConicDirection( center.x(), center.y(), arcMetrics.startAngle(), arcMetrics.spanAngle() ); + const auto stops = qskExtractedGradientStops( gradient.stops(), + intv.lowerBound(), intv.upperBound() ); + + gradient.setStops( stops ); + + if ( metrics.spanAngle() < 0.0 ) + gradient.reverse(); } - const auto interval = qskFillInterval( ring ); - const auto arcMetrics = ring->arcMetricsHint( subControl ); - - const auto startAngle = arcMetrics.startAngle() + interval.lowerBound() * arcMetrics.spanAngle(); - const auto spanAngle = interval.upperBound() * arcMetrics.spanAngle(); + const auto startAngle = metrics.startAngle() + intv.lowerBound() * metrics.spanAngle(); + const auto spanAngle = intv.upperBound() * metrics.spanAngle(); return updateArcNode( ring, node, rect, gradient, startAngle, spanAngle, subControl ); } @@ -116,10 +94,28 @@ QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable, if ( which != Qt::PreferredSize ) return QSizeF(); - const auto ring = static_cast< const Q* >( skinnable ); + return skinnable->strutSizeHint( Q::Fill ); +} - const auto r = ring->strutSizeHint( Q::Fill ); - return r; +QskIntervalF QskProgressRingSkinlet::fillInterval( + const QskProgressIndicator* indicator ) const +{ + qreal pos1, pos2; + + if ( indicator->isIndeterminate() ) + { + pos1 = pos2 = indicator->positionHint( QskProgressIndicator::Fill ); + } + else + { + pos1 = indicator->valueAsRatio( indicator->origin() ); + pos2 = indicator->valueAsRatio( indicator->value() ); + } + + if ( pos1 > pos2 ) + std::swap( pos1, pos2 ); + + return QskIntervalF( pos1, pos2 ); } #include "moc_QskProgressRingSkinlet.cpp" diff --git a/src/controls/QskProgressRingSkinlet.h b/src/controls/QskProgressRingSkinlet.h index 767930b1..c5dc815b 100644 --- a/src/controls/QskProgressRingSkinlet.h +++ b/src/controls/QskProgressRingSkinlet.h @@ -8,7 +8,7 @@ #include "QskProgressIndicatorSkinlet.h" -class QskProgressRing; +class QskIntervalF; class QSK_EXPORT QskProgressRingSkinlet : public QskProgressIndicatorSkinlet { @@ -29,6 +29,8 @@ class QSK_EXPORT QskProgressRingSkinlet : public QskProgressIndicatorSkinlet protected: QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const override; QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const override; + + QskIntervalF fillInterval( const QskProgressIndicator* ) const; }; #endif From c61e3c7f3621528506d47c79ed370f0ab7e0568c Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 4 Sep 2024 17:50:42 +0200 Subject: [PATCH 4/6] CircularProgressBar removed, using QskProgressRing instead --- .../gallery/progressbar/ProgressBarPage.cpp | 1 + examples/iotdashboard/CMakeLists.txt | 2 - examples/iotdashboard/CircularProgressBar.cpp | 19 ------- examples/iotdashboard/CircularProgressBar.h | 21 -------- .../CircularProgressBarSkinlet.cpp | 24 --------- .../iotdashboard/CircularProgressBarSkinlet.h | 23 --------- examples/iotdashboard/EnergyMeter.cpp | 8 +-- examples/iotdashboard/Skin.cpp | 11 ++-- examples/iotdashboard/StorageMeter.cpp | 51 ++++++++++--------- examples/iotdashboard/StorageMeter.h | 18 ++++--- src/controls/QskProgressRing.cpp | 2 + src/controls/QskProgressRingSkinlet.cpp | 17 +------ 12 files changed, 50 insertions(+), 147 deletions(-) delete mode 100644 examples/iotdashboard/CircularProgressBar.cpp delete mode 100644 examples/iotdashboard/CircularProgressBar.h delete mode 100644 examples/iotdashboard/CircularProgressBarSkinlet.cpp delete mode 100644 examples/iotdashboard/CircularProgressBarSkinlet.h diff --git a/examples/gallery/progressbar/ProgressBarPage.cpp b/examples/gallery/progressbar/ProgressBarPage.cpp index fe0e7b07..3517eb91 100644 --- a/examples/gallery/progressbar/ProgressBarPage.cpp +++ b/examples/gallery/progressbar/ProgressBarPage.cpp @@ -159,6 +159,7 @@ void ProgressBarPage::populate() { auto* ring = new QskProgressRing( determinateRingsHBox ); ring->setSize( size ); + ring->setLayoutAlignmentHint( Qt::AlignCenter ); QQuickItem* parentItem; diff --git a/examples/iotdashboard/CMakeLists.txt b/examples/iotdashboard/CMakeLists.txt index 183c0112..8a85943e 100644 --- a/examples/iotdashboard/CMakeLists.txt +++ b/examples/iotdashboard/CMakeLists.txt @@ -6,8 +6,6 @@ set(SOURCES Box.h Box.cpp BoxWithButtons.h BoxWithButtons.cpp - CircularProgressBar.h CircularProgressBar.cpp - CircularProgressBarSkinlet.h CircularProgressBarSkinlet.cpp Diagram.h Diagram.cpp DiagramSkinlet.h DiagramSkinlet.cpp EnergyMeter.h EnergyMeter.cpp diff --git a/examples/iotdashboard/CircularProgressBar.cpp b/examples/iotdashboard/CircularProgressBar.cpp deleted file mode 100644 index 8bb873ab..00000000 --- a/examples/iotdashboard/CircularProgressBar.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "CircularProgressBar.h" - -CircularProgressBar::CircularProgressBar( qreal min, qreal max, QQuickItem* parent ) - : Inherited( min, max, parent ) -{ - initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding ); -} - -CircularProgressBar::CircularProgressBar( QQuickItem* parent ) - : CircularProgressBar( 0.0, 100.0, parent ) -{ -} - -#include "moc_CircularProgressBar.cpp" diff --git a/examples/iotdashboard/CircularProgressBar.h b/examples/iotdashboard/CircularProgressBar.h deleted file mode 100644 index 810a18e5..00000000 --- a/examples/iotdashboard/CircularProgressBar.h +++ /dev/null @@ -1,21 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#pragma once - -#include - -class CircularProgressBar : public QskProgressRing -{ - Q_OBJECT - - using Inherited = QskProgressRing; - - public: - CircularProgressBar( qreal min, qreal max, QQuickItem* parent = nullptr ); - CircularProgressBar( QQuickItem* parent = nullptr ); - - ~CircularProgressBar() override = default; -}; diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.cpp b/examples/iotdashboard/CircularProgressBarSkinlet.cpp deleted file mode 100644 index 4f8eafe0..00000000 --- a/examples/iotdashboard/CircularProgressBarSkinlet.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "CircularProgressBarSkinlet.h" -#include - -CircularProgressBarSkinlet::CircularProgressBarSkinlet( QskSkin* skin ) - : Inherited( skin ) -{ -} - -CircularProgressBarSkinlet::~CircularProgressBarSkinlet() -{ -} - -QRectF CircularProgressBarSkinlet::subControlRect( - const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const -{ - return contentsRect; -} - -#include "moc_CircularProgressBarSkinlet.cpp" diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.h b/examples/iotdashboard/CircularProgressBarSkinlet.h deleted file mode 100644 index 92434b85..00000000 --- a/examples/iotdashboard/CircularProgressBarSkinlet.h +++ /dev/null @@ -1,23 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#pragma once - -#include - -class CircularProgressBarSkinlet : public QskProgressRingSkinlet -{ - Q_GADGET - - using Inherited = QskProgressRingSkinlet; - - public: - - Q_INVOKABLE CircularProgressBarSkinlet( QskSkin* = nullptr ); - ~CircularProgressBarSkinlet() override; - - QRectF subControlRect( const QskSkinnable*, - const QRectF&, QskAspect::Subcontrol ) const override; -}; diff --git a/examples/iotdashboard/EnergyMeter.cpp b/examples/iotdashboard/EnergyMeter.cpp index dae877ba..9f00a0ad 100644 --- a/examples/iotdashboard/EnergyMeter.cpp +++ b/examples/iotdashboard/EnergyMeter.cpp @@ -4,8 +4,8 @@ *****************************************************************************/ #include "EnergyMeter.h" -#include "CircularProgressBar.h" +#include #include #include @@ -35,8 +35,10 @@ EnergyMeter::EnergyMeter( const QColor& textColor, { setAutoLayoutChildren( true ); - auto valueBar = new CircularProgressBar( this ); - valueBar->setGradientHint( CircularProgressBar::Fill, gradient ); + auto valueBar = new QskProgressRing( this ); + valueBar->setSizePolicy( + QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained ); + valueBar->setFillGradient( gradient ); valueBar->setValue( value ); auto valueLabel = new ValueLabel( this ); diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index b6f8cd8f..8f7a23f1 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -7,8 +7,6 @@ #include "Box.h" #include "BoxWithButtons.h" -#include "CircularProgressBar.h" -#include "CircularProgressBarSkinlet.h" #include "DashboardPage.h" #include "Diagram.h" #include "DiagramSkinlet.h" @@ -56,7 +54,6 @@ Skin::Skin( QObject* parent ) { setObjectName( "iot" ); - declareSkinlet< CircularProgressBar, CircularProgressBarSkinlet >(); declareSkinlet< Diagram, DiagramSkinlet >(); declareSkinlet< LightDisplay, LightDisplaySkinlet >(); declareSkinlet< StorageBar, StorageBarSkinlet >(); @@ -127,10 +124,10 @@ void Skin::initHints() ed.setGradient( TopBarItem::Item4, 0xff6776ff, 0xff6100ff ); // the bar gradient is defined through the top bar items above - ed.setArcMetrics( CircularProgressBar::Groove, 90, -360, 8.53 ); + ed.setArcMetrics( QskProgressRing::Groove, 90, -360, 8.53 ); // the span angle will be set in the progress bar, we just give a dummy // value here: - ed.setArcMetrics( CircularProgressBar::Fill, 90, -360, 8.53 ); + ed.setArcMetrics( QskProgressRing::Fill, 90, -360, 8.53 ); ed.setFontRole( TimeTitleLabel::Text, { QskFontRole::Caption, QskFontRole::High } ); @@ -282,8 +279,8 @@ void Skin::initHints() ed.setColor( QskTextLabel::Text, palette.text ); ed.setColor( UsageDiagramBox::DayText, palette.text ); - ed.setMetric( CircularProgressBar::Groove | QskAspect::Border, 2 ); - ed.setColor( CircularProgressBar::Groove | QskAspect::Border, + ed.setMetric( QskProgressRing::Groove | QskAspect::Border, 2 ); + ed.setColor( QskProgressRing::Groove | QskAspect::Border, palette.circularProgressBarGroove ); // storage bar diff --git a/examples/iotdashboard/StorageMeter.cpp b/examples/iotdashboard/StorageMeter.cpp index 38b9c3fd..38233cb7 100644 --- a/examples/iotdashboard/StorageMeter.cpp +++ b/examples/iotdashboard/StorageMeter.cpp @@ -4,44 +4,47 @@ *****************************************************************************/ #include "StorageMeter.h" -#include "CircularProgressBar.h" + #include #include QSK_SUBCONTROL( StorageMeter, Status ) -namespace -{ - inline QString make_text( const QLocale& locale, const qreal value ) - { - return locale.toString( static_cast< int >( value ) ) + " " + locale.percent(); - } -} - StorageMeter::StorageMeter( QQuickItem* parent ) noexcept - : CircularProgressBar( parent ) - , label( new QskTextLabel( this ) ) + : QskProgressRing( parent ) { setAutoLayoutChildren( true ); - setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Constrained ); + initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained ); - label->setText( make_text( locale(), value() ) ); - label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); - label->setLayoutAlignmentHint( Qt::AlignCenter ); - label->setFontRole( QskFontRole::Caption ); + m_label = new QskTextLabel( this ); + m_label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + m_label->setLayoutAlignmentHint( Qt::AlignCenter ); + m_label->setFontRole( QskFontRole::Caption ); + + connect( this, &QskProgressRing::valueChanged, + this, &StorageMeter::updateMeter ); + + updateMeter( value() ); } -void StorageMeter::setValue( const qreal value ) +void StorageMeter::updateMeter( const qreal value ) { - const auto gradient = gradientHint( StorageMeter::Status ); - const auto color = gradient.extracted( value / 100.0, value / 100.0 ).startColor(); - setGradientHint( StorageMeter::Fill, { color, color.lighter() } ); - CircularProgressBar::setValue( value ); - label->setTextColor( color ); - label->setText( make_text( locale(), value ) ); + const auto color = qskInterpolatedColorAt( + gradientHint( Status ).stops(), value / 100.0 ); + + setFillGradient( { color, color.lighter() } ); + + m_label->setTextColor( color ); + + const auto locale = this->locale(); + const auto text = locale.toString( static_cast< int >( value ) ) + + " " + locale.percent(); + + m_label->setText( text ); } -QSizeF StorageMeter::contentsSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const +QSizeF StorageMeter::contentsSizeHint( + Qt::SizeHint which, const QSizeF& constraint ) const { if ( which != Qt::PreferredSize ) return QSizeF(); diff --git a/examples/iotdashboard/StorageMeter.h b/examples/iotdashboard/StorageMeter.h index 16a8f454..c6a6af42 100644 --- a/examples/iotdashboard/StorageMeter.h +++ b/examples/iotdashboard/StorageMeter.h @@ -5,18 +5,20 @@ #pragma once -#include "CircularProgressBar.h" -#include +#include -class StorageMeter final : public CircularProgressBar +class QskTextLabel; + +class StorageMeter final : public QskProgressRing { public: QSK_SUBCONTROLS( Status ) - explicit StorageMeter( QQuickItem* parent = nullptr ) noexcept; - public Q_SLOTS: - void setValue( qreal value ); + + StorageMeter( QQuickItem* parent = nullptr ) noexcept; private: - QSizeF contentsSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const override; - class QskTextLabel* label = nullptr; + void updateMeter( qreal value ); + QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override; + + QskTextLabel* m_label = nullptr; }; diff --git a/src/controls/QskProgressRing.cpp b/src/controls/QskProgressRing.cpp index dcc1d8d6..a87cb707 100644 --- a/src/controls/QskProgressRing.cpp +++ b/src/controls/QskProgressRing.cpp @@ -20,6 +20,8 @@ QskProgressRing::QskProgressRing( qreal min, qreal max, QQuickItem* parent ) : Inherited( min, max, parent ) , m_data( new PrivateData ) { + initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + m_data->size = NormalSize; setSubcontrolProxy( Inherited::Groove, Groove ); diff --git a/src/controls/QskProgressRingSkinlet.cpp b/src/controls/QskProgressRingSkinlet.cpp index ce611eef..04f8e427 100644 --- a/src/controls/QskProgressRingSkinlet.cpp +++ b/src/controls/QskProgressRingSkinlet.cpp @@ -24,22 +24,7 @@ QRectF QskProgressRingSkinlet::subControlRect( QskAspect::Subcontrol subControl ) const { if( subControl == Q::Groove || subControl == Q::Fill ) - { - const auto ring = static_cast< const Q* >( skinnable ); - - const auto size = ring->strutSizeHint( Q::Fill ); - - auto rect = contentsRect; - if( ring->layoutMirroring() ) - rect.setLeft( rect.right() - size.width() ); - else - rect.setWidth( size.width() ); - - rect.setTop( rect.top() + 0.5 * ( rect.height() - size.height() ) ); - rect.setHeight( size.height() ); - - return rect; - } + return contentsRect; return Inherited::subControlRect( skinnable, contentsRect, subControl ); } From d0a564ff501a1ab2b43cf4decf4cfa2f0f20f5f9 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 5 Sep 2024 09:15:25 +0200 Subject: [PATCH 5/6] using ValueMeter for StorageMeter/EnergyMeter --- examples/iotdashboard/CMakeLists.txt | 3 +- examples/iotdashboard/EnergyMeter.cpp | 71 ------------------- examples/iotdashboard/EnergyMeter.h | 18 ----- examples/iotdashboard/Skin.cpp | 12 ++-- examples/iotdashboard/StorageMeter.cpp | 68 ------------------ examples/iotdashboard/StoragePage.cpp | 61 ++++++++++++++-- examples/iotdashboard/StoragePage.h | 35 +-------- examples/iotdashboard/TopBar.cpp | 22 ++++-- examples/iotdashboard/ValueMeter.cpp | 42 +++++++++++ .../{StorageMeter.h => ValueMeter.h} | 11 +-- 10 files changed, 135 insertions(+), 208 deletions(-) delete mode 100644 examples/iotdashboard/EnergyMeter.cpp delete mode 100644 examples/iotdashboard/EnergyMeter.h delete mode 100644 examples/iotdashboard/StorageMeter.cpp create mode 100644 examples/iotdashboard/ValueMeter.cpp rename examples/iotdashboard/{StorageMeter.h => ValueMeter.h} (66%) diff --git a/examples/iotdashboard/CMakeLists.txt b/examples/iotdashboard/CMakeLists.txt index 8a85943e..afeffdb9 100644 --- a/examples/iotdashboard/CMakeLists.txt +++ b/examples/iotdashboard/CMakeLists.txt @@ -8,7 +8,6 @@ set(SOURCES BoxWithButtons.h BoxWithButtons.cpp Diagram.h Diagram.cpp DiagramSkinlet.h DiagramSkinlet.cpp - EnergyMeter.h EnergyMeter.cpp GraphicProvider.h GraphicProvider.cpp GridBox.h GridBox.cpp LightDisplaySkinlet.h LightDisplaySkinlet.cpp @@ -29,7 +28,7 @@ set(SOURCES UsageBox.h UsageBox.cpp UsageDiagram.h UsageDiagram.cpp StoragePage.h StoragePage.cpp - StorageMeter.h StorageMeter.cpp + ValueMeter.h ValueMeter.cpp StorageBar.h StorageBar.cpp StorageBarSkinlet.h StorageBarSkinlet.cpp nodes/DiagramDataNode.h nodes/DiagramDataNode.cpp diff --git a/examples/iotdashboard/EnergyMeter.cpp b/examples/iotdashboard/EnergyMeter.cpp deleted file mode 100644 index 9f00a0ad..00000000 --- a/examples/iotdashboard/EnergyMeter.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "EnergyMeter.h" - -#include -#include -#include - -namespace -{ - class ValueLabel : public QskTextLabel - { - public: - ValueLabel( QQuickItem* parent ) - : QskTextLabel( parent ) - { - initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); - setLayoutAlignmentHint( Qt::AlignCenter ); - setFontRole( QskFontRole::Caption ); - } - - void setValue( int value ) - { - setText( locale().toString( value ) + " " + locale().percent() ); - } - }; -} - -EnergyMeter::EnergyMeter( const QColor& textColor, - const QskGradient& gradient, int value, QQuickItem* parent ) - : QskControl( parent ) -{ - setAutoLayoutChildren( true ); - - auto valueBar = new QskProgressRing( this ); - valueBar->setSizePolicy( - QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained ); - valueBar->setFillGradient( gradient ); - valueBar->setValue( value ); - - auto valueLabel = new ValueLabel( this ); - valueLabel->setTextColor( textColor ); - valueLabel->setValue( value ); -} - -QSizeF EnergyMeter::contentsSizeHint( - Qt::SizeHint which, const QSizeF& constraint ) const -{ - if ( which != Qt::PreferredSize ) - return QSizeF(); - - qreal size; - - if ( constraint.width() > 0 ) - { - size = constraint.width(); - } - else if ( constraint.height() > 0 ) - { - size = constraint.height(); - } - else - { - size = 57; - } - - return QSizeF( size, size ); -} diff --git a/examples/iotdashboard/EnergyMeter.h b/examples/iotdashboard/EnergyMeter.h deleted file mode 100644 index 7780dd9e..00000000 --- a/examples/iotdashboard/EnergyMeter.h +++ /dev/null @@ -1,18 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2021 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#pragma once - -#include - -class EnergyMeter : public QskControl -{ - public: - EnergyMeter( const QColor&, const QskGradient&, - int progress, QQuickItem* parent = nullptr ); - - protected: - QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override; -}; diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index 8f7a23f1..72abc78c 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -19,7 +19,6 @@ #include "RoundedIcon.h" #include "StorageBar.h" #include "StorageBarSkinlet.h" -#include "StorageMeter.h" #include "StoragePage.h" #include "TopBar.h" #include "UsageBox.h" @@ -35,6 +34,7 @@ #include #include #include +#include #include #include @@ -298,9 +298,13 @@ void Skin::initHints() // storage meter { - ed.setGradient( StorageMeter::Status, - { { { 0.00, "#00ff00" }, { 0.33, "#00ff00" }, { 0.33, "#ffaf00" }, { 0.66, "#ffaf00" }, - { 0.66, "#ff0000" }, { 1.00, "#ff0000" } } } ); + ed.setGradient( StoragePage::Status, + { { + { 0.00, "#00ff00" }, { 0.33, "#00ff00" }, + { 0.33, "#ffaf00" }, { 0.66, "#ffaf00" }, + { 0.66, "#ff0000" }, { 1.00, "#ff0000" } + } } + ); } } diff --git a/examples/iotdashboard/StorageMeter.cpp b/examples/iotdashboard/StorageMeter.cpp deleted file mode 100644 index 38233cb7..00000000 --- a/examples/iotdashboard/StorageMeter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2022 Edelhirsch Software GmbH - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include "StorageMeter.h" - -#include -#include - -QSK_SUBCONTROL( StorageMeter, Status ) - -StorageMeter::StorageMeter( QQuickItem* parent ) noexcept - : QskProgressRing( parent ) -{ - setAutoLayoutChildren( true ); - initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained ); - - m_label = new QskTextLabel( this ); - m_label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); - m_label->setLayoutAlignmentHint( Qt::AlignCenter ); - m_label->setFontRole( QskFontRole::Caption ); - - connect( this, &QskProgressRing::valueChanged, - this, &StorageMeter::updateMeter ); - - updateMeter( value() ); -} - -void StorageMeter::updateMeter( const qreal value ) -{ - const auto color = qskInterpolatedColorAt( - gradientHint( Status ).stops(), value / 100.0 ); - - setFillGradient( { color, color.lighter() } ); - - m_label->setTextColor( color ); - - const auto locale = this->locale(); - const auto text = locale.toString( static_cast< int >( value ) ) - + " " + locale.percent(); - - m_label->setText( text ); -} - -QSizeF StorageMeter::contentsSizeHint( - Qt::SizeHint which, const QSizeF& constraint ) const -{ - if ( which != Qt::PreferredSize ) - return QSizeF(); - - qreal size; - - if ( constraint.width() > 0 ) - { - size = constraint.width(); - } - else if ( constraint.height() > 0 ) - { - size = constraint.height(); - } - else - { - size = 57; - } - - return QSizeF( size, size ); -} diff --git a/examples/iotdashboard/StoragePage.cpp b/examples/iotdashboard/StoragePage.cpp index f1ff5b3c..038a6e39 100644 --- a/examples/iotdashboard/StoragePage.cpp +++ b/examples/iotdashboard/StoragePage.cpp @@ -6,7 +6,7 @@ #include "StoragePage.h" #include "Box.h" #include "StorageBar.h" -#include "StorageMeter.h" +#include "ValueMeter.h" #include #include #include @@ -20,6 +20,60 @@ #include QSK_SUBCONTROL( StoragePage, Panel ) +QSK_SUBCONTROL( StoragePage, Status ) + +namespace +{ + struct Storage + { + struct Media + { + qreal pictures = 0; + qreal music = 0; + qreal videos = 0; + qreal documents = 0; + qreal others = 0; + + inline constexpr bool operator==( const Media& rhs ) const noexcept + { + return pictures == rhs.pictures && music == rhs.music && videos == rhs.videos && + documents == rhs.documents && others == rhs.others; + } + + inline constexpr qreal free() const noexcept + { + return 1.0 - pictures - music - videos - documents - others; + } + }; + + QString title; + QString description; + Media distribution; + }; + + class StorageMeter final : public ValueMeter + { + public: + StorageMeter( QQuickItem* parent = nullptr ) + : ValueMeter( parent ) + { + setFixedSize( 64, 64 ); + + connect( this, &ValueMeter::valueChanged, + this, &StorageMeter::setStatusColor ); + } + + private: + void setStatusColor( qreal value ) + { + const auto color = qskInterpolatedColorAt( + gradientHint( StoragePage::Status ).stops(), value / 100.0 ); + + setFillGradient( { color, color.lighter() } ); + setTextColor( color ); + } + }; +} struct StorageRowAnimator final : public QObject, public QskAnimator { @@ -85,8 +139,6 @@ void StoragePage::addRow( const QString& title, const QString& description, const auto percent = 100.0 * ( 1.0 - storage.distribution.free() ); auto* const meter = new StorageMeter( left ); meter->setValue( percent ); - meter->setMinimumSize( 64, 64 ); - meter->setMaximumSize( 64, 64 ); auto* const maintitle = new QskTextLabel( storage.title, center ); maintitle->setFontRole( QskFontRole::Headline ); @@ -136,5 +188,6 @@ void StoragePage::addRow( const QString& title, const QString& description, bar->setDocuments( media.documents * v ); bar->setOthers( media.others * v ); }; - connect( sync, &QskPushButton::clicked, animator, [ animator ]() { animator->start(); } ); + connect( sync, &QskPushButton::clicked, + animator, [ animator ]() { animator->start(); } ); } diff --git a/examples/iotdashboard/StoragePage.h b/examples/iotdashboard/StoragePage.h index efb09d41..7f1d0146 100644 --- a/examples/iotdashboard/StoragePage.h +++ b/examples/iotdashboard/StoragePage.h @@ -7,44 +7,15 @@ #include #include -#include - -class QQuickItem; class StoragePage final : public QskLinearBox { public: - QSK_SUBCONTROLS( Panel ) - explicit StoragePage( QQuickItem* parent = nullptr ); + QSK_SUBCONTROLS( Panel, Status ) + + StoragePage( QQuickItem* parent = nullptr ); private: - struct Storage - { - struct Media - { - qreal pictures = 0; - qreal music = 0; - qreal videos = 0; - qreal documents = 0; - qreal others = 0; - - inline constexpr bool operator==( const Media& rhs ) const noexcept - { - return pictures == rhs.pictures && music == rhs.music && videos == rhs.videos && - documents == rhs.documents && others == rhs.others; - } - - inline constexpr qreal free() const noexcept - { - return 1.0 - pictures - music - videos - documents - others; - } - }; - - QString title; - QString description; - Media distribution; - }; - void addRow( const QString& title, const QString& description, qreal pictures, qreal music, qreal videos, qreal documents, qreal others ); }; diff --git a/examples/iotdashboard/TopBar.cpp b/examples/iotdashboard/TopBar.cpp index 31b6d932..0667f21e 100644 --- a/examples/iotdashboard/TopBar.cpp +++ b/examples/iotdashboard/TopBar.cpp @@ -4,7 +4,7 @@ *****************************************************************************/ #include "TopBar.h" -#include "EnergyMeter.h" +#include "ValueMeter.h" #include #include @@ -41,6 +41,22 @@ namespace return TopBarItem::Item4; } } + + class EnergyMeter : public ValueMeter + { + public: + EnergyMeter( const QColor& textColor, + const QskGradient& gradient, int value, QQuickItem* parent ) + : ValueMeter( parent ) + { + setFillGradient( gradient ); + setValue( value ); + setTextColor( textColor ); + + setFixedSize( 57, 57 ); + } + }; + } TopBarItem::TopBarItem( @@ -62,9 +78,7 @@ TopBarItem::TopBarItem( const auto subcontrol = subcontrolForIndex( index ); const auto textColor = color( subcontrol | QskAspect::TextColor ); - auto meter = new EnergyMeter( - textColor, gradient, progress, pieChartAndDisplay ); - meter->setSizePolicy( Qt::Horizontal, QskSizePolicy::Constrained ); + (void) new EnergyMeter( textColor, gradient, progress, pieChartAndDisplay ); auto display = new QskLinearBox( Qt::Vertical, pieChartAndDisplay ); display->setSpacing( 0 ); diff --git a/examples/iotdashboard/ValueMeter.cpp b/examples/iotdashboard/ValueMeter.cpp new file mode 100644 index 00000000..43f34dd2 --- /dev/null +++ b/examples/iotdashboard/ValueMeter.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright (C) 2022 Edelhirsch Software GmbH + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "ValueMeter.h" + +#include +#include + +ValueMeter::ValueMeter( QQuickItem* parent ) + : QskProgressRing( parent ) +{ + setAutoLayoutChildren( true ); + initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained ); + + m_label = new QskTextLabel( this ); + m_label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + m_label->setLayoutAlignmentHint( Qt::AlignCenter ); + m_label->setFontRole( QskFontRole::Caption ); + + connect( this, &QskProgressRing::valueChanged, + this, &ValueMeter::updateMeter ); + + updateMeter( value() ); +} + +void ValueMeter::updateMeter( const qreal value ) +{ + m_label->setText( text( value ) ); +} + +QString ValueMeter::text( qreal value ) const +{ + value = static_cast< int >( value ); + return locale().toString( value ) + ' ' + locale().percent(); +} + +void ValueMeter::setTextColor( const QColor& color ) +{ + m_label->setTextColor( color ); +} diff --git a/examples/iotdashboard/StorageMeter.h b/examples/iotdashboard/ValueMeter.h similarity index 66% rename from examples/iotdashboard/StorageMeter.h rename to examples/iotdashboard/ValueMeter.h index c6a6af42..52d31dd3 100644 --- a/examples/iotdashboard/StorageMeter.h +++ b/examples/iotdashboard/ValueMeter.h @@ -9,16 +9,17 @@ class QskTextLabel; -class StorageMeter final : public QskProgressRing +class ValueMeter : public QskProgressRing { public: - QSK_SUBCONTROLS( Status ) + ValueMeter( QQuickItem* parent = nullptr ); - StorageMeter( QQuickItem* parent = nullptr ) noexcept; + void setTextColor( const QColor& ); + + protected: + virtual QString text( qreal ) const; private: void updateMeter( qreal value ); - QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override; - QskTextLabel* m_label = nullptr; }; From cc64460a80eb00c1d60d00fb6a8f25050570f270 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 9 Sep 2024 09:54:23 +0200 Subject: [PATCH 6/6] QskProgressRingSkinlet::contentsSizeHint with constraints --- examples/iotdashboard/Skin.cpp | 29 ++++++++++++++----------- src/controls/QskProgressRing.cpp | 1 - src/controls/QskProgressRingSkinlet.cpp | 17 +++++++++++++-- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index 72abc78c..697a0b3b 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -84,9 +84,9 @@ void Skin::initHints() ed.setPadding( MainContentGridBox::Panel, { 19, 0, 27, 24 } ); - // menu bar: - { + // menu bar: + using Q = QskPushButton; using A = QskAspect; @@ -110,24 +110,27 @@ void Skin::initHints() ed.setAlignment( Q::Icon | A::Header, Qt::AlignCenter ); } - // top bar: - ed.setPadding( TopBar::Panel, { 25, 35, 25, 0 } ); + { + // top bar: - ed.setColor( TopBarItem::Item1 | QskAspect::TextColor, 0xffff3122 ); - ed.setColor( TopBarItem::Item2 | QskAspect::TextColor, 0xff6776ff ); - ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 ); - ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff ); + ed.setPadding( TopBar::Panel, { 25, 35, 25, 0 } ); - ed.setGradient( TopBarItem::Item1, 0xffff5c00, 0xffff3122 ); - ed.setGradient( TopBarItem::Item2, 0xff6776ff, 0xff6100ff ); - ed.setGradient( TopBarItem::Item3, 0xffffce50, 0xffff3122 ); - ed.setGradient( TopBarItem::Item4, 0xff6776ff, 0xff6100ff ); + ed.setColor( TopBarItem::Item1 | QskAspect::TextColor, 0xffff3122 ); + ed.setColor( TopBarItem::Item2 | QskAspect::TextColor, 0xff6776ff ); + ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 ); + ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff ); + + ed.setGradient( TopBarItem::Item1, 0xffff5c00, 0xffff3122 ); + ed.setGradient( TopBarItem::Item2, 0xff6776ff, 0xff6100ff ); + ed.setGradient( TopBarItem::Item3, 0xffffce50, 0xffff3122 ); + ed.setGradient( TopBarItem::Item4, 0xff6776ff, 0xff6100ff ); + } // the bar gradient is defined through the top bar items above ed.setArcMetrics( QskProgressRing::Groove, 90, -360, 8.53 ); // the span angle will be set in the progress bar, we just give a dummy // value here: - ed.setArcMetrics( QskProgressRing::Fill, 90, -360, 8.53 ); + ed.setArcMetrics( QskProgressRing::Fill, ed.arcMetrics( QskProgressRing::Groove ) ); ed.setFontRole( TimeTitleLabel::Text, { QskFontRole::Caption, QskFontRole::High } ); diff --git a/src/controls/QskProgressRing.cpp b/src/controls/QskProgressRing.cpp index a87cb707..af6c414b 100644 --- a/src/controls/QskProgressRing.cpp +++ b/src/controls/QskProgressRing.cpp @@ -4,7 +4,6 @@ *****************************************************************************/ #include "QskProgressRing.h" - #include "QskIntervalF.h" QSK_SUBCONTROL( QskProgressRing, Groove ) diff --git a/src/controls/QskProgressRingSkinlet.cpp b/src/controls/QskProgressRingSkinlet.cpp index 04f8e427..167cb861 100644 --- a/src/controls/QskProgressRingSkinlet.cpp +++ b/src/controls/QskProgressRingSkinlet.cpp @@ -74,12 +74,25 @@ QSGNode* QskProgressRingSkinlet::updateFillNode( } QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable, - Qt::SizeHint which, const QSizeF& ) const + Qt::SizeHint which, const QSizeF& constraint ) const { if ( which != Qt::PreferredSize ) return QSizeF(); - return skinnable->strutSizeHint( Q::Fill ); + auto hint = skinnable->strutSizeHint( Q::Fill ); + hint = hint.expandedTo( skinnable->strutSizeHint( Q::Groove ) ); + + if ( !constraint.isEmpty() ) + { + const qreal aspectRatio = hint.isEmpty() ? 1.0 : hint.width() / hint.height(); + + if ( constraint.width() >= 0.0 ) + hint.setHeight( constraint.width() / aspectRatio ); + else + hint.setWidth( constraint.height() * aspectRatio ); + } + + return hint; } QskIntervalF QskProgressRingSkinlet::fillInterval(