1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2010-09-20
7 * Description : Managing visibility state with animations
8 *
9 * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10 * Copyright (C) 2012-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "itemvisibilitycontroller.h"
26
27 // Qt includes
28
29 #include <QParallelAnimationGroup>
30 #include <QPropertyAnimation>
31
32 // Local includes
33
34 #include "digikam_debug.h"
35
36 namespace Digikam
37 {
38
ItemVisibilityControllerPropertyObject(QObject * const parent)39 ItemVisibilityControllerPropertyObject::ItemVisibilityControllerPropertyObject(QObject* const parent)
40 : QObject (parent),
41 m_opacity(0),
42 m_visible(false)
43 {
44 }
45
opacity() const46 qreal ItemVisibilityControllerPropertyObject::opacity() const
47 {
48 return m_opacity;
49 }
50
setOpacity(qreal opacity)51 void ItemVisibilityControllerPropertyObject::setOpacity(qreal opacity)
52 {
53 m_opacity = opacity;
54
55 emit opacityChanged();
56 }
57
isVisible() const58 bool ItemVisibilityControllerPropertyObject::isVisible() const
59 {
60 return m_visible;
61 }
62
setVisible(bool visible)63 void ItemVisibilityControllerPropertyObject::setVisible(bool visible)
64 {
65 m_visible = visible;
66
67 emit visibleChanged();
68 }
69
70 // ---------------------------------------------------------------------------------
71
AnimatedVisibility(QObject * const parent)72 AnimatedVisibility::AnimatedVisibility(QObject* const parent)
73 : ItemVisibilityControllerPropertyObject(parent)
74 {
75 m_controller = new ItemVisibilityController(this);
76 m_controller->addItem(this);
77 }
78
controller() const79 ItemVisibilityController* AnimatedVisibility::controller() const
80 {
81 return m_controller;
82 }
83
84 // ---------------------------------------------------------------------------------
85
HidingStateChanger(QObject * const parent)86 HidingStateChanger::HidingStateChanger(QObject* const parent)
87 : ItemVisibilityController(parent),
88 m_object (nullptr)
89 {
90 connect(this, SIGNAL(propertiesAssigned(bool)),
91 this, SLOT(slotPropertiesAssigned(bool)));
92 }
93
HidingStateChanger(QObject * const target,const QByteArray & property,QObject * const parent)94 HidingStateChanger::HidingStateChanger(QObject* const target, const QByteArray& property, QObject* const parent)
95 : ItemVisibilityController(parent)
96 {
97 connect(this, SIGNAL(propertiesAssigned(bool)),
98 this, SLOT(slotPropertiesAssigned(bool)));
99
100 setTargetObject(target);
101 setPropertyName(property);
102
103 // here, we assume to start with a visible item
104
105 setVisible(true);
106 }
107
setTargetObject(QObject * const object)108 void HidingStateChanger::setTargetObject(QObject* const object)
109 {
110 m_object = object;
111 }
112
setPropertyName(const QByteArray & propertyName)113 void HidingStateChanger::setPropertyName(const QByteArray& propertyName)
114 {
115 m_property = propertyName;
116 }
117
changeValue(const QVariant & value)118 void HidingStateChanger::changeValue(const QVariant& value)
119 {
120 m_value = value;
121
122 if (!hasVisibleItems())
123 {
124 // shortcut
125
126 slotPropertiesAssigned(false);
127 slotPropertiesAssigned(true);
128 }
129 else
130 {
131 hide();
132 }
133 }
134
slotPropertiesAssigned(bool visible)135 void HidingStateChanger::slotPropertiesAssigned(bool visible)
136 {
137 if (!visible)
138 {
139 if (m_object)
140 {
141 m_object->setProperty(m_property.constData(), m_value);
142 }
143
144 emit stateChanged();
145 show();
146 }
147 else
148 {
149 emit finished();
150 }
151 }
152
153 // ---------------------------------------------------------------------------------
154
155 class Q_DECL_HIDDEN AnimationControl
156 {
157 public:
158
159 enum Situation
160 {
161 MainControl,
162 IndependentControl,
163 RemovingControl
164 };
165
166 public:
167
168 explicit AnimationControl(ItemVisibilityController* const q);
169 AnimationControl(AnimationControl* const other, QObject* const item);
170 ~AnimationControl();
171
172 void clear();
173
174 void addItem(QAbstractAnimation* const animation, QObject* const item);
175 QAbstractAnimation* takeItem(QObject* const item);
176 void moveTo(AnimationControl* const other, QObject* const item);
177 void moveAllTo(AnimationControl* const other);
178
179 bool hasItem(QObject* const o) const;
180 bool hasVisibleItems(ItemVisibilityController::IncludeFadingOutMode mode) const;
181
182 void transitionToVisible(bool show, bool immediately = false);
183 void animationFinished();
184
185 void syncProperties(QObject* const o);
186 void connect(QObject* const item);
187 void disconnect(QObject* const item);
188
189 void setEasingCurve(const QEasingCurve& easing);
190 void setAnimationDuration(int msecs);
191
192 public:
193
194 QList<QObject*> m_items;
195 QAbstractAnimation* m_animation;
196 ItemVisibilityController::State m_state;
197 Situation m_situation;
198
199 private:
200
201 void setVisibleProperty(bool value);
202 void connect(QAbstractAnimation* const anim);
203 void disconnect(QAbstractAnimation* const anim);
204 void moveToGroup();
205
206 private:
207
208 QParallelAnimationGroup* m_animationGroup;
209 ItemVisibilityController* const m_q;
210 };
211
AnimationControl(ItemVisibilityController * const q)212 AnimationControl::AnimationControl(ItemVisibilityController* const q)
213 : m_animation (nullptr),
214 m_state (ItemVisibilityController::Hidden),
215 m_situation (MainControl),
216 m_animationGroup(nullptr),
217 m_q (q)
218 {
219 }
220
AnimationControl(AnimationControl * const other,QObject * const object)221 AnimationControl::AnimationControl(AnimationControl* const other, QObject* const object)
222 : m_animation (nullptr),
223 m_state (other->m_state),
224 m_situation (IndependentControl),
225 m_animationGroup(nullptr),
226 m_q (other->m_q)
227 {
228 other->moveTo(this, object);
229 }
230
~AnimationControl()231 AnimationControl::~AnimationControl()
232 {
233 clear();
234 delete m_animation;
235 }
236
clear()237 void AnimationControl::clear()
238 {
239 m_state = ItemVisibilityController::Hidden;
240
241 if (m_animation)
242 {
243 disconnect(m_animation);
244 }
245
246 delete m_animation;
247 m_animation = nullptr;
248 m_animationGroup = nullptr; // the same pointer as animation
249
250 foreach (QObject* const item, m_items)
251 {
252 disconnect(item);
253 }
254
255 m_items.clear();
256 }
257
connect(QObject * const item)258 void AnimationControl::connect(QObject* const item)
259 {
260 m_q->connect(item, SIGNAL(destroyed(QObject*)),
261 m_q, SLOT(objectDestroyed(QObject*)));
262 }
263
disconnect(QObject * const item)264 void AnimationControl::disconnect(QObject* const item)
265 {
266 m_q->disconnect(item, SIGNAL(destroyed(QObject*)),
267 m_q, SLOT(objectDestroyed(QObject*)));
268 }
269
connect(QAbstractAnimation * const anim)270 void AnimationControl::connect(QAbstractAnimation* const anim)
271 {
272 m_q->connect(anim, SIGNAL(finished()),
273 m_q, SLOT(animationFinished()));
274 }
275
disconnect(QAbstractAnimation * const anim)276 void AnimationControl::disconnect(QAbstractAnimation* const anim)
277 {
278 m_q->disconnect(anim, SIGNAL(finished()),
279 m_q, SLOT(animationFinished()));
280 }
281
moveToGroup()282 void AnimationControl::moveToGroup()
283 {
284 if (!m_animationGroup)
285 {
286 m_animationGroup = new QParallelAnimationGroup;
287 connect(m_animationGroup);
288
289 if (m_animation)
290 {
291 disconnect(m_animation);
292 m_animationGroup->addAnimation(m_animation);
293 }
294
295 m_animation = m_animationGroup;
296 }
297 }
298
addItem(QAbstractAnimation * const anim,QObject * const item)299 void AnimationControl::addItem(QAbstractAnimation* const anim, QObject* const item)
300 {
301 // Either there is no group but now for the first time two items,
302 // or the control got empty intermittently, but still has the group installed
303
304 if (!m_items.isEmpty() || m_animationGroup)
305 {
306 moveToGroup();
307 m_animationGroup->addAnimation(anim);
308 }
309 else
310 {
311 connect(anim);
312 m_animation = anim;
313 }
314
315 m_items << item;
316 }
317
takeItem(QObject * const item)318 QAbstractAnimation* AnimationControl::takeItem(QObject* const item)
319 {
320 int index = m_items.indexOf(item);
321
322 if (index == -1)
323 {
324 return nullptr;
325 }
326
327 m_items.removeAt(index);
328
329 if (m_animationGroup)
330 {
331 return m_animationGroup->takeAnimation(index);
332 }
333 else
334 {
335 QAbstractAnimation* const anim = m_animation;
336 disconnect(m_animation);
337 m_animation = nullptr;
338 return anim;
339 }
340 }
341
moveTo(AnimationControl * const other,QObject * const item)342 void AnimationControl::moveTo(AnimationControl* const other, QObject* const item)
343 {
344 QAbstractAnimation* const anim = takeItem(item);
345
346 if (anim)
347 {
348 other->addItem(anim, item);
349 }
350 }
351
moveAllTo(AnimationControl * const other)352 void AnimationControl::moveAllTo(AnimationControl* const other)
353 {
354 foreach (QObject* const item, m_items)
355 {
356 moveTo(other, item);
357 }
358 }
359
hasItem(QObject * const o) const360 bool AnimationControl::hasItem(QObject* const o) const
361 {
362 return m_items.contains(o);
363 }
364
hasVisibleItems(ItemVisibilityController::IncludeFadingOutMode mode) const365 bool AnimationControl::hasVisibleItems(ItemVisibilityController::IncludeFadingOutMode mode) const
366 {
367 if (m_items.isEmpty())
368 {
369 return false;
370 }
371
372 if (mode == ItemVisibilityController::IncludeFadingOut)
373 {
374 return (m_state != ItemVisibilityController::Hidden);
375 }
376 else
377 {
378 return ((m_state != ItemVisibilityController::Hidden) && (m_state != ItemVisibilityController::FadingOut));
379 }
380 }
381
setVisibleProperty(bool value)382 void AnimationControl::setVisibleProperty(bool value)
383 {
384 foreach (QObject* const o, m_items)
385 {
386 o->setProperty("visible", value);
387 }
388 }
389
syncProperties(QObject * const o)390 void AnimationControl::syncProperties(QObject* const o)
391 {
392 if (m_state == ItemVisibilityController::Visible || m_state == ItemVisibilityController::FadingIn)
393 {
394 o->setProperty("visible", true);
395 o->setProperty("opacity", 1.0);
396 }
397 else
398 {
399 o->setProperty("visible", false);
400 o->setProperty("opacity", 0);
401 }
402 }
403
transitionToVisible(bool show,bool immediately)404 void AnimationControl::transitionToVisible(bool show, bool immediately)
405 {
406 //qCDebug(DIGIKAM_WIDGETS_LOG) << "state" << state << "show" << show << items.size();
407
408 if (show)
409 {
410 if ((m_state == ItemVisibilityController::Visible) || (m_state == ItemVisibilityController::FadingIn))
411 {
412 return;
413 }
414
415 if (m_state == ItemVisibilityController::Hidden)
416 {
417 setVisibleProperty(true);
418 }
419
420 m_state = ItemVisibilityController::FadingIn;
421 }
422 else
423 {
424 if ((m_state == ItemVisibilityController::Hidden) || (m_state == ItemVisibilityController::FadingOut))
425 {
426 return;
427 }
428
429 m_state = ItemVisibilityController::FadingOut;
430 }
431
432 if (m_animation)
433 {
434 QAbstractAnimation::Direction direction = show ? QAbstractAnimation::Forward
435 : QAbstractAnimation::Backward;
436 m_animation->setDirection(direction);
437
438 if (immediately)
439 {
440 m_animation->setCurrentTime(show ? m_animation->totalDuration() : 0);
441 }
442
443 m_animation->start();
444 }
445 }
446
animationFinished()447 void AnimationControl::animationFinished()
448 {
449 if (m_state == ItemVisibilityController::FadingOut)
450 {
451 setVisibleProperty(false);
452 m_state = ItemVisibilityController::Hidden;
453 }
454 else if (m_state == ItemVisibilityController::FadingIn)
455 {
456 m_state = ItemVisibilityController::Visible;
457 }
458 }
459
setEasingCurve(const QEasingCurve & easing)460 void AnimationControl::setEasingCurve(const QEasingCurve& easing)
461 {
462 if (m_animationGroup)
463 {
464 for (int i = 0 ; i < m_animationGroup->animationCount() ; ++i)
465 {
466 QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animationGroup->animationAt(i));
467
468 if (anim)
469 {
470 anim->setEasingCurve(easing);
471 }
472 }
473 }
474 else if (m_animation)
475 {
476 QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animation);
477
478 if (anim)
479 {
480 anim->setEasingCurve(easing);
481 }
482 }
483 }
484
setAnimationDuration(int msecs)485 void AnimationControl::setAnimationDuration(int msecs)
486 {
487 if (m_animationGroup)
488 {
489 for (int i = 0 ; i < m_animationGroup->animationCount() ; ++i)
490 {
491 QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animationGroup->animationAt(i));
492
493 if (anim)
494 {
495 anim->setDuration(msecs);
496 }
497 }
498 }
499 else if (m_animation)
500 {
501 QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animation);
502
503 if (anim)
504 {
505 anim->setDuration(msecs);
506 }
507 }
508 }
509
510 // ---------------------------------------------------------------------------------
511
512 class Q_DECL_HIDDEN ItemVisibilityController::Private
513 {
514 public:
515
Private(ItemVisibilityController * const qq)516 explicit Private(ItemVisibilityController* const qq)
517 : visible (false),
518 shallBeShown (true),
519 itemShallBeShown (nullptr),
520 animationDuration(75),
521 easingCurve (QEasingCurve::InOutQuad),
522 control (nullptr),
523 q (qq)
524 {
525 }
526
527 public:
528
529 void setVisible(bool v, bool immediately);
530 void setItemVisible(QObject* const item, bool visible, bool immediately);
531
532 AnimationControl* findInChildren(QObject* const item) const;
533 AnimationControl* getChild(QObject* const item);
534 void cleanupChildren(QAbstractAnimation* const finishedAnimation);
535
536 public:
537
538 bool visible;
539 bool shallBeShown;
540 QObject* itemShallBeShown;
541
542 int animationDuration;
543 QEasingCurve easingCurve;
544
545 AnimationControl* control;
546 QList<AnimationControl*> childControls;
547 ItemVisibilityController* const q;
548 };
549
findInChildren(QObject * const item) const550 AnimationControl* ItemVisibilityController::Private::findInChildren(QObject* const item) const
551 {
552 foreach (AnimationControl* const child, childControls)
553 {
554 if (child->hasItem(item))
555 {
556 return child;
557 }
558 }
559
560 return nullptr;
561 }
562
getChild(QObject * const item)563 AnimationControl* ItemVisibilityController::Private::getChild(QObject* const item)
564 {
565 if (!control)
566 {
567 return nullptr;
568 }
569
570 if (control->hasItem(item))
571 {
572 AnimationControl* const child = new AnimationControl(control, item);
573 childControls << child;
574
575 return child;
576 }
577 else
578 {
579 return findInChildren(item);
580 }
581 }
582
cleanupChildren(QAbstractAnimation * const finishedAnimation)583 void ItemVisibilityController::Private::cleanupChildren(QAbstractAnimation* const finishedAnimation)
584 {
585 QList<AnimationControl*>::iterator it;
586
587 for (it = childControls.begin() ; it != childControls.end() ; )
588 {
589 AnimationControl* child = *it;
590
591 if ((child->m_state == control->m_state) && (child->m_situation == AnimationControl::IndependentControl))
592 {
593 // merge back to main control
594
595 child->moveAllTo(control);
596 delete child;
597 it = childControls.erase(it);
598 }
599 else if ((child->m_animation == finishedAnimation) && (child->m_situation == AnimationControl::RemovingControl))
600 {
601 foreach (QObject* const item, child->m_items)
602 {
603 emit q->hiddenAndRemoved(item);
604 }
605
606 delete child;
607 it = childControls.erase(it);
608 }
609 else
610 {
611 ++it;
612 }
613 }
614 }
615
setVisible(bool v,bool immediately)616 void ItemVisibilityController::Private::setVisible(bool v, bool immediately)
617 {
618 // no check d->visible == visible
619
620 visible = v;
621
622 if (control)
623 {
624 control->transitionToVisible(shallBeShown && visible, immediately);
625 }
626
627 foreach (AnimationControl* const child, childControls)
628 {
629 if (child->m_situation == AnimationControl::IndependentControl)
630 {
631 child->transitionToVisible(shallBeShown && visible, immediately);
632 }
633 }
634
635 if (itemShallBeShown)
636 {
637 setItemVisible(itemShallBeShown, visible, immediately);
638 }
639 }
640
setItemVisible(QObject * const item,bool visible,bool immediately)641 void ItemVisibilityController::Private::setItemVisible(QObject* const item, bool visible, bool immediately)
642 {
643 AnimationControl* const child = getChild(item);
644
645 if (child)
646 {
647 child->transitionToVisible(visible, immediately);
648 }
649 }
650
651 // ---------------------------------------------------------------------------------
652
ItemVisibilityController(QObject * const parent)653 ItemVisibilityController::ItemVisibilityController(QObject* const parent)
654 : QObject(parent),
655 d (new Private(this))
656 {
657 }
658
~ItemVisibilityController()659 ItemVisibilityController::~ItemVisibilityController()
660 {
661 clear();
662 delete d->control;
663 delete d;
664 }
665
createAnimation(QObject *)666 QPropertyAnimation* ItemVisibilityController::createAnimation(QObject*)
667 {
668 QPropertyAnimation* const anim = new QPropertyAnimation(this);
669 anim->setPropertyName("opacity");
670 anim->setStartValue(0);
671 anim->setEndValue(1.0);
672 anim->setDuration(d->animationDuration);
673 anim->setEasingCurve(d->easingCurve);
674
675 return anim;
676 }
677
addItem(QObject * item)678 void ItemVisibilityController::addItem(QObject* item)
679 {
680 if (!item)
681 {
682 return;
683 }
684
685 if (!d->control)
686 {
687 // initialize main control
688
689 d->control = new AnimationControl(this);
690 d->control->transitionToVisible(d->shallBeShown && d->visible);
691 }
692
693 QPropertyAnimation* const anim = createAnimation(item);
694 anim->setTargetObject(item);
695 d->control->connect(item);
696 d->control->syncProperties(item);
697 d->control->addItem(anim, item);
698 }
699
removeItem(QObject * item)700 void ItemVisibilityController::removeItem(QObject* item)
701 {
702 if (!item || !d->control)
703 {
704 return;
705 }
706
707 if (d->control->hasItem(item))
708 {
709 d->control->disconnect(item);
710 delete d->control->takeItem(item);
711 }
712 else
713 {
714 AnimationControl* child = d->findInChildren(item);
715
716 if (child)
717 {
718 child->disconnect(item);
719 d->childControls.removeOne(child);
720 delete child;
721 }
722 }
723 }
724
clear()725 void ItemVisibilityController::clear()
726 {
727 if (d->control)
728 {
729 d->control->clear();
730 }
731
732 foreach (AnimationControl* const child, d->childControls)
733 {
734 child->clear();
735 }
736
737 d->childControls.clear();
738
739 d->visible = false;
740 }
741
items() const742 QList<QObject*> ItemVisibilityController::items() const
743 {
744 QList<QObject*> items;
745
746 if (d->control)
747 {
748 items = d->control->m_items;
749 }
750
751 foreach (AnimationControl* const child, d->childControls)
752 {
753 items += child->m_items;
754 }
755
756 return items;
757 }
758
visibleItems(IncludeFadingOutMode mode) const759 QList<QObject*> ItemVisibilityController::visibleItems(IncludeFadingOutMode mode) const
760 {
761 QList<QObject*> items;
762
763 if (d->control && d->control->hasVisibleItems(mode))
764 {
765 items = d->control->m_items;
766 }
767
768 foreach (AnimationControl* const child, d->childControls)
769 {
770 if (child->hasVisibleItems(mode))
771 {
772 items += child->m_items;
773 }
774 }
775
776 return items;
777 }
778
shallBeShown() const779 bool ItemVisibilityController::shallBeShown() const
780 {
781 return d->shallBeShown;
782 }
783
isVisible() const784 bool ItemVisibilityController::isVisible() const
785 {
786 return d->visible;
787 }
788
state() const789 ItemVisibilityController::State ItemVisibilityController::state() const
790 {
791 return (d->control ? d->control->m_state : Hidden);
792 }
793
hasVisibleItems(IncludeFadingOutMode mode) const794 bool ItemVisibilityController::hasVisibleItems(IncludeFadingOutMode mode) const
795 {
796 if (d->control && d->control->hasVisibleItems(mode))
797 {
798 return true;
799 }
800
801 foreach (AnimationControl* const child, d->childControls)
802 {
803 if (child->hasVisibleItems(mode))
804 {
805 return true;
806 }
807 }
808
809 return false;
810 }
811
setEasingCurve(const QEasingCurve & easing)812 void ItemVisibilityController::setEasingCurve(const QEasingCurve& easing)
813 {
814 d->easingCurve = easing;
815
816 if (d->control)
817 {
818 d->control->setEasingCurve(easing);
819 }
820
821 foreach (AnimationControl* const child, d->childControls)
822 {
823 child->setEasingCurve(easing);
824 }
825 }
826
setAnimationDuration(int msecs)827 void ItemVisibilityController::setAnimationDuration(int msecs)
828 {
829 d->animationDuration = msecs;
830
831 if (d->control)
832 {
833 d->control->setAnimationDuration(msecs);
834 }
835
836 foreach (AnimationControl* const child, d->childControls)
837 {
838 child->setAnimationDuration(msecs);
839 }
840 }
841
setShallBeShown(bool shallBeShown)842 void ItemVisibilityController::setShallBeShown(bool shallBeShown)
843 {
844 // no check d->shallBeShown == shallBeShown
845
846 d->shallBeShown = shallBeShown;
847 d->itemShallBeShown = nullptr;
848
849 // apply
850
851 setVisible(d->visible);
852 }
853
setShallBeShownDirectly(bool shallBeShown)854 void ItemVisibilityController::setShallBeShownDirectly(bool shallBeShown)
855 {
856 // no check d->shallBeShown == shallBeShown
857
858 d->shallBeShown = shallBeShown;
859 d->itemShallBeShown = nullptr;
860
861 // apply
862
863 setDirectlyVisible(d->visible);
864 }
865
setItemThatShallBeShown(QObject * item)866 void ItemVisibilityController::setItemThatShallBeShown(QObject* item)
867 {
868 d->itemShallBeShown = item;
869 d->shallBeShown = false;
870 setVisible(d->visible);
871 }
872
show()873 void ItemVisibilityController::show()
874 {
875 setVisible(true);
876 }
877
hide()878 void ItemVisibilityController::hide()
879 {
880 setVisible(false);
881 }
882
setVisible(bool visible)883 void ItemVisibilityController::setVisible(bool visible)
884 {
885 d->setVisible(visible, false);
886 }
887
setDirectlyVisible(bool visible)888 void ItemVisibilityController::setDirectlyVisible(bool visible)
889 {
890 d->setVisible(visible, true);
891 }
892
showItem(QObject * item)893 void ItemVisibilityController::showItem(QObject* item)
894 {
895 setItemVisible(item, true);
896 }
897
hideItem(QObject * item)898 void ItemVisibilityController::hideItem(QObject* item)
899 {
900 setItemVisible(item, false);
901 }
902
setItemVisible(QObject * item,bool visible)903 void ItemVisibilityController::setItemVisible(QObject* item, bool visible)
904 {
905 d->setItemVisible(item, visible, false);
906 }
907
setItemDirectlyVisible(QObject * item,bool visible)908 void ItemVisibilityController::setItemDirectlyVisible(QObject* item, bool visible)
909 {
910 d->setItemVisible(item, visible, true);
911 }
912
hideAndRemoveItem(QObject * item)913 void ItemVisibilityController::hideAndRemoveItem(QObject* item)
914 {
915 AnimationControl* const child = d->getChild(item);
916
917 if (child)
918 {
919 child->m_situation = AnimationControl::RemovingControl;
920 child->transitionToVisible(false);
921 }
922 }
923
animationFinished()924 void ItemVisibilityController::animationFinished()
925 {
926 QAbstractAnimation* const animation = static_cast<QAbstractAnimation*>(sender());
927
928 if (d->control && (d->control->m_animation == animation))
929 {
930 d->control->animationFinished();
931 emit propertiesAssigned(d->control->m_state == Visible);
932 }
933
934 foreach (AnimationControl* const child, d->childControls)
935 {
936 if (child->m_animation == animation)
937 {
938 child->animationFinished();
939
940 foreach (QObject* const item, child->m_items)
941 {
942 if (d->control)
943 {
944 emit propertiesAssigned(item, (d->control->m_state == Visible));
945 }
946 }
947 }
948 }
949
950 // if a child is now in main state, move again to main control
951
952 d->cleanupChildren(animation);
953 }
954
objectDestroyed(QObject * item)955 void ItemVisibilityController::objectDestroyed(QObject* item)
956 {
957 removeItem(item);
958 }
959
960 } // namespace Digikam
961