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 #ifndef DIGIKAM_ITEM_VISIBILITY_CONTROLLER_H 0017 #define DIGIKAM_ITEM_VISIBILITY_CONTROLLER_H 0018 0019 // Qt includes 0020 0021 #include <QAbstractAnimation> 0022 #include <QVariant> 0023 0024 // Local includes 0025 0026 #include "digikam_export.h" 0027 0028 class QEasingCurve; 0029 class QPropertyAnimation; 0030 0031 namespace Digikam 0032 { 0033 0034 class DIGIKAM_EXPORT ItemVisibilityController : public QObject 0035 { 0036 Q_OBJECT 0037 Q_PROPERTY(bool shallBeShown READ shallBeShown WRITE setShallBeShown) 0038 Q_PROPERTY(bool visible READ isVisible WRITE setVisible) 0039 0040 public: 0041 0042 /** 0043 * This class handles complex visibility situations for items. 0044 * There is a 3-tiered approach: 0045 * 1) shallBeShown determines if the items shall at any time be shown. 0046 * If it is false, items will never be shown. 0047 * Default is true, so you can ignore this setting. 0048 * 2) visible determines if the items shall be shown now. 0049 * Only takes effect if shallBeShown is true. 0050 * Default is false: Initially, controlled items are hidden. 0051 * 3) Opacity and individual item visibility: 0052 * When showing, items are first set to individually visible, 0053 * then their opacity is increased from 0 to 1. 0054 * When hiding, opacity is first decreased from 1 to 0, 0055 * then they are set individually to hidden. 0056 * Different types of items can be handled: 0057 * - a group of items with an "opacity" and "visible" property 0058 * - a single item with an "opacity" and "visible" property 0059 * - a proxy object with these properties (see above) 0060 */ 0061 0062 enum State 0063 { 0064 Hidden, 0065 FadingIn, 0066 Visible, 0067 FadingOut 0068 }; 0069 Q_ENUM(State) 0070 0071 enum IncludeFadingOutMode 0072 { 0073 /// In addition to items visible or fading in, return those fading out 0074 IncludeFadingOut, 0075 0076 /// Do not return those items currently fading out (soon to be hidden) 0077 ExcludeFadingOut 0078 }; 0079 0080 public: 0081 0082 explicit ItemVisibilityController(QObject* const parent = nullptr); 0083 ~ItemVisibilityController() override; 0084 0085 bool shallBeShown() const; 0086 bool isVisible() const; 0087 State state() const; 0088 0089 /** 0090 * This returns the "result" of isVisible and shallBeShown: 0091 * Something is indeed visible on the scene. 0092 * Also returns false if no items are available. 0093 */ 0094 bool hasVisibleItems(IncludeFadingOutMode mode = IncludeFadingOut) const; 0095 0096 /** 0097 * Remove all animations 0098 */ 0099 void clear(); 0100 0101 /** 0102 * Add and remove objects. The given objects shall provide 0103 * an "opacity" and a "visible" property. 0104 * You can, for convenience, use a ItemVisibilityControllerPropertyObject 0105 * as a value container, if your items do not provide these properties directly. 0106 * No ownership is taken, so the objects should live as long as this object 0107 * is used. 0108 */ 0109 void addItem(QObject* object); 0110 void removeItem(QObject* object); 0111 0112 /** 0113 * Returns all items under control 0114 */ 0115 QList<QObject*> items() const; 0116 0117 /** 0118 * Returns all currently visible items. 0119 */ 0120 QList<QObject*> visibleItems(IncludeFadingOutMode mode = IncludeFadingOut) const; 0121 0122 /** 0123 * Allows to change the default parameters of all animations. 0124 */ 0125 void setEasingCurve(const QEasingCurve& easing); 0126 void setAnimationDuration(int msecs); 0127 0128 Q_SIGNALS: 0129 0130 /** 0131 * Emitted when the (main) transition has finished 0132 */ 0133 void propertiesAssigned(bool visible); 0134 0135 /** 0136 * Emitted when a transition for a single item finished 0137 * (see setItemVisible()) 0138 */ 0139 void propertiesAssigned(QObject* item, bool visible); 0140 0141 /** 0142 * Emitted when hideAndRemoveItem has finished 0143 */ 0144 void hiddenAndRemoved(QObject* item); 0145 0146 public Q_SLOTS: 0147 0148 /** 0149 * Adjusts the first condition - the items are shown if shallBeShown is true and isVisible is true 0150 */ 0151 void setShallBeShown(bool shallBeShown); 0152 void setShallBeShownDirectly(bool shallBeShown); 0153 0154 /** 0155 * Sets a single item to be shown. Calling setVisible() will effectively 0156 * effect only this single item, as if calling setItemVisible(). 0157 * Reset by calling with 0 or setShallBeShown(). 0158 */ 0159 void setItemThatShallBeShown(QObject* item); 0160 0161 /** 0162 * Adjusts the main condition. 0163 * All items are affected. 0164 * If any items were shown or hidden separately, they will be resynchronized. 0165 * "Directly" means no animation is employed. 0166 */ 0167 void show(); 0168 void hide(); 0169 void setVisible(bool visible); 0170 void setDirectlyVisible(bool visible); 0171 0172 /** 0173 * Shows or hides a single item. 0174 * The item's status is changed individually. 0175 * The next call to the "global" method will take precedence again. 0176 * "Directly" means no animation is employed. 0177 */ 0178 void showItem(QObject* item); 0179 void hideItem(QObject* item); 0180 void setItemVisible(QObject* item, bool visible); 0181 void setItemDirectlyVisible(QObject* item, bool visible); 0182 0183 /** 0184 * Hide the item, and then remove it. 0185 * When finished, hiddenAndRemoved() is emitted. 0186 */ 0187 void hideAndRemoveItem(QObject* item); 0188 0189 protected: 0190 0191 /** 0192 * Creates the animation for showing and hiding the given item. 0193 * The item is given for information only, you do not need to use it. 0194 * The default implementation creates and animation for "opacity" 0195 * from 0.0 to 1.0, using default easing curve and duration, 0196 * which can and will be changed by setEasingCurve and setAnimationDuration. 0197 */ 0198 virtual QPropertyAnimation* createAnimation(QObject* item); 0199 0200 protected Q_SLOTS: 0201 0202 void animationFinished(); 0203 void objectDestroyed(QObject*); 0204 0205 private: 0206 0207 class Private; 0208 Private* const d; 0209 }; 0210 0211 // ------------------------------------------------------------------------------------------ 0212 0213 class DIGIKAM_EXPORT ItemVisibilityControllerPropertyObject : public QObject 0214 { 0215 Q_OBJECT 0216 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) 0217 Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) 0218 0219 public: 0220 0221 /** 0222 * You can use this object as a container providing the properties 0223 * set by ItemVisibilityController. 0224 * Connect to the signals accordingly, e.g. to trigger a repaint. 0225 */ 0226 0227 explicit ItemVisibilityControllerPropertyObject(QObject* const parent = nullptr); 0228 0229 qreal opacity() const; 0230 void setOpacity(qreal opacity); 0231 0232 bool isVisible() const; 0233 void setVisible(bool visible); 0234 0235 Q_SIGNALS: 0236 0237 void opacityChanged(); 0238 void visibleChanged(); 0239 0240 protected: 0241 0242 qreal m_opacity; 0243 bool m_visible; 0244 }; 0245 0246 // ------------------------------------------------------------------------------------------ 0247 0248 class DIGIKAM_EXPORT AnimatedVisibility : public ItemVisibilityControllerPropertyObject 0249 { 0250 Q_OBJECT 0251 0252 public: 0253 0254 /** A convenience class: 0255 * The property object brings its own controller. 0256 * Ready to use: Just construct an object and connect to the signals. 0257 * Please note the difference between controller()->setVisible() and setVisible(): 0258 * You want to call the controller's method! 0259 */ 0260 0261 explicit AnimatedVisibility(QObject* const parent = nullptr); 0262 0263 ItemVisibilityController* controller() const; 0264 0265 protected: 0266 0267 ItemVisibilityController* m_controller; 0268 }; 0269 0270 // ------------------------------------------------------------------------------------------ 0271 0272 class DIGIKAM_EXPORT HidingStateChanger : public ItemVisibilityController 0273 { 0274 Q_OBJECT 0275 0276 public: 0277 0278 /** 0279 * This class provides a state change while fading in and out: 0280 * When changeValue is called, first the items are hidden, 0281 * when this is finished, the property is assigned to the object. 0282 * Afterwards, the items are shown again. 0283 * Note that the targetObject is not necessarily a controlled item! 0284 */ 0285 0286 explicit HidingStateChanger(QObject* const parent = nullptr); 0287 0288 /** 0289 * Convenience constructor: Sets target and property name 0290 */ 0291 HidingStateChanger(QObject* const target, const QByteArray& property, QObject* const parent = nullptr); 0292 0293 void setTargetObject(QObject* const object); 0294 void setPropertyName(const QByteArray& propertyName); 0295 0296 public Q_SLOTS: 0297 0298 void changeValue(const QVariant& value); 0299 0300 Q_SIGNALS: 0301 0302 /** 0303 * Emitted when the items were hidden and the target object's property changed 0304 */ 0305 void stateChanged(); 0306 0307 /** 0308 * Emitted when the items were hidden, the target object's property changed, and the items shown again 0309 */ 0310 void finished(); 0311 0312 protected Q_SLOTS: 0313 0314 void slotPropertiesAssigned(bool); 0315 0316 protected: 0317 0318 QObject* m_object; 0319 QByteArray m_property; 0320 QVariant m_value; 0321 }; 0322 0323 } // namespace Digikam 0324 0325 #endif // DIGIKAM_ITEM_VISIBILITY_CONTROLLER_H