1 //////////////////////////////////////////////////////////////////////////////
2 // oxygenanimations.cpp
3 // container for all animation engines
4 // -------------------
5 //
6 // SPDX-FileCopyrightText: 2006, 2007 Riccardo Iaconelli <riccardo@kde.org>
7 // SPDX-FileCopyrightText: 2006, 2007 Casper Boemann <cbr@boemann.dk>
8 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
9 //
10 // SPDX-License-Identifier: MIT
11 //////////////////////////////////////////////////////////////////////////////
12 
13 #include "oxygenanimations.h"
14 #include "oxygenpropertynames.h"
15 #include "oxygenstyleconfigdata.h"
16 
17 #include <QAbstractItemView>
18 #include <QComboBox>
19 #include <QDial>
20 #include <QHeaderView>
21 #include <QLineEdit>
22 #include <QMainWindow>
23 #include <QMdiSubWindow>
24 #include <QProgressBar>
25 #include <QScrollBar>
26 #include <QSpinBox>
27 #include <QSplitterHandle>
28 #include <QTextEdit>
29 #include <QToolBar>
30 #include <QToolBox>
31 #include <QToolButton>
32 #include <QGroupBox>
33 
34 namespace Oxygen
35 {
36 
37     //____________________________________________________________
Animations(QObject * parent)38     Animations::Animations( QObject* parent ):
39         QObject( parent )
40     {
41 
42         _widgetEnableStateEngine = new WidgetStateEngine( this );
43         _spinBoxEngine = new SpinBoxEngine( this );
44         _comboBoxEngine = new WidgetStateEngine( this );
45         _toolButtonEngine = new WidgetStateEngine( this );
46         _toolBoxEngine = new ToolBoxEngine( this );
47         _busyIndicatorEngine = new BusyIndicatorEngine( this );
48 
49         registerEngine( _dockSeparatorEngine = new DockSeparatorEngine( this ) );
50         registerEngine( _headerViewEngine = new HeaderViewEngine( this ) );
51         registerEngine( _widgetStateEngine = new WidgetStateEngine( this ) );
52         registerEngine( _progressBarEngine = new ProgressBarEngine( this ) );
53         registerEngine( _menuBarEngine = new MenuBarEngineV1( this ) );
54         registerEngine( _menuEngine = new MenuEngineV1( this ) );
55         registerEngine( _scrollBarEngine = new ScrollBarEngine( this ) );
56         registerEngine( _inputWidgetEngine = new WidgetStateEngine( this ) );
57         registerEngine( _splitterEngine = new SplitterEngine( this ) );
58         registerEngine( _tabBarEngine = new TabBarEngine( this ) );
59         registerEngine( _toolBarEngine = new ToolBarEngine( this ) );
60         registerEngine( _mdiWindowEngine = new MdiWindowEngine( this ) );
61     }
62 
63     //____________________________________________________________
setupEngines(void)64     void Animations::setupEngines( void )
65     {
66 
67         // animation steps
68         AnimationData::setSteps( StyleConfigData::animationSteps() );
69 
70         {
71             // default enability, duration and maxFrame
72             bool animationsEnabled( StyleConfigData::animationsEnabled() );
73 
74             // enability
75             _widgetEnableStateEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
76             _widgetStateEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
77             _inputWidgetEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
78             _comboBoxEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
79             _toolButtonEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
80             _toolBoxEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
81             _splitterEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
82             _scrollBarEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
83             _spinBoxEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
84             _tabBarEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
85             _dockSeparatorEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
86             _headerViewEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
87             _mdiWindowEngine->setEnabled( animationsEnabled &&  StyleConfigData::genericAnimationsEnabled() );
88             _progressBarEngine->setEnabled( animationsEnabled &&  StyleConfigData::progressBarAnimationsEnabled() );
89 
90             // busy indicator
91             _busyIndicatorEngine->setEnabled( StyleConfigData::progressBarAnimated() );
92 
93             // menubar engine
94             int menuBarAnimationType( StyleConfigData::menuBarAnimationType() );
95             if( menuBarAnimationType == StyleConfigData::MB_FADE && !qobject_cast<MenuBarEngineV1*>( _menuBarEngine ) )
96             {
97                 if( _menuBarEngine )
98                 {
99 
100                     MenuBarEngineV1* newEngine = new MenuBarEngineV1( this, _menuBarEngine );
101                     registerEngine( newEngine );
102                     _menuBarEngine->deleteLater();
103                     _menuBarEngine = newEngine;
104 
105                 } else registerEngine( _menuBarEngine = new MenuBarEngineV1( this ) );
106 
107             } else if( menuBarAnimationType == StyleConfigData::MB_FOLLOW_MOUSE && !qobject_cast<MenuBarEngineV2*>( _menuBarEngine ) ) {
108 
109                 if( _menuBarEngine )
110                 {
111 
112                     MenuBarEngineV2* newEngine = new MenuBarEngineV2( this, _menuBarEngine );
113                     registerEngine( newEngine );
114                     _menuBarEngine->deleteLater();
115                     _menuBarEngine = newEngine;
116 
117                 } else registerEngine( _menuBarEngine = new MenuBarEngineV1( this ) );
118 
119             }
120 
121             // menu engine
122             int menuAnimationType( StyleConfigData::menuAnimationType() );
123             if( menuAnimationType == StyleConfigData::ME_FADE && !qobject_cast<MenuEngineV1*>( _menuEngine ) )
124             {
125 
126                 if( _menuEngine )
127                 {
128 
129                     MenuEngineV1* newEngine = new MenuEngineV1( this, _menuEngine );
130                     registerEngine( newEngine );
131                     _menuEngine->deleteLater();
132                     _menuEngine = newEngine;
133 
134                 } else registerEngine( _menuEngine = new MenuEngineV1( this ) );
135 
136             } else if( menuAnimationType == StyleConfigData::ME_FOLLOW_MOUSE && !qobject_cast<MenuEngineV2*>( _menuEngine ) ) {
137 
138                 if( _menuEngine )
139                 {
140 
141                     MenuEngineV2* newEngine = new MenuEngineV2( this, _menuEngine );
142                     registerEngine( newEngine );
143                     _menuEngine->deleteLater();
144                     _menuEngine = newEngine;
145 
146                 } else registerEngine( _menuEngine = new MenuEngineV1( this ) );
147 
148             }
149 
150             _menuBarEngine->setEnabled( animationsEnabled && menuBarAnimationType != StyleConfigData::MB_NONE );
151             _menuEngine->setEnabled( animationsEnabled && menuAnimationType != StyleConfigData::ME_NONE );
152 
153             // toolbar engine
154             int toolBarAnimationType( StyleConfigData::toolBarAnimationType() );
155             if( toolBarAnimationType == StyleConfigData::TB_NONE || toolBarAnimationType == StyleConfigData::TB_FOLLOW_MOUSE )
156             {
157 
158                 // disable toolbar engine
159                 _toolBarEngine->setEnabled( animationsEnabled && toolBarAnimationType == StyleConfigData::TB_FOLLOW_MOUSE );
160 
161                 // unregister all toolbuttons that belong to a toolbar
162                 foreach( QWidget* widget, _widgetStateEngine->registeredWidgets( AnimationHover|AnimationFocus ) )
163                 {
164                     if( qobject_cast<QToolButton*>( widget ) && qobject_cast<QToolBar*>( widget->parentWidget() ) )
165                     { _widgetStateEngine->unregisterWidget( widget ); }
166                 }
167 
168             } else if( toolBarAnimationType == StyleConfigData::TB_FADE ) {
169 
170                 // disable toolbar engine
171                 _toolBarEngine->setEnabled( false );
172 
173                 // retrieve all registered toolbars
174                 BaseEngine::WidgetList widgets( _toolBarEngine->registeredWidgets() );
175                 foreach( QWidget* widget, widgets )
176                 {
177                     // get all toolbuttons
178                     foreach( QObject* child, widget->children() )
179                     {
180                         if( QToolButton* toolButton = qobject_cast<QToolButton*>( child ) )
181                         { _widgetStateEngine->registerWidget( toolButton, AnimationHover ); }
182                     }
183                 }
184 
185             }
186 
187         }
188 
189 
190         {
191 
192             // durations
193             _widgetEnableStateEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
194             _widgetStateEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
195             _inputWidgetEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
196             _comboBoxEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
197             _toolButtonEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
198             _toolBoxEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
199             _splitterEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
200             _scrollBarEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
201             _spinBoxEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
202             _tabBarEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
203             _dockSeparatorEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
204             _headerViewEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
205             _mdiWindowEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
206 
207             _progressBarEngine->setDuration( StyleConfigData::progressBarAnimationsDuration() );
208             _busyIndicatorEngine->setDuration( StyleConfigData::progressBarBusyStepDuration() );
209 
210             _toolBarEngine->setDuration( StyleConfigData::genericAnimationsDuration() );
211             _toolBarEngine->setFollowMouseDuration( StyleConfigData::toolBarAnimationsDuration() );
212 
213             _menuBarEngine->setDuration( StyleConfigData::menuBarAnimationsDuration() );
214             _menuBarEngine->setFollowMouseDuration( StyleConfigData::menuBarFollowMouseAnimationsDuration() );
215 
216             _menuEngine->setDuration( StyleConfigData::menuAnimationsDuration() );
217             _menuEngine->setFollowMouseDuration( StyleConfigData::menuFollowMouseAnimationsDuration() );
218 
219         }
220 
221     }
222 
223     //____________________________________________________________
registerWidget(QWidget * widget) const224     void Animations::registerWidget( QWidget* widget ) const
225     {
226 
227         if( !widget ) return;
228 
229         // check against noAnimations propery
230         QVariant propertyValue( widget->property( PropertyNames::noAnimations ) );
231         if( propertyValue.isValid() && propertyValue.toBool() ) return;
232 
233         // these are needed to not register animations for kwin widgets
234         if( widget->objectName() == QStringLiteral( "decoration widget" ) ) return;
235         if( widget->inherits( "KCommonDecorationButton" ) ) return;
236         if( widget->inherits( "QShapedPixmapWidget" ) ) return;
237 
238         // all widgets are registered to the enability engine.
239         _widgetEnableStateEngine->registerWidget( widget, AnimationEnable );
240 
241         // install animation timers
242         // for optimization, one should put with most used widgets here first
243         if( qobject_cast<QToolButton*>(widget) )
244         {
245 
246             _toolButtonEngine->registerWidget( widget, AnimationHover );
247             bool isInToolBar( qobject_cast<QToolBar*>(widget->parent()) );
248             if( isInToolBar )
249             {
250 
251                 if( StyleConfigData::toolBarAnimationType() == StyleConfigData::TB_FADE )
252                 { _widgetStateEngine->registerWidget( widget, AnimationHover ); }
253 
254             } else _widgetStateEngine->registerWidget( widget, AnimationHover|AnimationFocus );
255 
256         } else if( qobject_cast<QAbstractButton*>(widget) ) {
257 
258             if( qobject_cast<QToolBox*>( widget->parent() ) )
259             { _toolBoxEngine->registerWidget( widget ); }
260 
261             _widgetStateEngine->registerWidget( widget, AnimationHover|AnimationFocus );
262 
263         } else if( qobject_cast<QDial*>(widget) ) {
264 
265             _widgetStateEngine->registerWidget( widget, AnimationHover|AnimationFocus );
266 
267         }
268 
269         // groupboxes
270         else if( QGroupBox* groupBox = qobject_cast<QGroupBox*>( widget ) )
271         {
272             if( groupBox->isCheckable() )
273             { _widgetStateEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
274         }
275 
276         // scrollbar
277         else if( qobject_cast<QScrollBar*>( widget ) ) { _scrollBarEngine->registerWidget( widget ); }
278         else if( qobject_cast<QSlider*>( widget ) ) { _widgetStateEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
279         else if( qobject_cast<QProgressBar*>( widget ) )
280         {
281             _progressBarEngine->registerWidget( widget );
282             _busyIndicatorEngine->registerWidget( widget );
283         }
284         else if( qobject_cast<QSplitterHandle*>( widget ) ) { _splitterEngine->registerWidget( widget ); }
285         else if( qobject_cast<QMainWindow*>( widget ) ) { _dockSeparatorEngine->registerWidget( widget ); }
286         else if( qobject_cast<QHeaderView*>( widget ) ) { _headerViewEngine->registerWidget( widget ); }
287 
288         // menu
289         else if( qobject_cast<QMenu*>( widget ) ) { _menuEngine->registerWidget( widget ); }
290         else if( qobject_cast<QMenuBar*>( widget ) ) { _menuBarEngine->registerWidget( widget ); }
291         else if( qobject_cast<QTabBar*>( widget ) ) { _tabBarEngine->registerWidget( widget ); }
292         else if( qobject_cast<QToolBar*>( widget ) ) { _toolBarEngine->registerWidget( widget ); }
293 
294         // editors
295         else if( qobject_cast<QComboBox*>( widget ) ) {
296             _comboBoxEngine->registerWidget( widget, AnimationHover );
297             _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus );
298         } else if( qobject_cast<QSpinBox*>( widget ) ) {
299             _spinBoxEngine->registerWidget( widget );
300             _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus );
301         }
302         else if( qobject_cast<QLineEdit*>( widget ) ) { _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
303         else if( qobject_cast<QTextEdit*>( widget ) ) { _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
304         else if( widget->inherits( "KTextEditor::View" ) ) { _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
305 
306         // lists
307         else if( qobject_cast<QAbstractItemView*>( widget ) )
308         { _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
309 
310         // scrollarea
311         else if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>( widget ) ) {
312 
313             if( scrollArea->frameShadow() == QFrame::Sunken && (widget->focusPolicy()&Qt::StrongFocus) )
314             { _inputWidgetEngine->registerWidget( widget, AnimationHover|AnimationFocus ); }
315 
316         }
317 
318         // mdi subwindows
319         else if( qobject_cast<QMdiSubWindow*>( widget ) )
320         { _mdiWindowEngine->registerWidget( widget ); }
321 
322         return;
323 
324     }
325 
326     //____________________________________________________________
unregisterWidget(QWidget * widget) const327     void Animations::unregisterWidget( QWidget* widget ) const
328     {
329 
330         if( !widget ) return;
331 
332         /*
333         these are the engines that have not been stored
334         inside the list, because they can be register widgets in combination
335         with other engines
336         */
337         _widgetEnableStateEngine->unregisterWidget( widget );
338         _spinBoxEngine->unregisterWidget( widget );
339         _comboBoxEngine->unregisterWidget( widget );
340         _toolButtonEngine->unregisterWidget( widget );
341         _toolBoxEngine->unregisterWidget( widget );
342         _busyIndicatorEngine->unregisterWidget( widget );
343 
344         // the following allows some optimization of widget unregistration
345         // it assumes that a widget can be registered atmost in one of the
346         // engines stored in the list.
347         foreach( const BaseEngine::Pointer& engine, _engines )
348         { if( engine && engine.data()->unregisterWidget( widget ) ) break; }
349 
350     }
351 
352     //_______________________________________________________________
unregisterEngine(QObject * object)353     void Animations::unregisterEngine( QObject* object )
354     {
355         int index( _engines.indexOf( qobject_cast<BaseEngine*>(object) ) );
356         if( index >= 0 ) _engines.removeAt( index );
357     }
358 
359     //_______________________________________________________________
registerEngine(BaseEngine * engine)360     void Animations::registerEngine( BaseEngine* engine )
361     {
362         _engines.append( engine );
363         connect( engine, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterEngine(QObject*)) );
364     }
365 
366 }
367