File indexing completed on 2025-04-27 03:58:24

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-09-20
0007  * Description : Managing visibility state with animations
0008  *
0009  * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "itemvisibilitycontroller.h"
0017 
0018 // Qt includes
0019 
0020 #include <QParallelAnimationGroup>
0021 #include <QPropertyAnimation>
0022 
0023 // Local includes
0024 
0025 #include "digikam_debug.h"
0026 
0027 namespace Digikam
0028 {
0029 
0030 ItemVisibilityControllerPropertyObject::ItemVisibilityControllerPropertyObject(QObject* const parent)
0031     : QObject  (parent),
0032       m_opacity(0),
0033       m_visible(false)
0034 {
0035 }
0036 
0037 qreal ItemVisibilityControllerPropertyObject::opacity() const
0038 {
0039     return m_opacity;
0040 }
0041 
0042 void ItemVisibilityControllerPropertyObject::setOpacity(qreal opacity)
0043 {
0044     m_opacity = opacity;
0045 
0046     Q_EMIT opacityChanged();
0047 }
0048 
0049 bool ItemVisibilityControllerPropertyObject::isVisible() const
0050 {
0051     return m_visible;
0052 }
0053 
0054 void ItemVisibilityControllerPropertyObject::setVisible(bool visible)
0055 {
0056     m_visible = visible;
0057 
0058     Q_EMIT visibleChanged();
0059 }
0060 
0061 // ---------------------------------------------------------------------------------
0062 
0063 AnimatedVisibility::AnimatedVisibility(QObject* const parent)
0064     : ItemVisibilityControllerPropertyObject(parent)
0065 {
0066     m_controller = new ItemVisibilityController(this);
0067     m_controller->addItem(this);
0068 }
0069 
0070 ItemVisibilityController* AnimatedVisibility::controller() const
0071 {
0072     return m_controller;
0073 }
0074 
0075 // ---------------------------------------------------------------------------------
0076 
0077 HidingStateChanger::HidingStateChanger(QObject* const parent)
0078     : ItemVisibilityController(parent),
0079       m_object                (nullptr)
0080 {
0081     connect(this, SIGNAL(propertiesAssigned(bool)),
0082             this, SLOT(slotPropertiesAssigned(bool)));
0083 }
0084 
0085 HidingStateChanger::HidingStateChanger(QObject* const target, const QByteArray& property, QObject* const parent)
0086     : ItemVisibilityController(parent)
0087 {
0088     connect(this, SIGNAL(propertiesAssigned(bool)),
0089             this, SLOT(slotPropertiesAssigned(bool)));
0090 
0091     setTargetObject(target);
0092     setPropertyName(property);
0093 
0094     // here, we assume to start with a visible item
0095 
0096     setVisible(true);
0097 }
0098 
0099 void HidingStateChanger::setTargetObject(QObject* const object)
0100 {
0101     m_object = object;
0102 }
0103 
0104 void HidingStateChanger::setPropertyName(const QByteArray& propertyName)
0105 {
0106     m_property = propertyName;
0107 }
0108 
0109 void HidingStateChanger::changeValue(const QVariant& value)
0110 {
0111     m_value = value;
0112 
0113     if (!hasVisibleItems())
0114     {
0115         // shortcut
0116 
0117         slotPropertiesAssigned(false);
0118         slotPropertiesAssigned(true);
0119     }
0120     else
0121     {
0122         hide();
0123     }
0124 }
0125 
0126 void HidingStateChanger::slotPropertiesAssigned(bool visible)
0127 {
0128     if (!visible)
0129     {
0130         if (m_object)
0131         {
0132             m_object->setProperty(m_property.constData(), m_value);
0133         }
0134 
0135         Q_EMIT stateChanged();
0136         show();
0137     }
0138     else
0139     {
0140         Q_EMIT finished();
0141     }
0142 }
0143 
0144 // ---------------------------------------------------------------------------------
0145 
0146 class Q_DECL_HIDDEN AnimationControl
0147 {
0148 public:
0149 
0150     enum Situation
0151     {
0152         MainControl,
0153         IndependentControl,
0154         RemovingControl
0155     };
0156 
0157 public:
0158 
0159     explicit AnimationControl(ItemVisibilityController* const q);
0160     AnimationControl(AnimationControl* const other, QObject* const item);
0161     ~AnimationControl();
0162 
0163     void clear();
0164 
0165     void addItem(QAbstractAnimation* const animation, QObject* const item);
0166     QAbstractAnimation* takeItem(QObject* const item);
0167     void moveTo(AnimationControl* const other, QObject* const item);
0168     void moveAllTo(AnimationControl* const other);
0169 
0170     bool hasItem(QObject* const o) const;
0171     bool hasVisibleItems(ItemVisibilityController::IncludeFadingOutMode mode) const;
0172 
0173     void transitionToVisible(bool show, bool immediately = false);
0174     void animationFinished();
0175 
0176     void syncProperties(QObject* const o);
0177     void connect(QObject* const item);
0178     void disconnect(QObject* const item);
0179 
0180     void setEasingCurve(const QEasingCurve& easing);
0181     void setAnimationDuration(int msecs);
0182 
0183 public:
0184 
0185     QList<QObject*>                 m_items;
0186     QAbstractAnimation*             m_animation;
0187     ItemVisibilityController::State m_state;
0188     Situation                       m_situation;
0189 
0190 private:
0191 
0192     void setVisibleProperty(bool value);
0193     void connect(QAbstractAnimation* const anim);
0194     void disconnect(QAbstractAnimation* const anim);
0195     void moveToGroup();
0196 
0197 private:
0198 
0199     QParallelAnimationGroup*        m_animationGroup;
0200     ItemVisibilityController* const m_q;
0201 };
0202 
0203 AnimationControl::AnimationControl(ItemVisibilityController* const q)
0204     : m_animation     (nullptr),
0205       m_state         (ItemVisibilityController::Hidden),
0206       m_situation     (MainControl),
0207       m_animationGroup(nullptr),
0208       m_q             (q)
0209 {
0210 }
0211 
0212 AnimationControl::AnimationControl(AnimationControl* const other, QObject* const object)
0213     : m_animation     (nullptr),
0214       m_state         (other->m_state),
0215       m_situation     (IndependentControl),
0216       m_animationGroup(nullptr),
0217       m_q             (other->m_q)
0218 {
0219     other->moveTo(this, object);
0220 }
0221 
0222 AnimationControl::~AnimationControl()
0223 {
0224     clear();
0225     delete m_animation;
0226 }
0227 
0228 void AnimationControl::clear()
0229 {
0230     m_state = ItemVisibilityController::Hidden;
0231 
0232     if (m_animation)
0233     {
0234         disconnect(m_animation);
0235     }
0236 
0237     delete m_animation;
0238     m_animation      = nullptr;
0239     m_animationGroup = nullptr; // the same pointer as animation
0240 
0241     Q_FOREACH (QObject* const item, m_items)
0242     {
0243         disconnect(item);
0244     }
0245 
0246     m_items.clear();
0247 }
0248 
0249 void AnimationControl::connect(QObject* const item)
0250 {
0251     m_q->connect(item, SIGNAL(destroyed(QObject*)),
0252                  m_q, SLOT(objectDestroyed(QObject*)));
0253 }
0254 
0255 void AnimationControl::disconnect(QObject* const item)
0256 {
0257     m_q->disconnect(item, SIGNAL(destroyed(QObject*)),
0258                     m_q, SLOT(objectDestroyed(QObject*)));
0259 }
0260 
0261 void AnimationControl::connect(QAbstractAnimation* const anim)
0262 {
0263     m_q->connect(anim, SIGNAL(finished()),
0264                  m_q, SLOT(animationFinished()));
0265 }
0266 
0267 void AnimationControl::disconnect(QAbstractAnimation* const anim)
0268 {
0269     m_q->disconnect(anim, SIGNAL(finished()),
0270                     m_q, SLOT(animationFinished()));
0271 }
0272 
0273 void AnimationControl::moveToGroup()
0274 {
0275     if (!m_animationGroup)
0276     {
0277         m_animationGroup = new QParallelAnimationGroup;
0278         connect(m_animationGroup);
0279 
0280         if (m_animation)
0281         {
0282             disconnect(m_animation);
0283             m_animationGroup->addAnimation(m_animation);
0284         }
0285 
0286         m_animation = m_animationGroup;
0287     }
0288 }
0289 
0290 void AnimationControl::addItem(QAbstractAnimation* const anim, QObject* const item)
0291 {
0292     // Either there is no group but now for the first time two items,
0293     // or the control got empty intermittently, but still has the group installed
0294 
0295     if (!m_items.isEmpty() || m_animationGroup)
0296     {
0297         moveToGroup();
0298         m_animationGroup->addAnimation(anim);
0299     }
0300     else
0301     {
0302         connect(anim);
0303         m_animation = anim;
0304     }
0305 
0306     m_items << item;
0307 }
0308 
0309 QAbstractAnimation* AnimationControl::takeItem(QObject* const item)
0310 {
0311     int index = m_items.indexOf(item);
0312 
0313     if (index == -1)
0314     {
0315         return nullptr;
0316     }
0317 
0318     m_items.removeAt(index);
0319 
0320     if (m_animationGroup)
0321     {
0322         return m_animationGroup->takeAnimation(index);
0323     }
0324     else
0325     {
0326         QAbstractAnimation* const anim = m_animation;
0327         disconnect(m_animation);
0328         m_animation = nullptr;
0329         return anim;
0330     }
0331 }
0332 
0333 void AnimationControl::moveTo(AnimationControl* const other, QObject* const item)
0334 {
0335     QAbstractAnimation* const anim = takeItem(item);
0336 
0337     if (anim)
0338     {
0339         other->addItem(anim, item);
0340     }
0341 }
0342 
0343 void AnimationControl::moveAllTo(AnimationControl* const other)
0344 {
0345     Q_FOREACH (QObject* const item, m_items)
0346     {
0347         moveTo(other, item);
0348     }
0349 }
0350 
0351 bool AnimationControl::hasItem(QObject* const o) const
0352 {
0353     return m_items.contains(o);
0354 }
0355 
0356 bool AnimationControl::hasVisibleItems(ItemVisibilityController::IncludeFadingOutMode mode) const
0357 {
0358     if (m_items.isEmpty())
0359     {
0360         return false;
0361     }
0362 
0363     if (mode == ItemVisibilityController::IncludeFadingOut)
0364     {
0365         return (m_state != ItemVisibilityController::Hidden);
0366     }
0367     else
0368     {
0369         return ((m_state != ItemVisibilityController::Hidden) && (m_state != ItemVisibilityController::FadingOut));
0370     }
0371 }
0372 
0373 void AnimationControl::setVisibleProperty(bool value)
0374 {
0375     Q_FOREACH (QObject* const o, m_items)
0376     {
0377         o->setProperty("visible", value);
0378     }
0379 }
0380 
0381 void AnimationControl::syncProperties(QObject* const o)
0382 {
0383     if (m_state == ItemVisibilityController::Visible || m_state == ItemVisibilityController::FadingIn)
0384     {
0385         o->setProperty("visible", true);
0386         o->setProperty("opacity", 1.0);
0387     }
0388     else
0389     {
0390         o->setProperty("visible", false);
0391         o->setProperty("opacity", 0);
0392     }
0393 }
0394 
0395 void AnimationControl::transitionToVisible(bool show, bool immediately)
0396 {
0397     //qCDebug(DIGIKAM_WIDGETS_LOG) << "state" << state << "show" << show << items.size();
0398 
0399     if (show)
0400     {
0401         if ((m_state == ItemVisibilityController::Visible) || (m_state == ItemVisibilityController::FadingIn))
0402         {
0403             return;
0404         }
0405 
0406         if (m_state == ItemVisibilityController::Hidden)
0407         {
0408             setVisibleProperty(true);
0409         }
0410 
0411         m_state = ItemVisibilityController::FadingIn;
0412     }
0413     else
0414     {
0415         if ((m_state == ItemVisibilityController::Hidden) || (m_state == ItemVisibilityController::FadingOut))
0416         {
0417             return;
0418         }
0419 
0420         m_state = ItemVisibilityController::FadingOut;
0421     }
0422 
0423     if (m_animation)
0424     {
0425         QAbstractAnimation::Direction direction = show ? QAbstractAnimation::Forward
0426                                                        : QAbstractAnimation::Backward;
0427         m_animation->setDirection(direction);
0428 
0429         if (immediately)
0430         {
0431             m_animation->setCurrentTime(show ? m_animation->totalDuration() : 0);
0432         }
0433 
0434         m_animation->start();
0435     }
0436 }
0437 
0438 void AnimationControl::animationFinished()
0439 {
0440     if      (m_state == ItemVisibilityController::FadingOut)
0441     {
0442         setVisibleProperty(false);
0443         m_state = ItemVisibilityController::Hidden;
0444     }
0445     else if (m_state == ItemVisibilityController::FadingIn)
0446     {
0447         m_state = ItemVisibilityController::Visible;
0448     }
0449 }
0450 
0451 void AnimationControl::setEasingCurve(const QEasingCurve& easing)
0452 {
0453     if      (m_animationGroup)
0454     {
0455         for (int i = 0 ; i < m_animationGroup->animationCount() ; ++i)
0456         {
0457             QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animationGroup->animationAt(i));
0458 
0459             if (anim)
0460             {
0461                 anim->setEasingCurve(easing);
0462             }
0463         }
0464     }
0465     else if (m_animation)
0466     {
0467         QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animation);
0468 
0469         if (anim)
0470         {
0471             anim->setEasingCurve(easing);
0472         }
0473     }
0474 }
0475 
0476 void AnimationControl::setAnimationDuration(int msecs)
0477 {
0478     if      (m_animationGroup)
0479     {
0480         for (int i = 0 ; i < m_animationGroup->animationCount() ; ++i)
0481         {
0482             QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animationGroup->animationAt(i));
0483 
0484             if (anim)
0485             {
0486                 anim->setDuration(msecs);
0487             }
0488         }
0489     }
0490     else if (m_animation)
0491     {
0492         QVariantAnimation* const anim = static_cast<QVariantAnimation*>(m_animation);
0493 
0494         if (anim)
0495         {
0496             anim->setDuration(msecs);
0497         }
0498     }
0499 }
0500 
0501 // ---------------------------------------------------------------------------------
0502 
0503 class Q_DECL_HIDDEN ItemVisibilityController::Private
0504 {
0505 public:
0506 
0507     explicit Private(ItemVisibilityController* const qq)
0508         : visible          (false),
0509           shallBeShown     (true),
0510           itemShallBeShown (nullptr),
0511           animationDuration(75),
0512           easingCurve      (QEasingCurve::InOutQuad),
0513           control          (nullptr),
0514           q                (qq)
0515     {
0516     }
0517 
0518 public:
0519 
0520     void              setVisible(bool v, bool immediately);
0521     void              setItemVisible(QObject* const item, bool visible, bool immediately);
0522 
0523     AnimationControl* findInChildren(QObject* const item) const;
0524     AnimationControl* getChild(QObject* const item);
0525     void              cleanupChildren(QAbstractAnimation* const finishedAnimation);
0526 
0527 public:
0528 
0529     bool                            visible;
0530     bool                            shallBeShown;
0531     QObject*                        itemShallBeShown;
0532 
0533     int                             animationDuration;
0534     QEasingCurve                    easingCurve;
0535 
0536     AnimationControl*               control;
0537     QList<AnimationControl*>        childControls;
0538     ItemVisibilityController* const q;
0539 };
0540 
0541 AnimationControl* ItemVisibilityController::Private::findInChildren(QObject* const item) const
0542 {
0543     Q_FOREACH (AnimationControl* const child, childControls)
0544     {
0545         if (child->hasItem(item))
0546         {   // cppcheck-suppress useStlAlgorithm
0547             return child;
0548         }
0549     }
0550 
0551     return nullptr;
0552 }
0553 
0554 AnimationControl* ItemVisibilityController::Private::getChild(QObject* const item)
0555 {
0556     if (!control)
0557     {
0558         return nullptr;
0559     }
0560 
0561     if (control->hasItem(item))
0562     {
0563         AnimationControl* const child = new AnimationControl(control, item);
0564         childControls << child;
0565 
0566         return child;
0567     }
0568     else
0569     {
0570         return findInChildren(item);
0571     }
0572 }
0573 
0574 void ItemVisibilityController::Private::cleanupChildren(QAbstractAnimation* const finishedAnimation)
0575 {
0576     QList<AnimationControl*>::iterator it;
0577 
0578     for (it = childControls.begin() ; it != childControls.end() ; )
0579     {
0580         AnimationControl* child = *it;
0581 
0582         if      ((child->m_state == control->m_state) && (child->m_situation == AnimationControl::IndependentControl))
0583         {
0584             // merge back to main control
0585 
0586             child->moveAllTo(control);
0587             delete child;
0588             it = childControls.erase(it);
0589         }
0590         else if ((child->m_animation == finishedAnimation) && (child->m_situation == AnimationControl::RemovingControl))
0591         {
0592             Q_FOREACH (QObject* const item, child->m_items)
0593             {
0594                 Q_EMIT q->hiddenAndRemoved(item);
0595             }
0596 
0597             delete child;
0598             it = childControls.erase(it);
0599         }
0600         else
0601         {
0602             ++it;
0603         }
0604     }
0605 }
0606 
0607 void ItemVisibilityController::Private::setVisible(bool v, bool immediately)
0608 {
0609     // no check d->visible == visible
0610 
0611     visible = v;
0612 
0613     if (control)
0614     {
0615         control->transitionToVisible(shallBeShown && visible, immediately);
0616     }
0617 
0618     Q_FOREACH (AnimationControl* const child, childControls)
0619     {
0620         if (child->m_situation == AnimationControl::IndependentControl)
0621         {
0622             child->transitionToVisible(shallBeShown && visible, immediately);
0623         }
0624     }
0625 
0626     if (itemShallBeShown)
0627     {
0628         setItemVisible(itemShallBeShown, visible, immediately);
0629     }
0630 }
0631 
0632 void ItemVisibilityController::Private::setItemVisible(QObject* const item, bool visible, bool immediately)
0633 {
0634     AnimationControl* const child = getChild(item);
0635 
0636     if (child)
0637     {
0638         child->transitionToVisible(visible, immediately);
0639     }
0640 }
0641 
0642 // ---------------------------------------------------------------------------------
0643 
0644 ItemVisibilityController::ItemVisibilityController(QObject* const parent)
0645     : QObject(parent),
0646       d      (new Private(this))
0647 {
0648 }
0649 
0650 ItemVisibilityController::~ItemVisibilityController()
0651 {
0652     clear();
0653     delete d->control;
0654     delete d;
0655 }
0656 
0657 QPropertyAnimation* ItemVisibilityController::createAnimation(QObject*)
0658 {
0659     QPropertyAnimation* const anim = new QPropertyAnimation(this);
0660     anim->setPropertyName("opacity");
0661     anim->setStartValue(0);
0662     anim->setEndValue(1.0);
0663     anim->setDuration(d->animationDuration);
0664     anim->setEasingCurve(d->easingCurve);
0665 
0666     return anim;
0667 }
0668 
0669 void ItemVisibilityController::addItem(QObject* item)
0670 {
0671     if (!item)
0672     {
0673         return;
0674     }
0675 
0676     if (!d->control)
0677     {
0678         // initialize main control
0679 
0680         d->control = new AnimationControl(this);
0681         d->control->transitionToVisible(d->shallBeShown && d->visible);
0682     }
0683 
0684     QPropertyAnimation* const anim = createAnimation(item);
0685     anim->setTargetObject(item);
0686     d->control->connect(item);
0687     d->control->syncProperties(item);
0688     d->control->addItem(anim, item);
0689 }
0690 
0691 void ItemVisibilityController::removeItem(QObject* item)
0692 {
0693     if (!item || !d->control)
0694     {
0695         return;
0696     }
0697 
0698     if (d->control->hasItem(item))
0699     {
0700         d->control->disconnect(item);
0701         delete d->control->takeItem(item);
0702     }
0703     else
0704     {
0705         AnimationControl* child = d->findInChildren(item);
0706 
0707         if (child)
0708         {
0709             child->disconnect(item);
0710             d->childControls.removeOne(child);
0711             delete child;
0712         }
0713     }
0714 }
0715 
0716 void ItemVisibilityController::clear()
0717 {
0718     if (d->control)
0719     {
0720         d->control->clear();
0721     }
0722 
0723     Q_FOREACH (AnimationControl* const child, d->childControls)
0724     {
0725         child->clear();
0726     }
0727 
0728     d->childControls.clear();
0729 
0730     d->visible = false;
0731 }
0732 
0733 QList<QObject*> ItemVisibilityController::items() const
0734 {
0735     QList<QObject*> items;
0736 
0737     if (d->control)
0738     {
0739         items = d->control->m_items;
0740     }
0741 
0742     Q_FOREACH (AnimationControl* const child, d->childControls)
0743     {
0744         // cppcheck-suppress useStlAlgorithm
0745         items += child->m_items;
0746     }
0747 
0748     return items;
0749 }
0750 
0751 QList<QObject*> ItemVisibilityController::visibleItems(IncludeFadingOutMode mode) const
0752 {
0753     QList<QObject*> items;
0754 
0755     if (d->control && d->control->hasVisibleItems(mode))
0756     {
0757         items = d->control->m_items;
0758     }
0759 
0760     Q_FOREACH (AnimationControl* const child, d->childControls)
0761     {
0762         if (child->hasVisibleItems(mode))
0763         {
0764             // cppcheck-suppress useStlAlgorithm
0765             items += child->m_items;
0766         }
0767     }
0768 
0769     return items;
0770 }
0771 
0772 bool ItemVisibilityController::shallBeShown() const
0773 {
0774     return d->shallBeShown;
0775 }
0776 
0777 bool ItemVisibilityController::isVisible() const
0778 {
0779     return d->visible;
0780 }
0781 
0782 ItemVisibilityController::State ItemVisibilityController::state() const
0783 {
0784     return (d->control ? d->control->m_state : Hidden);
0785 }
0786 
0787 bool ItemVisibilityController::hasVisibleItems(IncludeFadingOutMode mode) const
0788 {
0789     if (d->control && d->control->hasVisibleItems(mode))
0790     {
0791         return true;
0792     }
0793 
0794     Q_FOREACH (AnimationControl* const child, d->childControls)
0795     {
0796         if (child->hasVisibleItems(mode))
0797         {   // cppcheck-suppress useStlAlgorithm
0798             return true;
0799         }
0800     }
0801 
0802     return false;
0803 }
0804 
0805 void ItemVisibilityController::setEasingCurve(const QEasingCurve& easing)
0806 {
0807     d->easingCurve = easing;
0808 
0809     if (d->control)
0810     {
0811         d->control->setEasingCurve(easing);
0812     }
0813 
0814     Q_FOREACH (AnimationControl* const child, d->childControls)
0815     {
0816         child->setEasingCurve(easing);
0817     }
0818 }
0819 
0820 void ItemVisibilityController::setAnimationDuration(int msecs)
0821 {
0822     d->animationDuration = msecs;
0823 
0824     if (d->control)
0825     {
0826         d->control->setAnimationDuration(msecs);
0827     }
0828 
0829     Q_FOREACH (AnimationControl* const child, d->childControls)
0830     {
0831         child->setAnimationDuration(msecs);
0832     }
0833 }
0834 
0835 void ItemVisibilityController::setShallBeShown(bool shallBeShown)
0836 {
0837     // no check d->shallBeShown == shallBeShown
0838 
0839     d->shallBeShown     = shallBeShown;
0840     d->itemShallBeShown = nullptr;
0841 
0842     // apply
0843 
0844     setVisible(d->visible);
0845 }
0846 
0847 void ItemVisibilityController::setShallBeShownDirectly(bool shallBeShown)
0848 {
0849     // no check d->shallBeShown == shallBeShown
0850 
0851     d->shallBeShown     = shallBeShown;
0852     d->itemShallBeShown = nullptr;
0853 
0854     // apply
0855 
0856     setDirectlyVisible(d->visible);
0857 }
0858 
0859 void ItemVisibilityController::setItemThatShallBeShown(QObject* item)
0860 {
0861     d->itemShallBeShown = item;
0862     d->shallBeShown     = false;
0863     setVisible(d->visible);
0864 }
0865 
0866 void ItemVisibilityController::show()
0867 {
0868     setVisible(true);
0869 }
0870 
0871 void ItemVisibilityController::hide()
0872 {
0873     setVisible(false);
0874 }
0875 
0876 void ItemVisibilityController::setVisible(bool visible)
0877 {
0878     d->setVisible(visible, false);
0879 }
0880 
0881 void ItemVisibilityController::setDirectlyVisible(bool visible)
0882 {
0883     d->setVisible(visible, true);
0884 }
0885 
0886 void ItemVisibilityController::showItem(QObject* item)
0887 {
0888     setItemVisible(item, true);
0889 }
0890 
0891 void ItemVisibilityController::hideItem(QObject* item)
0892 {
0893     setItemVisible(item, false);
0894 }
0895 
0896 void ItemVisibilityController::setItemVisible(QObject* item, bool visible)
0897 {
0898     d->setItemVisible(item, visible, false);
0899 }
0900 
0901 void ItemVisibilityController::setItemDirectlyVisible(QObject* item, bool visible)
0902 {
0903     d->setItemVisible(item, visible, true);
0904 }
0905 
0906 void ItemVisibilityController::hideAndRemoveItem(QObject* item)
0907 {
0908     AnimationControl* const child = d->getChild(item);
0909 
0910     if (child)
0911     {
0912         child->m_situation = AnimationControl::RemovingControl;
0913         child->transitionToVisible(false);
0914     }
0915 }
0916 
0917 void ItemVisibilityController::animationFinished()
0918 {
0919     QAbstractAnimation* const animation = static_cast<QAbstractAnimation*>(sender());
0920 
0921     if (d->control && (d->control->m_animation == animation))
0922     {
0923         d->control->animationFinished();
0924         Q_EMIT propertiesAssigned(d->control->m_state == Visible);
0925     }
0926 
0927     Q_FOREACH (AnimationControl* const child, d->childControls)
0928     {
0929         if (child->m_animation == animation)
0930         {
0931             child->animationFinished();
0932 
0933             Q_FOREACH (QObject* const item, child->m_items)
0934             {
0935                 if (d->control)
0936                 {
0937                     Q_EMIT propertiesAssigned(item, (d->control->m_state == Visible));
0938                 }
0939             }
0940         }
0941     }
0942 
0943     // if a child is now in main state, move again to main control
0944 
0945     d->cleanupChildren(animation);
0946 }
0947 
0948 void ItemVisibilityController::objectDestroyed(QObject* item)
0949 {
0950     removeItem(item);
0951 }
0952 
0953 } // namespace Digikam
0954 
0955 #include "moc_itemvisibilitycontroller.cpp"