File indexing completed on 2025-01-19 03:53:50

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2003-11-03
0007  * Description : Automatic retrieving, saving and resetting skeleton based settings in a dialog.
0008  *
0009  * SPDX-FileCopyrightText: 2019-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2003      by Benjamin C Meyer <ben plus kdelibs at meyerhome dot net>
0011  * SPDX-FileCopyrightText: 2003      by Waldo Bastian <bastian at kde dot org>
0012  * SPDX-FileCopyrightText: 2017      by Friedrich W. H. Kossebau <kossebau at kde dot org>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "dconfigdlgmngr.h"
0019 
0020 // Qt includes
0021 
0022 #include <QComboBox>
0023 #include <QGroupBox>
0024 #include <QLabel>
0025 #include <QMetaObject>
0026 #include <QMetaProperty>
0027 #include <QLayout>
0028 #include <QTimer>
0029 #include <QAbstractButton>
0030 
0031 // KDE includes
0032 
0033 #include <kconfigskeleton.h>
0034 
0035 // Local includes
0036 
0037 #include "digikam_debug.h"
0038 
0039 // clazy:skip
0040 
0041 namespace Digikam
0042 {
0043 
0044 typedef QHash<QString, QByteArray> MyHash;
0045 
0046 Q_GLOBAL_STATIC(MyHash, s_propertyMap)
0047 Q_GLOBAL_STATIC(MyHash, s_changedMap)
0048 
0049 class Q_DECL_HIDDEN DConfigDlgMngr::Private
0050 {
0051 public:
0052 
0053     explicit Private(DConfigDlgMngr* const q)
0054         : q             (q),
0055           conf          (nullptr),
0056           dialog        (nullptr),
0057           insideGroupBox(false),
0058           trackChanges  (false)
0059     {
0060     }
0061 
0062 public:
0063 
0064     DConfigDlgMngr* const    q;
0065 
0066     /**
0067      * Skeleton object used to store settings
0068      */
0069     KConfigSkeleton*         conf;
0070 
0071     /**
0072      * Dialog being managed
0073      */
0074     QWidget*                 dialog;
0075 
0076     QHash<QString, QWidget*> knownWidget;
0077     QHash<QString, QWidget*> buddyWidget;
0078     QSet<QWidget*>           allExclusiveGroupBoxes;
0079     bool                     insideGroupBox;
0080     bool                     trackChanges;
0081 };
0082 
0083 DConfigDlgMngr::DConfigDlgMngr(QWidget* const parent, KConfigSkeleton* const conf)
0084     : QObject(parent),
0085       d      (new Private(this))
0086 {
0087     d->conf   = conf;
0088     d->dialog = parent;
0089     init(true);
0090 }
0091 
0092 DConfigDlgMngr::~DConfigDlgMngr()
0093 {
0094     delete d;
0095 }
0096 
0097 void DConfigDlgMngr::initMaps()
0098 {
0099     if (s_changedMap()->isEmpty())
0100     {
0101         s_changedMap()->insert(QLatin1String("QCheckBox"),      SIGNAL(stateChanged(int)));
0102         s_changedMap()->insert(QLatin1String("QPushButton"),    SIGNAL(clicked(bool)));
0103         s_changedMap()->insert(QLatin1String("QRadioButton"),   SIGNAL(toggled(bool)));
0104         s_changedMap()->insert(QLatin1String("QGroupBox"),      SIGNAL(toggled(bool)));
0105         s_changedMap()->insert(QLatin1String("QComboBox"),      SIGNAL(activated(int)));
0106         s_changedMap()->insert(QLatin1String("QDateEdit"),      SIGNAL(dateChanged(QDate)));
0107         s_changedMap()->insert(QLatin1String("QTimeEdit"),      SIGNAL(timeChanged(QTime)));
0108         s_changedMap()->insert(QLatin1String("QDateTimeEdit"),  SIGNAL(dateTimeChanged(QDateTime)));
0109         s_changedMap()->insert(QLatin1String("QDial"),          SIGNAL(valueChanged(int)));
0110         s_changedMap()->insert(QLatin1String("QDoubleSpinBox"), SIGNAL(valueChanged(double)));
0111         s_changedMap()->insert(QLatin1String("QLineEdit"),      SIGNAL(textChanged(QString)));
0112         s_changedMap()->insert(QLatin1String("QSlider"),        SIGNAL(valueChanged(int)));
0113         s_changedMap()->insert(QLatin1String("QSpinBox"),       SIGNAL(valueChanged(int)));
0114         s_changedMap()->insert(QLatin1String("QTextEdit"),      SIGNAL(textChanged()));
0115         s_changedMap()->insert(QLatin1String("QTextBrowser"),   SIGNAL(sourceChanged(QString)));
0116         s_changedMap()->insert(QLatin1String("QPlainTextEdit"), SIGNAL(textChanged()));
0117         s_changedMap()->insert(QLatin1String("QTabWidget"),     SIGNAL(currentChanged(int)));
0118     }
0119 }
0120 
0121 QHash<QString, QByteArray>* DConfigDlgMngr::propertyMap()
0122 {
0123     initMaps();
0124 
0125     return s_propertyMap();
0126 }
0127 
0128 QHash<QString, QByteArray>* DConfigDlgMngr::changedMap()
0129 {
0130     initMaps();
0131 
0132     return s_changedMap();
0133 }
0134 
0135 void DConfigDlgMngr::init(bool trackChanges)
0136 {
0137     initMaps();
0138     d->trackChanges = trackChanges;
0139 
0140     // Go through all of the children of the widgets and find all known widgets
0141 
0142     (void)parseChildren(d->dialog, trackChanges);
0143 }
0144 
0145 void DConfigDlgMngr::addWidget(QWidget* const widget)
0146 {
0147     (void)parseChildren(widget, true);
0148 }
0149 
0150 void DConfigDlgMngr::setupWidget(QWidget* widget, KConfigSkeletonItem* item)
0151 {
0152     QVariant minValue = item->minValue();
0153 
0154     if (minValue.isValid())
0155     {
0156         if (widget->metaObject()->indexOfProperty("minValue") != -1)
0157         {
0158             widget->setProperty("minValue", minValue);
0159         }
0160 
0161         if (widget->metaObject()->indexOfProperty("minimum") != -1)
0162         {
0163             widget->setProperty("minimum", minValue);
0164         }
0165     }
0166 
0167     QVariant maxValue = item->maxValue();
0168 
0169     if (maxValue.isValid())
0170     {
0171         if (widget->metaObject()->indexOfProperty("maxValue") != -1)
0172         {
0173             widget->setProperty("maxValue", maxValue);
0174         }
0175 
0176         if (widget->metaObject()->indexOfProperty("maximum") != -1)
0177         {
0178             widget->setProperty("maximum", maxValue);
0179         }
0180     }
0181 
0182     if (widget->whatsThis().isEmpty())
0183     {
0184         QString whatsThis = item->whatsThis();
0185 
0186         if (!whatsThis.isEmpty())
0187         {
0188             widget->setWhatsThis(whatsThis);
0189         }
0190     }
0191 
0192     if (widget->toolTip().isEmpty())
0193     {
0194         QString toolTip = item->toolTip();
0195 
0196         if (!toolTip.isEmpty())
0197         {
0198             widget->setToolTip(toolTip);
0199         }
0200     }
0201 
0202     // If it is a QGroupBox with only autoExclusive buttons
0203     // and has no custom property and the config item type
0204     // is an integer, assume we want to save the index
0205     // instead of if it is checked or not
0206 
0207     QGroupBox* const gb = qobject_cast<QGroupBox*>(widget);
0208 
0209     if (gb && getCustomProperty(gb).isEmpty())
0210     {
0211         const KConfigSkeletonItem* const sitem = d->conf->findItem(widget->objectName().mid(5));
0212 
0213 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0214 
0215         if (sitem->property().typeId() == QVariant::Int)
0216 
0217 #else
0218 
0219         if (sitem->property().type() == QVariant::Int)
0220 
0221 #endif
0222 
0223         {
0224             QObjectList children                  = gb->children();
0225             children.removeAll(gb->layout());
0226             const QList<QAbstractButton*> buttons = gb->findChildren<QAbstractButton*>();
0227             bool allAutoExclusiveDirectChildren   = true;
0228 
0229             for (QAbstractButton* const button : buttons)
0230             {
0231                 // cppcheck-suppress useStlAlgorithm
0232                 allAutoExclusiveDirectChildren = (
0233                                                   allAutoExclusiveDirectChildren &&
0234                                                   button->autoExclusive()        &&
0235                                                   (button->parent() == gb)
0236                                                  );
0237             }
0238 
0239             // cppcheck-suppress knownConditionTrueFalse
0240             if (allAutoExclusiveDirectChildren)
0241             {
0242                 d->allExclusiveGroupBoxes << widget;
0243             }
0244         }
0245     }
0246 
0247     if (!item->isEqual(property(widget)))
0248     {
0249         setProperty(widget, item->property());
0250     }
0251 }
0252 
0253 bool DConfigDlgMngr::parseChildren(const QWidget* widget, bool trackChanges)
0254 {
0255     bool valueChanged                    = false;
0256     const QList<QObject*> listOfChildren = widget->children();
0257 
0258     if (listOfChildren.isEmpty())
0259     {
0260         return valueChanged;
0261     }
0262 
0263     const QMetaMethod widgetModifiedSignal = metaObject()->method(metaObject()->indexOfSignal("widgetModified()"));
0264 
0265     Q_ASSERT(widgetModifiedSignal.isValid() && (metaObject()->indexOfSignal("widgetModified()") >= 0));
0266 
0267     for (QObject* const object : listOfChildren)
0268     {
0269         if (!object->isWidgetType())
0270         {
0271             // Skip non-widgets
0272 
0273             continue;
0274         }
0275 
0276         QWidget* const childWidget = static_cast<QWidget*>(object);
0277         QString widgetName         = childWidget->objectName();
0278         bool bParseChildren        = true;
0279         bool bSaveInsideGroupBox   = d->insideGroupBox;
0280 
0281         if      (widgetName.startsWith(QLatin1String("kcfg_")))
0282         {
0283             // This is one of our widgets!
0284 
0285             QString configId                = widgetName.mid(5);
0286             KConfigSkeletonItem* const item = d->conf->findItem(configId);
0287 
0288             if (item)
0289             {
0290                 d->knownWidget.insert(configId, childWidget);
0291 
0292                 setupWidget(childWidget, item);
0293 
0294                 if (trackChanges)
0295                 {
0296                     bool changeSignalFound = false;
0297 
0298                     if (d->allExclusiveGroupBoxes.contains(childWidget))
0299                     {
0300                         const QList<QAbstractButton*> buttons = childWidget->findChildren<QAbstractButton*>();
0301 
0302                         for (QAbstractButton* const button : buttons)
0303                         {
0304                             connect(button, &QAbstractButton::toggled,
0305                                     this, &DConfigDlgMngr::widgetModified);
0306                         }
0307                     }
0308 
0309                     QByteArray propertyChangeSignal = getCustomPropertyChangedSignal(childWidget);
0310 
0311                     if (propertyChangeSignal.isEmpty())
0312                     {
0313                         propertyChangeSignal = getUserPropertyChangedSignal(childWidget);
0314                     }
0315 
0316                     if (propertyChangeSignal.isEmpty())
0317                     {
0318                         // get the change signal from the meta object
0319 
0320                         const QMetaObject* const metaObject = childWidget->metaObject();
0321                         QByteArray userproperty             = getCustomProperty(childWidget);
0322 
0323                         if (userproperty.isEmpty())
0324                         {
0325                             userproperty = getUserProperty(childWidget);
0326                         }
0327 
0328                         if (!userproperty.isEmpty())
0329                         {
0330                             const int indexOfProperty = metaObject->indexOfProperty(userproperty.constData());
0331 
0332                             if (indexOfProperty != -1)
0333                             {
0334                                 const QMetaProperty property   = metaObject->property(indexOfProperty);
0335                                 const QMetaMethod notifySignal = property.notifySignal();
0336 
0337                                 if (notifySignal.isValid())
0338                                 {
0339                                     connect(childWidget, notifySignal,      // clazy:exclude=connect-non-signal
0340                                             this, widgetModifiedSignal);
0341 
0342                                     changeSignalFound = true;
0343                                 }
0344                             }
0345                         }
0346                         else
0347                         {
0348                            qCWarning(DIGIKAM_GENERAL_LOG) << "Don't know how to monitor widget '"
0349                                                           << childWidget->metaObject()->className()
0350                                                           << "' for changes!";
0351                         }
0352                     }
0353                     else
0354                     {
0355                         connect(childWidget, propertyChangeSignal.constData(),
0356                                 this, SIGNAL(widgetModified()));
0357 
0358                         changeSignalFound = true;
0359                     }
0360 
0361                     if (changeSignalFound)
0362                     {
0363                         QComboBox* const cb = qobject_cast<QComboBox*>(childWidget);
0364 
0365                         if (cb && cb->isEditable())
0366                         {
0367                             connect(cb, &QComboBox::editTextChanged,
0368                                     this, &DConfigDlgMngr::widgetModified);
0369                         }
0370                     }
0371                 }
0372 
0373                 QGroupBox* const gb = qobject_cast<QGroupBox*>(childWidget);
0374 
0375                 if (!gb)
0376                 {
0377                     bParseChildren = false;
0378                 }
0379                 else
0380                 {
0381                     d->insideGroupBox = true;
0382                 }
0383             }
0384             else
0385             {
0386                qCWarning(DIGIKAM_GENERAL_LOG) << "A widget named '" << widgetName
0387                                               << "' was found but there is no setting named '"
0388                                               << configId << "'";
0389             }
0390         }
0391         else if (QLabel* const label = qobject_cast<QLabel*>(childWidget))
0392         {
0393             QWidget* const buddy = label->buddy();
0394 
0395             if (!buddy)
0396             {
0397                 continue;
0398             }
0399 
0400             QString buddyName = buddy->objectName();
0401 
0402             if (buddyName.startsWith(QLatin1String("kcfg_")))
0403             {
0404                 // This is one of our widgets!
0405 
0406                 QString configId = buddyName.mid(5);
0407                 d->buddyWidget.insert(configId, childWidget);
0408             }
0409         }
0410 
0411         if (bParseChildren)
0412         {
0413             // this widget is not known as something we can store.
0414             // Maybe we can store one of its children.
0415 
0416             valueChanged |= parseChildren(childWidget, trackChanges);
0417         }
0418 
0419         d->insideGroupBox = bSaveInsideGroupBox;
0420     }
0421 
0422     return valueChanged;
0423 }
0424 
0425 void DConfigDlgMngr::updateWidgets()
0426 {
0427     bool changed         = false;
0428     bool bSignalsBlocked = signalsBlocked();
0429     blockSignals(true);
0430 
0431     QWidget* widget      = nullptr;
0432     QHashIterator<QString, QWidget*> it(d->knownWidget);
0433 
0434     while (it.hasNext())
0435     {
0436         it.next();
0437         widget = it.value();
0438 
0439         KConfigSkeletonItem* const item = d->conf->findItem(it.key());
0440 
0441         if (!item)
0442         {
0443             qCWarning(DIGIKAM_GENERAL_LOG) << "The setting '" << it.key() << "' has disappeared!";
0444             continue;
0445         }
0446 
0447         if (!item->isEqual(property(widget)))
0448         {
0449             setProperty(widget, item->property());
0450             changed = true;
0451         }
0452 
0453         if (item->isImmutable())
0454         {
0455             widget->setEnabled(false);
0456             QWidget* const buddy = d->buddyWidget.value(it.key(), nullptr);
0457 
0458             if (buddy)
0459             {
0460                 buddy->setEnabled(false);
0461             }
0462         }
0463     }
0464 
0465     blockSignals(bSignalsBlocked);
0466 
0467     if (changed)
0468     {
0469         QTimer::singleShot(0, this, &DConfigDlgMngr::widgetModified);
0470     }
0471 }
0472 
0473 void DConfigDlgMngr::updateWidgetsDefault()
0474 {
0475     bool bUseDefaults = d->conf->useDefaults(true);
0476     updateWidgets();
0477     d->conf->useDefaults(bUseDefaults);
0478 }
0479 
0480 void DConfigDlgMngr::updateSettings()
0481 {
0482     bool changed    = false;
0483     QWidget* widget = nullptr;
0484     QHashIterator<QString, QWidget*> it(d->knownWidget);
0485 
0486     while (it.hasNext())
0487     {
0488         it.next();
0489         widget                          = it.value();
0490         KConfigSkeletonItem* const item = d->conf->findItem(it.key());
0491 
0492         if (!item)
0493         {
0494             qCWarning(DIGIKAM_GENERAL_LOG) << "The setting '" << it.key() << "' has disappeared!";
0495             continue;
0496         }
0497 
0498         QVariant fromWidget = property(widget);
0499 
0500         if (!item->isEqual(fromWidget))
0501         {
0502             item->setProperty(fromWidget);
0503             changed = true;
0504         }
0505     }
0506 
0507     if (changed)
0508     {
0509         d->conf->save();
0510         Q_EMIT settingsChanged();
0511     }
0512 }
0513 
0514 QByteArray DConfigDlgMngr::getUserProperty(const QWidget* widget) const
0515 {
0516     if (!s_propertyMap()->contains(QString::fromUtf8(widget->metaObject()->className())))
0517     {
0518         const QMetaObject* const metaObject = widget->metaObject();
0519         const QMetaProperty user            = metaObject->userProperty();
0520 
0521         if (user.isValid())
0522         {
0523             s_propertyMap()->insert(QString::fromUtf8(widget->metaObject()->className()), user.name());
0524         }
0525         else
0526         {
0527             return QByteArray(); // no USER property
0528         }
0529     }
0530 
0531     const QComboBox* const cb = qobject_cast<const QComboBox*>(widget);
0532 
0533     if (cb)
0534     {
0535         const char* const qcomboUserPropertyName = cb->QComboBox::metaObject()->userProperty().name();
0536         const int qcomboUserPropertyIndex        = qcomboUserPropertyName ? cb->QComboBox::metaObject()->indexOfProperty(qcomboUserPropertyName) : -1;
0537         const char* const widgetUserPropertyName = widget->metaObject()->userProperty().name();
0538         const int widgetUserPropertyIndex        = widgetUserPropertyName ? cb->metaObject()->indexOfProperty(widgetUserPropertyName)            : -1;
0539 
0540         // no custom user property set on subclass of QComboBox?
0541 
0542         if (qcomboUserPropertyIndex == widgetUserPropertyIndex)
0543         {
0544             return QByteArray(); // use the QCombobox special code
0545         }
0546     }
0547 
0548     return s_propertyMap()->value(QString::fromUtf8(widget->metaObject()->className()));
0549 }
0550 
0551 QByteArray DConfigDlgMngr::getCustomProperty(const QWidget* widget) const
0552 {
0553     QVariant prop(widget->property("kcfg_property"));
0554 
0555     if (prop.isValid())
0556     {
0557 
0558 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0559 
0560         if (!prop.canConvert(QMetaType(QMetaType::QByteArray)))
0561 
0562 #else
0563 
0564         if (!prop.canConvert(QVariant::ByteArray))
0565 
0566 #endif
0567 
0568         {
0569            qCWarning(DIGIKAM_GENERAL_LOG) << "Property on"
0570                                           << widget->metaObject()->className()
0571                                           << "is not of type ByteArray";
0572         }
0573         else
0574         {
0575             return prop.toByteArray();
0576         }
0577     }
0578 
0579     return QByteArray();
0580 }
0581 
0582 QByteArray DConfigDlgMngr::getUserPropertyChangedSignal(const QWidget* widget) const
0583 {
0584     QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap()->constFind(QString::fromUtf8(widget->metaObject()->className()));
0585 
0586     if (changedIt == s_changedMap()->constEnd())
0587     {
0588         // If the class name of the widget wasn't in the monitored widgets map, then look for
0589         // it again using the super class name.
0590 
0591         if (widget->metaObject()->superClass())
0592         {
0593             changedIt = s_changedMap()->constFind(QString::fromUtf8(widget->metaObject()->superClass()->className()));
0594         }
0595     }
0596 
0597     return ((changedIt == s_changedMap()->constEnd()) ? QByteArray() : *changedIt);
0598 }
0599 
0600 QByteArray DConfigDlgMngr::getCustomPropertyChangedSignal(const QWidget *widget) const
0601 {
0602     QVariant prop(widget->property("kcfg_propertyNotify"));
0603 
0604     if (prop.isValid())
0605     {
0606 
0607 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0608 
0609         if (!prop.canConvert(QMetaType(QMetaType::QByteArray)))
0610 
0611 #else
0612 
0613         if (!prop.canConvert(QVariant::ByteArray))
0614 
0615 #endif
0616 
0617         {
0618            qCWarning(DIGIKAM_GENERAL_LOG) << "PropertyNotify on"
0619                                           << widget->metaObject()->className()
0620                                           << "is not of type ByteArray";
0621         }
0622         else
0623         {
0624             return prop.toByteArray();
0625         }
0626     }
0627 
0628     return QByteArray();
0629 }
0630 
0631 void DConfigDlgMngr::setProperty(QWidget* w, const QVariant& v)
0632 {
0633     if (d->allExclusiveGroupBoxes.contains(w))
0634     {
0635         const QList<QAbstractButton*> buttons = w->findChildren<QAbstractButton*>();
0636 
0637         if (v.toInt() < buttons.count())
0638         {
0639             buttons[v.toInt()]->setChecked(true);
0640         }
0641 
0642         return;
0643     }
0644 
0645     QByteArray userproperty = getCustomProperty(w);
0646 
0647     if (userproperty.isEmpty())
0648     {
0649         userproperty = getUserProperty(w);
0650     }
0651 
0652     if (userproperty.isEmpty())
0653     {
0654         QComboBox* const cb = qobject_cast<QComboBox*>(w);
0655 
0656         if (cb)
0657         {
0658             if (cb->isEditable())
0659             {
0660                 int i = cb->findText(v.toString());
0661 
0662                 if (i != -1)
0663                 {
0664                     cb->setCurrentIndex(i);
0665                 }
0666                 else
0667                 {
0668                     cb->setEditText(v.toString());
0669                 }
0670             }
0671             else
0672             {
0673                 cb->setCurrentIndex(v.toInt());
0674             }
0675 
0676             return;
0677         }
0678     }
0679 
0680     if (userproperty.isEmpty())
0681     {
0682         qCWarning(DIGIKAM_GENERAL_LOG) << w->metaObject()->className() << "widget not handled!";
0683         return;
0684     }
0685 
0686     w->setProperty(userproperty.constData(), v);
0687 }
0688 
0689 QVariant DConfigDlgMngr::property(QWidget* w) const
0690 {
0691     if (d->allExclusiveGroupBoxes.contains(w))
0692     {
0693         const QList<QAbstractButton*> buttons = w->findChildren<QAbstractButton*>();
0694 
0695         for (int i = 0 ; i < buttons.count() ; ++i)
0696         {
0697             if (buttons[i]->isChecked())
0698             {
0699                 return i;
0700             }
0701         }
0702 
0703         return -1;
0704     }
0705 
0706     QByteArray userproperty = getCustomProperty(w);
0707 
0708     if (userproperty.isEmpty())
0709     {
0710         userproperty = getUserProperty(w);
0711     }
0712 
0713     if (userproperty.isEmpty())
0714     {
0715         QComboBox* const cb = qobject_cast<QComboBox*>(w);
0716 
0717         if (cb)
0718         {
0719             if (cb->isEditable())
0720             {
0721                 return QVariant(cb->currentText());
0722             }
0723             else
0724             {
0725                 return QVariant(cb->currentIndex());
0726             }
0727         }
0728     }
0729 
0730     if (userproperty.isEmpty())
0731     {
0732         qCWarning(DIGIKAM_GENERAL_LOG) << w->metaObject()->className() << "widget not handled!";
0733         return QVariant();
0734     }
0735 
0736     return w->property(userproperty.constData());
0737 }
0738 
0739 bool DConfigDlgMngr::hasChanged() const
0740 {
0741     QWidget* widget = nullptr;
0742     QHashIterator<QString, QWidget*> it(d->knownWidget);
0743 
0744     while (it.hasNext())
0745     {
0746         it.next();
0747         widget                          = it.value();
0748         KConfigSkeletonItem* const item = d->conf->findItem(it.key());
0749 
0750         if (!item)
0751         {
0752             qCWarning(DIGIKAM_GENERAL_LOG) << "The setting '" << it.key() << "' has disappeared!";
0753             continue;
0754         }
0755 
0756         if (!item->isEqual(property(widget)))
0757         {
0758             return true;
0759         }
0760     }
0761 
0762     return false;
0763 }
0764 
0765 bool DConfigDlgMngr::isDefault() const
0766 {
0767     bool bUseDefaults = d->conf->useDefaults(true);
0768     bool result       = !hasChanged();
0769     d->conf->useDefaults(bUseDefaults);
0770 
0771     return result;
0772 }
0773 
0774 } // namespace Digikam
0775 
0776 #include "moc_dconfigdlgmngr.cpp"