Warning, file /frameworks/kconfigwidgets/src/kconfigdialogmanager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2003 Benjamin C Meyer <ben+kdelibs at meyerhome dot net> 0004 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0005 SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org> 0006 SPDX-FileCopyrightText: 2020 Kevin Ottens <kevin.ottens@enioka.com> 0007 SPDX-FileCopyrightText: 2020 Cyril Rossi <cyril.rossi@enioka.com> 0008 0009 SPDX-License-Identifier: LGPL-2.0-or-later 0010 */ 0011 0012 #include "kconfigdialogmanager.h" 0013 #include "kconfigdialogmanager_p.h" 0014 #include "kconfigwidgets_debug.h" 0015 0016 #include <QComboBox> 0017 #include <QGroupBox> 0018 #include <QLabel> 0019 #include <QLayout> 0020 #include <QMetaObject> 0021 #include <QMetaProperty> 0022 #include <QRadioButton> 0023 #include <QTimer> 0024 0025 #include <KConfigSkeleton> 0026 0027 typedef QHash<QString, QByteArray> MyHash; 0028 Q_GLOBAL_STATIC(MyHash, s_propertyMap) 0029 Q_GLOBAL_STATIC(MyHash, s_changedMap) 0030 0031 KConfigDialogManager::KConfigDialogManager(QWidget *parent, KCoreConfigSkeleton *conf) 0032 : QObject(parent) 0033 , d(new KConfigDialogManagerPrivate(this)) 0034 { 0035 d->m_conf = conf; 0036 d->m_dialog = parent; 0037 init(true); 0038 } 0039 0040 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 84) 0041 KConfigDialogManager::KConfigDialogManager(QWidget *parent, KConfigSkeleton *conf) 0042 : QObject(parent) 0043 , d(new KConfigDialogManagerPrivate(this)) 0044 { 0045 d->m_conf = conf; 0046 d->m_dialog = parent; 0047 init(true); 0048 } 0049 #endif 0050 0051 KConfigDialogManager::~KConfigDialogManager() = default; 0052 0053 // KF6: Drop this and get signals only from metaObject and/or widget's dynamic properties kcfg_property/kcfg_propertyNotify 0054 void KConfigDialogManager::initMaps() 0055 { 0056 if (s_propertyMap()->isEmpty()) { 0057 s_propertyMap()->insert(QStringLiteral("KButtonGroup"), "current"); 0058 s_propertyMap()->insert(QStringLiteral("KColorButton"), "color"); 0059 s_propertyMap()->insert(QStringLiteral("KColorCombo"), "color"); 0060 s_propertyMap()->insert(QStringLiteral("KKeySequenceWidget"), "keySequence"); 0061 } 0062 0063 if (s_changedMap()->isEmpty()) { 0064 // QT 0065 s_changedMap()->insert(QStringLiteral("QCheckBox"), SIGNAL(stateChanged(int))); 0066 s_changedMap()->insert(QStringLiteral("QPushButton"), SIGNAL(clicked(bool))); 0067 s_changedMap()->insert(QStringLiteral("QRadioButton"), SIGNAL(toggled(bool))); 0068 s_changedMap()->insert(QStringLiteral("QGroupBox"), SIGNAL(toggled(bool))); 0069 s_changedMap()->insert(QStringLiteral("QComboBox"), SIGNAL(activated(int))); 0070 s_changedMap()->insert(QStringLiteral("QDateEdit"), SIGNAL(dateChanged(QDate))); 0071 s_changedMap()->insert(QStringLiteral("QTimeEdit"), SIGNAL(timeChanged(QTime))); 0072 s_changedMap()->insert(QStringLiteral("QDateTimeEdit"), SIGNAL(dateTimeChanged(QDateTime))); 0073 s_changedMap()->insert(QStringLiteral("QDial"), SIGNAL(valueChanged(int))); 0074 s_changedMap()->insert(QStringLiteral("QDoubleSpinBox"), SIGNAL(valueChanged(double))); 0075 s_changedMap()->insert(QStringLiteral("QLineEdit"), SIGNAL(textChanged(QString))); 0076 s_changedMap()->insert(QStringLiteral("QSlider"), SIGNAL(valueChanged(int))); 0077 s_changedMap()->insert(QStringLiteral("QSpinBox"), SIGNAL(valueChanged(int))); 0078 s_changedMap()->insert(QStringLiteral("QTextEdit"), SIGNAL(textChanged())); 0079 s_changedMap()->insert(QStringLiteral("QTextBrowser"), SIGNAL(sourceChanged(QString))); 0080 s_changedMap()->insert(QStringLiteral("QPlainTextEdit"), SIGNAL(textChanged())); 0081 s_changedMap()->insert(QStringLiteral("QTabWidget"), SIGNAL(currentChanged(int))); 0082 0083 // KDE 0084 s_changedMap()->insert(QStringLiteral("KComboBox"), SIGNAL(activated(int))); 0085 s_changedMap()->insert(QStringLiteral("KFontComboBox"), SIGNAL(activated(int))); 0086 s_changedMap()->insert(QStringLiteral("KFontRequester"), SIGNAL(fontSelected(QFont))); 0087 s_changedMap()->insert(QStringLiteral("KFontChooser"), SIGNAL(fontSelected(QFont))); 0088 s_changedMap()->insert(QStringLiteral("KColorCombo"), SIGNAL(activated(QColor))); 0089 s_changedMap()->insert(QStringLiteral("KColorButton"), SIGNAL(changed(QColor))); 0090 s_changedMap()->insert(QStringLiteral("KDatePicker"), SIGNAL(dateSelected(QDate))); 0091 s_changedMap()->insert(QStringLiteral("KDateWidget"), SIGNAL(changed(QDate))); 0092 s_changedMap()->insert(QStringLiteral("KDateTimeWidget"), SIGNAL(valueChanged(QDateTime))); 0093 s_changedMap()->insert(QStringLiteral("KEditListWidget"), SIGNAL(changed())); 0094 s_changedMap()->insert(QStringLiteral("KListWidget"), SIGNAL(itemSelectionChanged())); 0095 s_changedMap()->insert(QStringLiteral("KLineEdit"), SIGNAL(textChanged(QString))); 0096 s_changedMap()->insert(QStringLiteral("KRestrictedLine"), SIGNAL(textChanged(QString))); 0097 s_changedMap()->insert(QStringLiteral("KTextEdit"), SIGNAL(textChanged())); 0098 s_changedMap()->insert(QStringLiteral("KUrlRequester"), SIGNAL(textChanged(QString))); 0099 s_changedMap()->insert(QStringLiteral("KUrlComboRequester"), SIGNAL(textChanged(QString))); 0100 s_changedMap()->insert(QStringLiteral("KUrlComboBox"), SIGNAL(urlActivated(QUrl))); 0101 s_changedMap()->insert(QStringLiteral("KButtonGroup"), SIGNAL(changed(int))); 0102 } 0103 } 0104 0105 QHash<QString, QByteArray> *KConfigDialogManager::propertyMap() 0106 { 0107 initMaps(); 0108 return s_propertyMap(); 0109 } 0110 0111 #if KCONFIGWIDGETS_BUILD_DEPRECATED_SINCE(5, 32) 0112 QHash<QString, QByteArray> *KConfigDialogManager::changedMap() 0113 { 0114 initMaps(); 0115 return s_changedMap(); 0116 } 0117 #endif 0118 0119 void KConfigDialogManager::init(bool trackChanges) 0120 { 0121 initMaps(); 0122 d->trackChanges = trackChanges; 0123 0124 // Go through all of the children of the widgets and find all known widgets 0125 (void)parseChildren(d->m_dialog, trackChanges); 0126 } 0127 0128 void KConfigDialogManager::addWidget(QWidget *widget) 0129 { 0130 (void)parseChildren(widget, true); 0131 } 0132 0133 void KConfigDialogManager::setupWidget(QWidget *widget, KConfigSkeletonItem *item) 0134 { 0135 QVariant minValue = item->minValue(); 0136 if (minValue.isValid()) { 0137 // KSelector is using this property 0138 if (widget->metaObject()->indexOfProperty("minValue") != -1) { 0139 widget->setProperty("minValue", minValue); 0140 } 0141 if (widget->metaObject()->indexOfProperty("minimum") != -1) { 0142 widget->setProperty("minimum", minValue); 0143 } 0144 } 0145 QVariant maxValue = item->maxValue(); 0146 if (maxValue.isValid()) { 0147 // KSelector is using this property 0148 if (widget->metaObject()->indexOfProperty("maxValue") != -1) { 0149 widget->setProperty("maxValue", maxValue); 0150 } 0151 if (widget->metaObject()->indexOfProperty("maximum") != -1) { 0152 widget->setProperty("maximum", maxValue); 0153 } 0154 } 0155 0156 if (widget->whatsThis().isEmpty()) { 0157 QString whatsThis = item->whatsThis(); 0158 if (!whatsThis.isEmpty()) { 0159 widget->setWhatsThis(whatsThis); 0160 } 0161 } 0162 0163 if (widget->toolTip().isEmpty()) { 0164 QString toolTip = item->toolTip(); 0165 if (!toolTip.isEmpty()) { 0166 widget->setToolTip(toolTip); 0167 } 0168 } 0169 0170 // If it is a QGroupBox with only autoExclusive buttons 0171 // and has no custom property and the config item type 0172 // is an integer, assume we want to save the index like we did with 0173 // KButtonGroup instead of if it is checked or not 0174 QGroupBox *gb = qobject_cast<QGroupBox *>(widget); 0175 if (gb && getCustomProperty(gb).isEmpty()) { 0176 const KConfigSkeletonItem *item = d->m_conf->findItem(widget->objectName().mid(5)); 0177 if (item->property().type() == QVariant::Int) { 0178 QObjectList children = gb->children(); 0179 children.removeAll(gb->layout()); 0180 const QList<QAbstractButton *> buttons = gb->findChildren<QAbstractButton *>(); 0181 bool allAutoExclusiveDirectChildren = true; 0182 for (QAbstractButton *button : buttons) { 0183 allAutoExclusiveDirectChildren = allAutoExclusiveDirectChildren && button->autoExclusive() && button->parent() == gb; 0184 } 0185 if (allAutoExclusiveDirectChildren) { 0186 d->allExclusiveGroupBoxes << widget; 0187 } 0188 } 0189 } 0190 0191 if (!item->isEqual(property(widget))) { 0192 setProperty(widget, item->property()); 0193 } 0194 0195 d->updateWidgetIndicator(item->name(), widget); 0196 } 0197 0198 bool KConfigDialogManager::parseChildren(const QWidget *widget, bool trackChanges) 0199 { 0200 bool valueChanged = false; 0201 const QList<QObject *> listOfChildren = widget->children(); 0202 if (listOfChildren.isEmpty()) { //?? XXX 0203 return valueChanged; 0204 } 0205 0206 const QMetaMethod onWidgetModifiedSlot = metaObject()->method(metaObject()->indexOfSlot("onWidgetModified()")); 0207 Q_ASSERT(onWidgetModifiedSlot.isValid() && metaObject()->indexOfSlot("onWidgetModified()") >= 0); 0208 0209 for (QObject *object : listOfChildren) { 0210 if (!object->isWidgetType()) { 0211 continue; // Skip non-widgets 0212 } 0213 0214 QWidget *childWidget = static_cast<QWidget *>(object); 0215 0216 QString widgetName = childWidget->objectName(); 0217 bool bParseChildren = true; 0218 bool bSaveInsideGroupBox = d->insideGroupBox; 0219 0220 if (widgetName.startsWith(QLatin1String("kcfg_"))) { 0221 // This is one of our widgets! 0222 QString configId = widgetName.mid(5); 0223 KConfigSkeletonItem *item = d->m_conf->findItem(configId); 0224 if (item) { 0225 d->knownWidget.insert(configId, childWidget); 0226 0227 setupWidget(childWidget, item); 0228 0229 if (trackChanges) { 0230 bool changeSignalFound = false; 0231 0232 if (d->allExclusiveGroupBoxes.contains(childWidget)) { 0233 const QList<QAbstractButton *> buttons = childWidget->findChildren<QAbstractButton *>(); 0234 for (QAbstractButton *button : buttons) { 0235 connect(button, &QAbstractButton::toggled, this, [this] { 0236 d->onWidgetModified(); 0237 }); 0238 } 0239 } 0240 0241 QByteArray propertyChangeSignal = getCustomPropertyChangedSignal(childWidget); 0242 if (propertyChangeSignal.isEmpty()) { 0243 propertyChangeSignal = getUserPropertyChangedSignal(childWidget); 0244 } 0245 0246 if (propertyChangeSignal.isEmpty()) { 0247 // get the change signal from the meta object 0248 const QMetaObject *metaObject = childWidget->metaObject(); 0249 QByteArray userproperty = getCustomProperty(childWidget); 0250 if (userproperty.isEmpty()) { 0251 userproperty = getUserProperty(childWidget); 0252 } 0253 if (!userproperty.isEmpty()) { 0254 const int indexOfProperty = metaObject->indexOfProperty(userproperty.constData()); 0255 if (indexOfProperty != -1) { 0256 const QMetaProperty property = metaObject->property(indexOfProperty); 0257 const QMetaMethod notifySignal = property.notifySignal(); 0258 if (notifySignal.isValid()) { 0259 connect(childWidget, notifySignal, this, onWidgetModifiedSlot); 0260 changeSignalFound = true; 0261 } 0262 } 0263 } else { 0264 qCWarning(KCONFIG_WIDGETS_LOG) << "Don't know how to monitor widget" << childWidget->metaObject()->className() << "for changes!"; 0265 } 0266 } else { 0267 connect(childWidget, propertyChangeSignal.constData(), this, SLOT(onWidgetModified())); 0268 changeSignalFound = true; 0269 } 0270 0271 if (changeSignalFound) { 0272 QComboBox *cb = qobject_cast<QComboBox *>(childWidget); 0273 if (cb && cb->isEditable()) { 0274 connect(cb, &QComboBox::editTextChanged, this, &KConfigDialogManager::widgetModified); 0275 } 0276 } 0277 } 0278 QGroupBox *gb = qobject_cast<QGroupBox *>(childWidget); 0279 if (!gb) { 0280 bParseChildren = false; 0281 } else { 0282 d->insideGroupBox = true; 0283 } 0284 } else { 0285 qCWarning(KCONFIG_WIDGETS_LOG) << "A widget named" << widgetName << "was found but there is no setting named" << configId; 0286 } 0287 } else if (QLabel *label = qobject_cast<QLabel *>(childWidget)) { 0288 QWidget *buddy = label->buddy(); 0289 if (!buddy) { 0290 continue; 0291 } 0292 QString buddyName = buddy->objectName(); 0293 if (buddyName.startsWith(QLatin1String("kcfg_"))) { 0294 // This is one of our widgets! 0295 QString configId = buddyName.mid(5); 0296 d->buddyWidget.insert(configId, childWidget); 0297 } 0298 } 0299 // kf5: commented out to reduce debug output 0300 // #ifndef NDEBUG 0301 // else if (!widgetName.isEmpty() && trackChanges) 0302 // { 0303 // QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap()->constFind(childWidget->metaObject()->className()); 0304 // if (changedIt != s_changedMap()->constEnd()) 0305 // { 0306 // if ((!d->insideGroupBox || !qobject_cast<QRadioButton*>(childWidget)) && 0307 // !qobject_cast<QGroupBox*>(childWidget) &&!qobject_cast<QTabWidget*>(childWidget) ) 0308 // qCDebug(KCONFIG_WIDGETS_LOG) << "Widget '" << widgetName << "' (" << childWidget->metaObject()->className() << ") remains unmanaged."; 0309 // } 0310 // } 0311 // #endif 0312 0313 if (bParseChildren) { 0314 // this widget is not known as something we can store. 0315 // Maybe we can store one of its children. 0316 valueChanged |= parseChildren(childWidget, trackChanges); 0317 } 0318 d->insideGroupBox = bSaveInsideGroupBox; 0319 } 0320 return valueChanged; 0321 } 0322 0323 void KConfigDialogManager::updateWidgets() 0324 { 0325 bool changed = false; 0326 bool bSignalsBlocked = signalsBlocked(); 0327 blockSignals(true); 0328 0329 QWidget *widget; 0330 QHashIterator<QString, QWidget *> it(d->knownWidget); 0331 while (it.hasNext()) { 0332 it.next(); 0333 widget = it.value(); 0334 0335 KConfigSkeletonItem *item = d->m_conf->findItem(it.key()); 0336 if (!item) { 0337 qCWarning(KCONFIG_WIDGETS_LOG) << "The setting" << it.key() << "has disappeared!"; 0338 continue; 0339 } 0340 0341 if (!item->isEqual(property(widget))) { 0342 setProperty(widget, item->property()); 0343 // qCDebug(KCONFIG_WIDGETS_LOG) << "The setting" << it.key() << "[" << widget->className() << "] has changed"; 0344 changed = true; 0345 } 0346 if (item->isImmutable()) { 0347 widget->setEnabled(false); 0348 QWidget *buddy = d->buddyWidget.value(it.key(), nullptr); 0349 if (buddy) { 0350 buddy->setEnabled(false); 0351 } 0352 } 0353 } 0354 blockSignals(bSignalsBlocked); 0355 0356 if (changed) { 0357 QTimer::singleShot(0, this, &KConfigDialogManager::widgetModified); 0358 d->updateAllWidgetIndicators(); 0359 } 0360 } 0361 0362 void KConfigDialogManager::updateWidgetsDefault() 0363 { 0364 bool bUseDefaults = d->m_conf->useDefaults(true); 0365 updateWidgets(); 0366 d->m_conf->useDefaults(bUseDefaults); 0367 d->updateAllWidgetIndicators(); 0368 } 0369 0370 void KConfigDialogManager::setDefaultsIndicatorsVisible(bool enabled) 0371 { 0372 d->setDefaultsIndicatorsVisible(enabled); 0373 } 0374 0375 void KConfigDialogManager::updateSettings() 0376 { 0377 bool changed = false; 0378 0379 QWidget *widget; 0380 QHashIterator<QString, QWidget *> it(d->knownWidget); 0381 while (it.hasNext()) { 0382 it.next(); 0383 widget = it.value(); 0384 0385 KConfigSkeletonItem *item = d->m_conf->findItem(it.key()); 0386 if (!item) { 0387 qCWarning(KCONFIG_WIDGETS_LOG) << "The setting" << it.key() << "has disappeared!"; 0388 continue; 0389 } 0390 0391 QVariant fromWidget = property(widget); 0392 if (!item->isEqual(fromWidget)) { 0393 item->setProperty(fromWidget); 0394 changed = true; 0395 } 0396 } 0397 if (changed) { 0398 d->m_conf->save(); 0399 Q_EMIT settingsChanged(); 0400 d->updateAllWidgetIndicators(); 0401 } 0402 } 0403 0404 QByteArray KConfigDialogManager::getUserProperty(const QWidget *widget) const 0405 { 0406 MyHash *map = s_propertyMap(); 0407 const QMetaObject *metaObject = widget->metaObject(); 0408 const QString className(QLatin1String(metaObject->className())); 0409 auto it = map->find(className); 0410 if (it == map->end()) { 0411 const QMetaProperty userProp = metaObject->userProperty(); 0412 if (userProp.isValid()) { 0413 it = map->insert(className, userProp.name()); 0414 // qCDebug(KCONFIG_WIDGETS_LOG) << "class name: '" << className 0415 //<< " 's USER property: " << metaProperty.name() << endl; 0416 } else { 0417 return QByteArray(); // no USER property 0418 } 0419 } 0420 0421 const QComboBox *cb = qobject_cast<const QComboBox *>(widget); 0422 if (cb) { 0423 const char *qcomboUserPropertyName = cb->QComboBox::metaObject()->userProperty().name(); 0424 const int qcomboUserPropertyIndex = qcomboUserPropertyName ? cb->QComboBox::metaObject()->indexOfProperty(qcomboUserPropertyName) : -1; 0425 const char *widgetUserPropertyName = metaObject->userProperty().name(); 0426 const int widgetUserPropertyIndex = widgetUserPropertyName ? cb->metaObject()->indexOfProperty(widgetUserPropertyName) : -1; 0427 0428 // no custom user property set on subclass of QComboBox? 0429 if (qcomboUserPropertyIndex == widgetUserPropertyIndex) { 0430 return QByteArray(); // use the q/kcombobox special code 0431 } 0432 } 0433 0434 return it != map->end() ? it.value() : QByteArray{}; 0435 } 0436 0437 QByteArray KConfigDialogManager::getCustomProperty(const QWidget *widget) const 0438 { 0439 QVariant prop(widget->property("kcfg_property")); 0440 if (prop.isValid()) { 0441 if (!prop.canConvert(QVariant::ByteArray)) { 0442 qCWarning(KCONFIG_WIDGETS_LOG) << "kcfg_property on" << widget->metaObject()->className() << "is not of type ByteArray"; 0443 } else { 0444 return prop.toByteArray(); 0445 } 0446 } 0447 return QByteArray(); 0448 } 0449 0450 QByteArray KConfigDialogManager::getUserPropertyChangedSignal(const QWidget *widget) const 0451 { 0452 const QString className = QLatin1String(widget->metaObject()->className()); 0453 auto changedIt = s_changedMap()->constFind(className); 0454 0455 if (changedIt == s_changedMap()->constEnd()) { 0456 // If the class name of the widget wasn't in the monitored widgets map, then look for 0457 // it again using the super class name. This fixes a problem with using QtRuby/Korundum 0458 // widgets with KConfigXT where 'Qt::Widget' wasn't being seen a the real deal, even 0459 // though it was a 'QWidget'. 0460 if (widget->metaObject()->superClass()) { 0461 const QString parentClassName = QLatin1String(widget->metaObject()->superClass()->className()); 0462 changedIt = s_changedMap()->constFind(parentClassName); 0463 } 0464 } 0465 0466 return (changedIt == s_changedMap()->constEnd()) ? QByteArray() : *changedIt; 0467 } 0468 0469 QByteArray KConfigDialogManager::getCustomPropertyChangedSignal(const QWidget *widget) const 0470 { 0471 QVariant prop(widget->property("kcfg_propertyNotify")); 0472 if (prop.isValid()) { 0473 if (!prop.canConvert(QVariant::ByteArray)) { 0474 qCWarning(KCONFIG_WIDGETS_LOG) << "kcfg_propertyNotify on" << widget->metaObject()->className() << "is not of type ByteArray"; 0475 } else { 0476 return prop.toByteArray(); 0477 } 0478 } 0479 return QByteArray(); 0480 } 0481 0482 void KConfigDialogManager::setProperty(QWidget *w, const QVariant &v) 0483 { 0484 if (d->allExclusiveGroupBoxes.contains(w)) { 0485 const QList<QAbstractButton *> buttons = w->findChildren<QAbstractButton *>(); 0486 if (v.toInt() < buttons.count()) { 0487 buttons[v.toInt()]->setChecked(true); 0488 } 0489 return; 0490 } 0491 0492 QByteArray userproperty = getCustomProperty(w); 0493 if (userproperty.isEmpty()) { 0494 userproperty = getUserProperty(w); 0495 } 0496 if (userproperty.isEmpty()) { 0497 QComboBox *cb = qobject_cast<QComboBox *>(w); 0498 if (cb) { 0499 if (cb->isEditable()) { 0500 int i = cb->findText(v.toString()); 0501 if (i != -1) { 0502 cb->setCurrentIndex(i); 0503 } else { 0504 cb->setEditText(v.toString()); 0505 } 0506 } else { 0507 cb->setCurrentIndex(v.toInt()); 0508 } 0509 return; 0510 } 0511 } 0512 if (userproperty.isEmpty()) { 0513 qCWarning(KCONFIG_WIDGETS_LOG) << w->metaObject()->className() << "widget not handled!"; 0514 return; 0515 } 0516 0517 w->setProperty(userproperty.constData(), v); 0518 } 0519 0520 QVariant KConfigDialogManager::property(QWidget *w) const 0521 { 0522 if (d->allExclusiveGroupBoxes.contains(w)) { 0523 const QList<QAbstractButton *> buttons = w->findChildren<QAbstractButton *>(); 0524 for (int i = 0; i < buttons.count(); ++i) { 0525 if (buttons[i]->isChecked()) { 0526 return i; 0527 } 0528 } 0529 return -1; 0530 } 0531 0532 QByteArray userproperty = getCustomProperty(w); 0533 if (userproperty.isEmpty()) { 0534 userproperty = getUserProperty(w); 0535 } 0536 if (userproperty.isEmpty()) { 0537 QComboBox *cb = qobject_cast<QComboBox *>(w); 0538 if (cb) { 0539 if (cb->isEditable()) { 0540 return QVariant(cb->currentText()); 0541 } else { 0542 return QVariant(cb->currentIndex()); 0543 } 0544 } 0545 } 0546 if (userproperty.isEmpty()) { 0547 qCWarning(KCONFIG_WIDGETS_LOG) << w->metaObject()->className() << "widget not handled!"; 0548 return QVariant(); 0549 } 0550 0551 return w->property(userproperty.constData()); 0552 } 0553 0554 bool KConfigDialogManager::hasChanged() const 0555 { 0556 QWidget *widget; 0557 QHashIterator<QString, QWidget *> it(d->knownWidget); 0558 while (it.hasNext()) { 0559 it.next(); 0560 widget = it.value(); 0561 0562 KConfigSkeletonItem *item = d->m_conf->findItem(it.key()); 0563 if (!item) { 0564 qCWarning(KCONFIG_WIDGETS_LOG) << "The setting" << it.key() << "has disappeared!"; 0565 continue; 0566 } 0567 0568 if (!item->isEqual(property(widget))) { 0569 // qCDebug(KCONFIG_WIDGETS_LOG) << "Widget for '" << it.key() << "' has changed."; 0570 return true; 0571 } 0572 } 0573 return false; 0574 } 0575 0576 bool KConfigDialogManager::isDefault() const 0577 { 0578 QWidget *widget; 0579 QHashIterator<QString, QWidget *> it(d->knownWidget); 0580 while (it.hasNext()) { 0581 it.next(); 0582 widget = it.value(); 0583 0584 KConfigSkeletonItem *item = d->m_conf->findItem(it.key()); 0585 if (!item) { 0586 qCWarning(KCONFIG_WIDGETS_LOG) << "The setting" << it.key() << "has disappeared!"; 0587 continue; 0588 } 0589 0590 if (property(widget) != item->getDefault()) { 0591 return false; 0592 } 0593 } 0594 return true; 0595 } 0596 0597 KConfigDialogManagerPrivate::KConfigDialogManagerPrivate(KConfigDialogManager *qq) 0598 : q(qq) 0599 , insideGroupBox(false) 0600 , defaultsIndicatorsVisible(false) 0601 { 0602 } 0603 0604 void KConfigDialogManagerPrivate::setDefaultsIndicatorsVisible(bool enabled) 0605 { 0606 if (defaultsIndicatorsVisible != enabled) { 0607 defaultsIndicatorsVisible = enabled; 0608 updateAllWidgetIndicators(); 0609 } 0610 } 0611 0612 void KConfigDialogManagerPrivate::onWidgetModified() 0613 { 0614 const auto widget = qobject_cast<QWidget *>(q->sender()); 0615 Q_ASSERT(widget); 0616 0617 const QLatin1String prefix("kcfg_"); 0618 QString configId = widget->objectName(); 0619 if (configId.startsWith(prefix)) { 0620 configId.remove(0, prefix.size()); 0621 updateWidgetIndicator(configId, widget); 0622 } else { 0623 auto *parent = qobject_cast<QWidget *>(widget->parent()); 0624 Q_ASSERT(parent); 0625 configId = parent->objectName(); 0626 Q_ASSERT(configId.startsWith(prefix)); 0627 configId.remove(0, prefix.size()); 0628 updateWidgetIndicator(configId, parent); 0629 } 0630 0631 Q_EMIT q->widgetModified(); 0632 } 0633 0634 void KConfigDialogManagerPrivate::updateWidgetIndicator(const QString &configId, QWidget *widget) 0635 { 0636 const auto item = m_conf->findItem(configId); 0637 Q_ASSERT(item); 0638 0639 const auto widgetValue = q->property(widget); 0640 const auto defaultValue = item->getDefault(); 0641 0642 const auto defaulted = widgetValue == defaultValue; 0643 0644 if (allExclusiveGroupBoxes.contains(widget)) { 0645 const QList<QAbstractButton *> buttons = widget->findChildren<QAbstractButton *>(); 0646 for (int i = 0; i < buttons.count(); i++) { 0647 const auto value = widgetValue.toInt() == i && !defaulted && defaultsIndicatorsVisible; 0648 buttons.at(i)->setProperty("_kde_highlight_neutral", value); 0649 buttons.at(i)->update(); 0650 } 0651 } else { 0652 widget->setProperty("_kde_highlight_neutral", !defaulted && defaultsIndicatorsVisible); 0653 widget->update(); 0654 } 0655 } 0656 0657 void KConfigDialogManagerPrivate::updateAllWidgetIndicators() 0658 { 0659 QHashIterator<QString, QWidget *> it(knownWidget); 0660 while (it.hasNext()) { 0661 it.next(); 0662 updateWidgetIndicator(it.key(), it.value()); 0663 } 0664 } 0665 0666 #include "moc_kconfigdialogmanager.cpp"