1 //////////////////////////////////////////////////////////////////////////////
2 // oxygenbusyindicatorengine.cpp
3 // handle progress bar busy indicator
4 // -------------------
5 //
6 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
7 //
8 // SPDX-License-Identifier: MIT
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #include "oxygenbusyindicatorengine.h"
12 
13 #include <QVariant>
14 
15 namespace Oxygen
16 {
17 
18     //_______________________________________________
BusyIndicatorEngine(QObject * object)19     BusyIndicatorEngine::BusyIndicatorEngine( QObject* object ):
20         BaseEngine( object )
21     {}
22 
23     //_______________________________________________
registerWidget(QObject * object)24     bool BusyIndicatorEngine::registerWidget( QObject* object )
25     {
26 
27         // check widget validity
28         if( !object ) return false;
29 
30          // create new data class
31         if( !_data.contains( object ) )
32         {
33             _data.insert( object, new BusyIndicatorData( this ) );
34 
35             // connect destruction signal
36             connect( object, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterWidget(QObject*)), Qt::UniqueConnection );
37         }
38 
39         return true;
40 
41     }
42 
43     //____________________________________________________________
isAnimated(const QObject * object)44     bool BusyIndicatorEngine::isAnimated( const QObject* object )
45     {
46 
47         DataMap<BusyIndicatorData>::Value data( BusyIndicatorEngine::data( object ) );
48         return data && data.data()->isAnimated();
49 
50     }
51 
52     //____________________________________________________________
setDuration(int value)53     void BusyIndicatorEngine::setDuration( int value )
54     {
55 
56         if( duration() == value ) return;
57         BaseEngine::setDuration( value );
58 
59         // restart timer with specified time
60         if( _animation )
61         { _animation.data()->setDuration( value*100 ); }
62 
63     }
64 
65     //____________________________________________________________
setAnimated(const QObject * object,bool value)66     void BusyIndicatorEngine::setAnimated( const QObject* object, bool value )
67     {
68 
69         DataMap<BusyIndicatorData>::Value data( BusyIndicatorEngine::data( object ) );
70         if( data )
71         {
72             // update data
73             data.data()->setAnimated( value );
74 
75             // start timer if needed
76             if( value )
77             {
78                 if( !_animation )
79                 {
80 
81                     // create animation if not already there
82                     _animation = new Animation( duration(), this );
83 
84                     // setup
85                     _animation.data()->setStartValue( 0 );
86                     _animation.data()->setEndValue( 1 );
87                     _animation.data()->setTargetObject( this );
88                     _animation.data()->setPropertyName( "value" );
89                     _animation.data()->setLoopCount( -1 );
90                     _animation.data()->setDuration( duration()*100 );
91 
92                 }
93 
94                 // start if  not already running
95                 if( !_animation.data()->isRunning() )
96                 { _animation.data()->start(); }
97 
98             }
99 
100         }
101 
102         return;
103 
104     }
105 
106 
107     //____________________________________________________________
data(const QObject * object)108     DataMap<BusyIndicatorData>::Value BusyIndicatorEngine::data( const QObject* object )
109     { return _data.find( object ).data(); }
110 
111     //_______________________________________________
setValue(qreal value)112     void BusyIndicatorEngine::setValue( qreal value )
113     {
114 
115         // update
116         _value = value;
117 
118         bool animated( false );
119 
120         // loop over objects in map
121         for( DataMap<BusyIndicatorData>::iterator iter = _data.begin(); iter != _data.end(); ++iter )
122         {
123 
124             if( iter.value().data()->isAnimated() )
125             {
126 
127                 // update animation flag
128                 animated = true;
129 
130                 // emit update signal on object
131                 if( const_cast<QObject*>( iter.key() )->inherits( "QQuickStyleItem" ))
132                 {
133 
134                     //QtQuickControls "rerender" method is updateItem
135                     QMetaObject::invokeMethod( const_cast<QObject*>( iter.key() ), "updateItem", Qt::QueuedConnection);
136 
137                 } else {
138 
139                     QMetaObject::invokeMethod( const_cast<QObject*>( iter.key() ), "update", Qt::QueuedConnection);
140 
141                 }
142 
143             }
144 
145         }
146 
147         if( _animation && !animated )
148         {
149             _animation.data()->stop();
150             _animation.data()->deleteLater();
151             _animation.clear();
152         }
153 
154     }
155 
156     //__________________________________________________________
unregisterWidget(QObject * object)157     bool BusyIndicatorEngine::unregisterWidget( QObject* object )
158     {
159         const bool removed( _data.unregisterWidget( object ) );
160         if( _animation && _data.isEmpty() )
161         {
162             _animation.data()->stop();
163             _animation.data()->deleteLater();
164             _animation.clear();
165         }
166 
167         return removed;
168     }
169 
170 }
171