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

0001 /* ============================================================
0002  *
0003  * This file is a part of digikam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-20-12
0007  * Description : Interface class for objects that can store their state.
0008  *
0009  * SPDX-FileCopyrightText: 2009 by Johannes Wienke <languitar at semipol dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "statesavingobject.h"
0016 
0017 // KDE includes
0018 
0019 #include <kconfiggroup.h>
0020 #include <ksharedconfig.h>
0021 
0022 // Local includes
0023 
0024 #include "digikam_debug.h"
0025 
0026 namespace Digikam
0027 {
0028 
0029 class Q_DECL_HIDDEN StateSavingObject::Private
0030 {
0031 public:
0032 
0033     explicit Private()
0034       : host    (nullptr),
0035         group   (),
0036         prefix  (),
0037         groupSet(false),
0038         depth   (StateSavingObject::INSTANCE)
0039     {
0040     }
0041 
0042     inline KConfigGroup getGroupFromObjectName()
0043     {
0044         KSharedConfig::Ptr config = KSharedConfig::openConfig();
0045 
0046         if (host->objectName().isEmpty())
0047         {
0048             qCWarning(DIGIKAM_WIDGETS_LOG) << "Object name for " << host
0049                                            << " is empty. Returning the default config group";
0050         }
0051 
0052         return config->group(host->objectName());
0053     }
0054 
0055     void recurse(const QObjectList& children, const bool save)
0056     {
0057         for (QObjectList::const_iterator childIt = children.constBegin() ;
0058              childIt != children.constEnd() ; ++childIt)
0059         {
0060             StateSavingObject* const statefulChild = dynamic_cast<StateSavingObject*>(*childIt);
0061 
0062             if (statefulChild)
0063             {
0064                 // if the child implements the interface, it can be save /
0065                 // restored
0066 
0067                 // but before invoking these actions, avoid duplicate calls to
0068                 // the methods of deeper children
0069 
0070                 const StateSavingObject::StateSavingDepth oldState = statefulChild->getStateSavingDepth();
0071                 statefulChild->setStateSavingDepth(StateSavingObject::INSTANCE);
0072 
0073                 // decide which action to invoke
0074 
0075                 if (save)
0076                 {
0077                     statefulChild->saveState();
0078                 }
0079                 else
0080                 {
0081                     statefulChild->loadState();
0082                 }
0083 
0084                 statefulChild->setStateSavingDepth(oldState);
0085             }
0086 
0087             // recurse children every time
0088 
0089             recurse((*childIt)->children(), save);
0090         }
0091     }
0092 
0093     void recurseOperation(const bool save)
0094     {
0095         QString action = QLatin1String("loading");
0096 
0097         if (save)
0098         {
0099             action = QLatin1String("saving");
0100         }
0101 
0102         if      (depth == StateSavingObject::DIRECT_CHILDREN)
0103         {
0104             //qCDebug(DIGIKAM_WIDGETS_LOG) << "Also restoring " << action << " of direct children";
0105 
0106             for (QObjectList::const_iterator childIt = host->children().begin() ;
0107                  childIt != host->children().end() ; ++childIt)
0108             {
0109                 StateSavingObject* const statefulChild = dynamic_cast<StateSavingObject*>(*childIt);
0110 
0111                 if (statefulChild)
0112                 {
0113                     if (save)
0114                     {
0115                         statefulChild->saveState();
0116                     }
0117                     else
0118                     {
0119                         statefulChild->loadState();
0120                     }
0121                 }
0122             }
0123         }
0124         else if (depth == StateSavingObject::RECURSIVE)
0125         {
0126             //qCDebug(DIGIKAM_WIDGETS_LOG) << "Also " << action << " state of all children (recursive)";
0127             recurse(host->children(), save);
0128         }
0129     }
0130 
0131 public:
0132 
0133     QObject*                            host;
0134     KConfigGroup                        group;
0135     QString                             prefix;
0136     bool                                groupSet;
0137     StateSavingObject::StateSavingDepth depth;
0138 };
0139 
0140 StateSavingObject::StateSavingObject(QObject* const host)
0141     : d(new Private)
0142 {
0143     d->host = host;
0144 
0145     // we cannot safely create the default config group here, because the host
0146     // may not have been properly initialized or its object name is set after
0147     // the constructor call
0148 }
0149 
0150 StateSavingObject::~StateSavingObject()
0151 {
0152     delete d;
0153 }
0154 
0155 StateSavingObject::StateSavingDepth StateSavingObject::getStateSavingDepth() const
0156 {
0157     return d->depth;
0158 }
0159 
0160 void StateSavingObject::setStateSavingDepth(const StateSavingObject::StateSavingDepth depth)
0161 {
0162     d->depth = depth;
0163 }
0164 
0165 void StateSavingObject::setConfigGroup(const KConfigGroup& group)
0166 {
0167 /*
0168     qCDebug(DIGIKAM_WIDGETS_LOG) << "received new config group: " << group.name();
0169 */
0170     d->group    = group;
0171     d->groupSet = true;
0172 }
0173 
0174 void StateSavingObject::setEntryPrefix(const QString& prefix)
0175 {
0176     d->prefix = prefix;
0177 }
0178 
0179 void StateSavingObject::loadState()
0180 {
0181 /*
0182     qCDebug(DIGIKAM_WIDGETS_LOG) << "Loading state";
0183 */
0184     doLoadState();
0185 
0186     d->recurseOperation(false);
0187 }
0188 
0189 void StateSavingObject::saveState()
0190 {
0191 /*
0192     qCDebug(DIGIKAM_WIDGETS_LOG) << "Saving state";
0193 */
0194     doSaveState();
0195 
0196     d->recurseOperation(true);
0197 }
0198 
0199 KConfigGroup StateSavingObject::getConfigGroup() const
0200 {
0201     if (!d->groupSet)
0202     {
0203 /*
0204         qCDebug(DIGIKAM_WIDGETS_LOG) << "No config group set, returning one based on object name";
0205 */
0206         return d->getGroupFromObjectName();
0207     }
0208 
0209     if (!d->group.isValid())
0210     {
0211         qCWarning(DIGIKAM_WIDGETS_LOG) << "KConfigGroup set via setConfigGroup is invalid. "
0212                                        << "Using object name based group.";
0213         return d->getGroupFromObjectName();
0214     }
0215 
0216     return d->group;
0217 }
0218 
0219 QString StateSavingObject::entryName(const QString& base) const
0220 {
0221     return (d->prefix + base);
0222 }
0223 
0224 } // namespace Digikam