From 3a1a7c635c5a737246d76ab56e94a20f9019d923 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 24 Aug 2021 08:46:26 +0200 Subject: [PATCH] Iot dashboard: Make circular progress bar a QskControl (#124) * IOT example, circular progress bar: Use a pen instead of a brush That way we don't have to draw two circles, and we can in addition use a conical gradient. * IOT example: Make circular progress bar a QskControl ... and internally use a QskPaintedNode for now. By doing this we already have the API ready (similar to QskProgressBar) and can swap the QskPaintedNode with an arc renderer at a later point in time. --- examples/iotdashboard/CircularProgressBar.cpp | 239 ++++++++++++------ examples/iotdashboard/CircularProgressBar.h | 58 +++-- .../CircularProgressBarSkinlet.cpp | 220 ++++++++++++++++ .../iotdashboard/CircularProgressBarSkinlet.h | 39 +++ examples/iotdashboard/PieChartPainted.cpp | 8 +- examples/iotdashboard/Skin.cpp | 17 +- examples/iotdashboard/Skin.h | 11 +- examples/iotdashboard/iotdashboard.pro | 2 + 8 files changed, 490 insertions(+), 104 deletions(-) create mode 100644 examples/iotdashboard/CircularProgressBarSkinlet.cpp create mode 100644 examples/iotdashboard/CircularProgressBarSkinlet.h diff --git a/examples/iotdashboard/CircularProgressBar.cpp b/examples/iotdashboard/CircularProgressBar.cpp index 1d16931c..3a839286 100644 --- a/examples/iotdashboard/CircularProgressBar.cpp +++ b/examples/iotdashboard/CircularProgressBar.cpp @@ -5,107 +5,190 @@ #include "CircularProgressBar.h" -#include +#include +#include -CircularProgressBar::CircularProgressBar( const QskGradient& gradient, int progress, QQuickItem* parent ) - : QQuickPaintedItem( parent ) - , m_progress( progress ) +QSK_SUBCONTROL( CircularProgressBar, Groove ) +QSK_SUBCONTROL( CircularProgressBar, Bar ) + +namespace { - // This is a bit hackish, but let's do this properly - // once QSkinny has an arc renderer in place - QLinearGradient g( 0, 0, 30, 0 ); - QGradientStop stop1( 0.0, gradient.colorAt( 0 ) ); - QGradientStop stop2( 1.0, gradient.colorAt( 1 ) ); - g.setStops( {stop1, stop2} ); - m_gradient = g; - - connect( this, &QQuickPaintedItem::contentsSizeChanged, [this]() + class PositionAnimator : public QskAnimator { - auto size = contentsSize(); - QRadialGradient ringGradient( size.width() / 2, size.height() / 2, 45 ); - QGradientStop stop1( 0.0, "#c0c0c0" ); - QGradientStop stop2( 0.5, "#f0f0f0" ); - QGradientStop stop3( 1.0, "#c0c0c0" ); - ringGradient.setStops( {stop1, stop2, stop3} ); + public: + PositionAnimator( CircularProgressBar* progressBar ) + : m_progressBar( progressBar ) + { + setAutoRepeat( true ); + setDuration( 1300 ); - m_ringGradient = ringGradient; - } ); + 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; + }; } -double CircularProgressBar::width() const +class CircularProgressBar::PrivateData { - return m_width; -} + public: + void updateIndeterminateAnimator( CircularProgressBar* progressBar ) + { + if ( !isIndeterminate ) + { + delete animator; + animator = nullptr; -void CircularProgressBar::setWidth( double width ) + 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_width = width; + m_data->value = minimum(); + + initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding ); + + connect( this, &QskBoundedControl::boundariesChanged, + this, &CircularProgressBar::adjustValue ); } -QColor CircularProgressBar::backgroundColor() const +CircularProgressBar::CircularProgressBar( QQuickItem* parent ) + : CircularProgressBar( 0.0, 100.0, parent ) { - return m_backgroundColor; } -void CircularProgressBar::setBackgroundColor( const QColor& color ) +bool CircularProgressBar::isIndeterminate() const { - m_backgroundColor = color; + return m_data->isIndeterminate; } -QRadialGradient CircularProgressBar::ringGradient() const +void CircularProgressBar::setIndeterminate( bool on ) { - return m_ringGradient; + if ( on == m_data->isIndeterminate ) + return; + + m_data->isIndeterminate = on; + m_data->updateIndeterminateAnimator( this ); + + update(); + Q_EMIT indeterminateChanged( on ); } -void CircularProgressBar::setRingGradient( const QRadialGradient& gradient ) +void CircularProgressBar::resetOrigin() { - m_ringGradient = gradient; + if ( m_data->hasOrigin ) + { + m_data->hasOrigin = false; + + update(); + Q_EMIT originChanged( origin() ); + } } -void CircularProgressBar::paint( QPainter* painter ) +qreal CircularProgressBar::origin() const { - const auto size = contentsSize(); + if ( m_data->hasOrigin ) + { + return boundedValue( m_data->origin ); + } - const int startAngle = 1440; - const int endAngle = -16 * ( m_progress / 100.0 ) * 360; - - painter->setRenderHint( QPainter::Antialiasing, true ); - -#if 1 - QRectF outerRect( {0, 0}, size ); - - painter->setBrush( m_ringGradient ); - painter->setPen( m_backgroundColor ); - painter->drawEllipse( outerRect ); - - painter->setBrush( m_gradient ); - painter->drawPie( outerRect, startAngle, endAngle ); - - painter->setBrush( m_backgroundColor ); - painter->setPen( m_backgroundColor ); - QRectF innerRect( width() / 2, width() / 2, size.width() - width(), size.height() - width() ); - painter->drawEllipse( innerRect ); -#else - const qreal w = 10; - - const QRectF r( 0.5 * w, 0.5 * w, size.width() - w, size.height() - w ); - - const QColor c0 ( Qt::lightGray ); - - QRadialGradient g1( r.center(), qMin( r.width(), r.height() ) ); - g1.setColorAt( 0.0, c0 ); - g1.setColorAt( 0.5, c0.lighter( 120 ) ); - g1.setColorAt( 1.0, c0 ); - - painter->setPen( QPen( g1, w, Qt::SolidLine, Qt::FlatCap ) ); - painter->drawArc( r, startAngle, 16 * 360 ); - - QConicalGradient g2( r.center(), 0 ); - g2.setColorAt( 0.0, Qt::red ); - g2.setColorAt( 0.5, Qt::blue ); - g2.setColorAt( 1.0, Qt::red ); - - painter->setPen( QPen( g2, w, Qt::SolidLine, Qt::FlatCap ) ); - painter->drawArc( r, startAngle, endAngle ); -#endif + 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 303ec346..24a0c4fc 100644 --- a/examples/iotdashboard/CircularProgressBar.h +++ b/examples/iotdashboard/CircularProgressBar.h @@ -5,31 +5,59 @@ #pragma once +#include #include #include -#include -class CircularProgressBar : public QQuickPaintedItem +class CircularProgressBar : public QskBoundedControl { + 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; + public: - CircularProgressBar( const QskGradient&, int progress, QQuickItem* parent = nullptr ); + QSK_SUBCONTROLS( Groove, Bar ) - virtual void paint( QPainter* painter ) override; + CircularProgressBar( qreal min, qreal max, QQuickItem* parent = nullptr ); + CircularProgressBar( QQuickItem* parent = nullptr ); - double width() const; - void setWidth( double width ); + bool isIndeterminate() const; + void setIndeterminate( bool on = true ); - QColor backgroundColor() const; - void setBackgroundColor( const QColor& ); + void resetOrigin(); + qreal origin() const; - QRadialGradient ringGradient() const; - void setRingGradient( const QRadialGradient& ); + 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: - QGradient m_gradient; - QColor m_backgroundColor; - QRadialGradient m_ringGradient; - double m_width = 20; - int m_progress; + void setValueInternal( qreal value ); + void adjustValue(); + + class PrivateData; + std::unique_ptr< PrivateData > m_data; }; diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.cpp b/examples/iotdashboard/CircularProgressBarSkinlet.cpp new file mode 100644 index 00000000..37e040a1 --- /dev/null +++ b/examples/iotdashboard/CircularProgressBarSkinlet.cpp @@ -0,0 +1,220 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2021 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "CircularProgressBarSkinlet.h" +#include "CircularProgressBar.h" + +#include + +#include +#include + +namespace { + class ArcNode : public QskPaintedNode + { + public: + ArcNode() : QskPaintedNode() + { + } + + void setGradient( const QskGradient& gradient ) + { + m_gradient = gradient; + } + + void setGradientType( QGradient::Type type ) + { + m_gradientType = type; + } + + void setWidth( double width ) + { + m_width = width; + } + + void setValue( double value ) + { + m_value = value; + } + + void setOrigin( double origin ) + { + m_origin = origin; + } + + void setMaximum( double maximum ) + { + m_maximum = maximum; + } + + void setIndeterminate( bool isIndeterminate ) + { + m_isIndeterminate = isIndeterminate; + } + + void setPosition( double position ) + { + m_position = position; + } + + virtual void paint( QPainter* painter, const QSizeF& size ) override + { + int startAngle; + int spanAngle; + + if( m_isIndeterminate ) + { + static const QEasingCurve curve( QEasingCurve::Linear ); + + startAngle = -1 * m_position * 360; + // the other option is to just set a fixed value for the + // span angle (or do some advanced stuff with easing curves) + spanAngle = qAbs( 0.5 - m_position ) * 360; + } + else + { + startAngle = 90 + -1 * ( m_origin / m_maximum ) * 360; + spanAngle = -1 * ( m_value / m_maximum ) * 360; + } + + painter->setRenderHint( QPainter::Antialiasing, true ); + + const QRectF r( 0.5 * m_width, 0.5 * m_width, size.width() - m_width, size.height() - m_width ); + + QGradientStops stops; + + for( const QskGradientStop& stop : m_gradient.stops() ) + { + QGradientStop s( stop.position(), stop.color() ); + stops.append( s ); + } + + if( m_gradientType == QGradient::RadialGradient ) + { + QRadialGradient radialGradient( r.center(), qMin( r.width(), r.height() ) ); + radialGradient.setStops( stops ); + + painter->setPen( QPen( radialGradient, m_width, Qt::SolidLine, Qt::FlatCap ) ); + painter->drawArc( r, startAngle * 16, spanAngle * 16 ); + } + else + { + QConicalGradient conicalGradient( r.center(), startAngle ); + conicalGradient.setStops( stops ); + + painter->setPen( QPen( conicalGradient, m_width, Qt::SolidLine, Qt::FlatCap ) ); + painter->drawArc( r, startAngle * 16, spanAngle * 16 ); + } + } + + virtual uint hash() const override + { + uint h = qHash( m_gradientType ); + h = qHash( m_width, h ); + h = qHash( m_value, h ); + h = qHash( m_origin, h ); + h = qHash( m_maximum, h ); + h = qHash( m_isIndeterminate, h ); + h = qHash( m_position, h ); + + for( const QskGradientStop& stop : m_gradient.stops() ) + { + h = stop.hash( h ); + } + + return h; + } + + private: + QskGradient m_gradient; + QGradient::Type m_gradientType; + double m_width; + double m_value; + double m_origin; + double m_maximum; + bool m_isIndeterminate; + double m_position; + }; +} + +CircularProgressBarSkinlet::CircularProgressBarSkinlet( QskSkin* skin ) + : QskSkinlet( skin ) +{ + setNodeRoles( { GrooveRole, BarRole } ); +} + +CircularProgressBarSkinlet::~CircularProgressBarSkinlet() +{ +} + +QRectF CircularProgressBarSkinlet::subControlRect( + const QskSkinnable* /*skinnable*/, const QRectF& contentsRect, + QskAspect::Subcontrol /*subControl*/ ) const +{ + return contentsRect; +} + +QSGNode* CircularProgressBarSkinlet::updateSubNode( + const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const +{ + const auto bar = static_cast< const CircularProgressBar* >( skinnable ); + + switch( nodeRole ) + { + case GrooveRole: // fall through + case BarRole: + { + return updateBarNode( bar, nodeRole, node ); + } + } + + return Inherited::updateSubNode( skinnable, nodeRole, node ); +} + +QSGNode* CircularProgressBarSkinlet::updateBarNode( const CircularProgressBar* bar, quint8 nodeRole, QSGNode* node ) const +{ + auto arcNode = static_cast< ArcNode* >( node ); + + if( arcNode == nullptr ) + { + arcNode = new ArcNode(); + } + + const auto subControl = ( nodeRole == GrooveRole ) ? CircularProgressBar::Groove + : CircularProgressBar::Bar; + + const QskGradient gradient = bar->gradientHint( subControl ); + + const QGradient::Type type = ( nodeRole == GrooveRole ) ? + QGradient::RadialGradient : QGradient::ConicalGradient; + + const double width = bar->metric( subControl | QskAspect::Size ); + const double value = ( nodeRole == GrooveRole ) ? bar->maximum() : bar->value(); + + arcNode->setGradient( gradient ); + arcNode->setGradientType( type ); + arcNode->setWidth( width ); + arcNode->setOrigin( bar->origin() ); + arcNode->setMaximum( bar->maximum() ); + arcNode->setIndeterminate( bar->isIndeterminate() ); + + if( bar->isIndeterminate() ) + { + const double position = bar->metric( CircularProgressBar::Bar | QskAspect::Position ); + arcNode->setPosition( position ); + } + else + { + arcNode->setValue( value ); + } + + QQuickWindow* window = bar->window(); + const QRect rect = bar->contentsRect().toRect(); + arcNode->update( window, QskTextureRenderer::AutoDetect, rect ); + + return arcNode; +} + +#include "moc_CircularProgressBarSkinlet.cpp" diff --git a/examples/iotdashboard/CircularProgressBarSkinlet.h b/examples/iotdashboard/CircularProgressBarSkinlet.h new file mode 100644 index 00000000..f7789fe8 --- /dev/null +++ b/examples/iotdashboard/CircularProgressBarSkinlet.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2021 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#pragma once + +#include + +class CircularProgressBar; + +class CircularProgressBarSkinlet : public QskSkinlet +{ + Q_GADGET + + using Inherited = QskSkinlet; + + 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; + + private: + QSGNode* updateBarNode( const CircularProgressBar*, quint8 nodeRole, QSGNode* ) const; +}; diff --git a/examples/iotdashboard/PieChartPainted.cpp b/examples/iotdashboard/PieChartPainted.cpp index d6e2e23f..a23c34e0 100644 --- a/examples/iotdashboard/PieChartPainted.cpp +++ b/examples/iotdashboard/PieChartPainted.cpp @@ -47,7 +47,6 @@ class ProgressBarAnimator : public QskAnimator void setup() override { m_backgroundColor = m_pieChart->color( PieChartPainted::Panel ); - m_ringGradient = m_progressBar->ringGradient(); } void advance( qreal value ) override @@ -68,7 +67,6 @@ class ProgressBarAnimator : public QskAnimator newGradient.setColorAt( stop.first, newColor ); } - m_progressBar->setRingGradient( newGradient ); m_progressBar->update(); } @@ -83,13 +81,16 @@ PieChartPainted::PieChartPainted( const QColor& color, const QskGradient& gradie : QskControl( parent ) , m_color( color ) , m_gradient( gradient ) - , m_progressBar( new CircularProgressBar( gradient, progress, this ) ) + , m_progressBar( new CircularProgressBar( this ) ) , m_progressLabel( new QskTextLabel( this ) ) , m_animator( new ProgressBarAnimator( this, m_progressBar ) ) { setAutoLayoutChildren( true ); setSubcontrolProxy( QskBox::Panel, PieChartPainted::Panel ); + m_progressBar->setGradientHint( CircularProgressBar::Bar, gradient ); + m_progressBar->setValue( progress ); + auto progressText = QString::number( progress ) + " %"; m_progressLabel->setText( progressText ); m_progressLabel->setFontRole( QskSkin::SmallFont ); @@ -109,7 +110,6 @@ QSizeF PieChartPainted::contentsSizeHint( Qt::SizeHint /*sizeHint*/, const QSize void PieChartPainted::updateLayout() { - m_progressBar->setContentsSize( size().toSize() ); m_progressBar->update(); const auto rect = layoutRect(); diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index acf051ab..de524ade 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -7,6 +7,8 @@ #include "Box.h" #include "BoxWithButtons.h" +#include "CircularProgressBar.h" +#include "CircularProgressBarSkinlet.h" #include "Diagram.h" #include "DiagramSkinlet.h" #include "LightIntensity.h" @@ -48,6 +50,7 @@ namespace Skin::Skin( const Palette& palette, QObject* parent ) : QskSkin( parent ) { + declareSkinlet< CircularProgressBar, CircularProgressBarSkinlet >(); declareSkinlet< Diagram, DiagramSkinlet >(); initHints( palette ); @@ -104,10 +107,15 @@ void Skin::initHints( const Palette& palette ) ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, "#f99055" ); ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, "#6776ff" ); - ed.setGradient( TopBarItem::Item1, { Qt::Horizontal, "#FF5C00", "#FF3122" } ); - ed.setGradient( TopBarItem::Item2, { Qt::Horizontal, "#6776FF", "#6100FF" } ); - ed.setGradient( TopBarItem::Item3, { Qt::Horizontal, "#FFCE50", "#FF3122" } ); - ed.setGradient( TopBarItem::Item4, { Qt::Horizontal, "#6776FF", "#6100FF" } ); + // conical gradients are counterclockwise, so specify the 2nd color first: + ed.setGradient( TopBarItem::Item1, { Qt::Horizontal, "#FF3122", "#FF5C00" } ); + ed.setGradient( TopBarItem::Item2, { Qt::Horizontal, "#6100FF", "#6776FF" } ); + ed.setGradient( TopBarItem::Item3, { Qt::Horizontal, "#FF3122", "#FFCE50" } ); + ed.setGradient( TopBarItem::Item4, { Qt::Horizontal, "#6100FF", "#6776FF" } ); + + // the bar gradient is defined through the top bar items above + ed.setMetricHint( CircularProgressBar::Groove | QskAspect::Size, 8.53 ); + ed.setMetricHint( CircularProgressBar::Bar | QskAspect::Size, 8.53 ); ed.setFontRole( TimeTitleLabel::Text, Skin::TitleFont ); @@ -180,4 +188,5 @@ void Skin::initHints( const Palette& palette ) ed.setColor( QskTextLabel::Text, palette.text ); ed.setColor( UsageDiagramBox::DayText, palette.text ); ed.setColor( ShadowPositioner::Panel, palette.shadow ); + ed.setGradient( CircularProgressBar::Groove, palette.circularProgressBarGroove ); } diff --git a/examples/iotdashboard/Skin.h b/examples/iotdashboard/Skin.h index f6b0f1ea..ba3bf163 100644 --- a/examples/iotdashboard/Skin.h +++ b/examples/iotdashboard/Skin.h @@ -17,7 +17,8 @@ class Skin : public QskSkin Palette( const QskGradient& menuBar, const QskGradient& mainContent, const QskGradient& box, const QColor& lightDisplay, const QColor& pieChart, const QskGradient& roundButton, const QColor& weekdayBox, - const QColor& text, const QColor& shadow ) + const QColor& text, const QColor& shadow, + const QskGradient& circularProgressBarGroove ) : menuBar( menuBar ) , mainContent( mainContent ) , box( box ) @@ -27,6 +28,7 @@ class Skin : public QskSkin , weekdayBox( weekdayBox ) , text( text ) , shadow( shadow ) + , circularProgressBarGroove( circularProgressBarGroove ) { } QskGradient menuBar; @@ -38,6 +40,7 @@ class Skin : public QskSkin QColor weekdayBox; QColor text; QColor shadow; + QskGradient circularProgressBarGroove; }; Skin( const Palette& palette, QObject* parent = nullptr ); @@ -59,7 +62,8 @@ class DaytimeSkin : public Skin : Skin( Skin::Palette( {"#6D7BFB"}, {"#fbfbfb"}, {"#ffffff"}, "#ffffff", "#ffffff", {"#f7f7f7"}, - {"#f4f4f4"}, Qt::black, Qt::black ) + {"#f4f4f4"}, Qt::black, Qt::black, + { Qt::Horizontal, { { 0.0, 0xc4c4c4 }, { 0.5, 0xf8f8f8 }, { 1.0, 0xc4c4c4 } } } ) , parent ) { } @@ -72,7 +76,8 @@ class NighttimeSkin : public Skin : Skin( Skin::Palette( {"#2937A7"}, {"#040404"}, {"#000000"}, "#000000", "#000000", {"#0a0a0a"}, - {"#0c0c0c"}, Qt::white, Qt::white ) + {"#0c0c0c"}, Qt::white, Qt::white, + { Qt::Horizontal, { { 0.0, 0x666666 }, { 0.5, 0x222222 }, { 1.0, 0x333333 } } } ) , parent ) { } diff --git a/examples/iotdashboard/iotdashboard.pro b/examples/iotdashboard/iotdashboard.pro index 5ec94ff3..27e7513e 100644 --- a/examples/iotdashboard/iotdashboard.pro +++ b/examples/iotdashboard/iotdashboard.pro @@ -4,6 +4,7 @@ SOURCES += \ Box.cpp \ BoxWithButtons.cpp \ CircularProgressBar.cpp \ + CircularProgressBarSkinlet.cpp \ Diagram.cpp \ DiagramSkinlet.cpp \ LightIntensity.cpp \ @@ -30,6 +31,7 @@ HEADERS += \ Box.h \ BoxWithButtons.h \ CircularProgressBar.h \ + CircularProgressBarSkinlet.h \ Diagram.h \ DiagramSkinlet.h \ LightIntensity.h \