00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kconfigdialogmanager.h"
00023
00024 #include <QComboBox>
00025 #include <QGroupBox>
00026 #include <QLabel>
00027 #include <QMetaObject>
00028 #include <QMetaProperty>
00029 #include <QTimer>
00030 #include <QRadioButton>
00031
00032
00033 #include <kconfigskeleton.h>
00034 #include <kdebug.h>
00035 #include <kglobal.h>
00036
00037 #include <assert.h>
00038
00039 typedef QHash<QString, QByteArray> MyHash;
00040 K_GLOBAL_STATIC(MyHash, s_propertyMap)
00041 K_GLOBAL_STATIC(MyHash, s_changedMap)
00042
00043 class KConfigDialogManager::Private {
00044
00045 public:
00046 Private(KConfigDialogManager *q) : q(q), insideGroupBox(false) { }
00047
00048 public:
00049 KConfigDialogManager *q;
00050
00051 static int debugArea() { static int s_area = KDebug::registerArea("kdeui (KConfigDialogManager)"); return s_area; }
00052
00056 KConfigSkeleton *m_conf;
00057
00061 QWidget *m_dialog;
00062
00063 QHash<QString, QWidget *> knownWidget;
00064 QHash<QString, QWidget *> buddyWidget;
00065 bool insideGroupBox : 1;
00066 bool trackChanges : 1;
00067 };
00068
00069 KConfigDialogManager::KConfigDialogManager(QWidget *parent, KConfigSkeleton *conf)
00070 : QObject(parent), d(new Private(this))
00071 {
00072 d->m_conf = conf;
00073 d->m_dialog = parent;
00074 init(true);
00075 }
00076
00077 KConfigDialogManager::~KConfigDialogManager()
00078 {
00079 delete d;
00080 }
00081
00082 void KConfigDialogManager::initMaps()
00083 {
00084 if ( s_propertyMap->isEmpty() ) {
00085 s_propertyMap->insert( "KButtonGroup", "current" );
00086 s_propertyMap->insert( "KColorButton", "color" );
00087 s_propertyMap->insert( "KColorCombo", "color" );
00088
00089
00090 }
00091
00092 if( s_changedMap->isEmpty() )
00093 {
00094
00095 s_changedMap->insert("QCheckBox", SIGNAL(stateChanged(int)));
00096 s_changedMap->insert("QPushButton", SIGNAL(clicked(bool)));
00097 s_changedMap->insert("QRadioButton", SIGNAL(toggled(bool)));
00098
00099
00100
00101 s_changedMap->insert("QGroupBox", SIGNAL(toggled(bool)));
00102 s_changedMap->insert("QComboBox", SIGNAL(activated (int)));
00103
00104
00105 s_changedMap->insert("QDateEdit", SIGNAL(dateChanged(const QDate &)));
00106 s_changedMap->insert("QTimeEdit", SIGNAL(timeChanged(const QTime &)));
00107 s_changedMap->insert("QDateTimeEdit", SIGNAL(dateTimeChanged(const QDateTime &)));
00108 s_changedMap->insert("QDial", SIGNAL(valueChanged (int)));
00109 s_changedMap->insert("QDoubleSpinBox", SIGNAL(valueChanged(double)));
00110 s_changedMap->insert("QLineEdit", SIGNAL(textChanged(const QString &)));
00111 s_changedMap->insert("QSlider", SIGNAL(valueChanged(int)));
00112 s_changedMap->insert("QSpinBox", SIGNAL(valueChanged(int)));
00113 s_changedMap->insert("QTextEdit", SIGNAL(textChanged()));
00114 s_changedMap->insert("QTextBrowser", SIGNAL(sourceChanged(const QString &)));
00115 s_changedMap->insert("QTabWidget", SIGNAL(currentChanged(int)));
00116
00117
00118 s_changedMap->insert( "KComboBox", SIGNAL(activated (int)));
00119 s_changedMap->insert( "KFontCombo", SIGNAL(activated (int)));
00120 s_changedMap->insert( "KFontRequester", SIGNAL(fontSelected(const QFont &)));
00121 s_changedMap->insert( "KFontChooser", SIGNAL(fontSelected(const QFont &)));
00122 s_changedMap->insert( "KHistoryCombo", SIGNAL(activated (int)));
00123 s_changedMap->insert( "KColorCombo", SIGNAL(activated (const QColor &)));
00124
00125 s_changedMap->insert( "KColorButton", SIGNAL(changed(const QColor &)));
00126 s_changedMap->insert( "KDatePicker", SIGNAL(dateSelected (QDate)));
00127 s_changedMap->insert( "KDateWidget", SIGNAL(changed (QDate)));
00128 s_changedMap->insert( "KDateTimeWidget", SIGNAL(valueChanged (const QDateTime &)));
00129 s_changedMap->insert( "KEditListBox", SIGNAL(changed()));
00130 s_changedMap->insert( "KListWidget", SIGNAL(itemSelectionChanged()));
00131 s_changedMap->insert( "KLineEdit", SIGNAL(textChanged(const QString &)));
00132 s_changedMap->insert( "KPasswordEdit", SIGNAL(textChanged(const QString &)));
00133 s_changedMap->insert( "KRestrictedLine", SIGNAL(textChanged(const QString &)));
00134 s_changedMap->insert( "KTextBrowser", SIGNAL(sourceChanged(const QString &)));
00135 s_changedMap->insert( "KTextEdit", SIGNAL(textChanged()));
00136 s_changedMap->insert( "KUrlRequester", SIGNAL(textChanged (const QString& )));
00137 s_changedMap->insert( "KUrlComboRequester", SIGNAL(textChanged (const QString& )));
00138 s_changedMap->insert( "KUrlComboBox", SIGNAL(urlActivated (const KUrl& )));
00139 s_changedMap->insert( "KIntNumInput", SIGNAL(valueChanged (int)));
00140 s_changedMap->insert( "KIntSpinBox", SIGNAL(valueChanged (int)));
00141 s_changedMap->insert( "KDoubleNumInput", SIGNAL(valueChanged (double)));
00142 s_changedMap->insert( "KButtonGroup", SIGNAL(changed(int)));
00143 }
00144 }
00145
00146 QHash<QString, QByteArray> *KConfigDialogManager::propertyMap()
00147 {
00148 initMaps();
00149 return s_propertyMap;
00150 }
00151
00152 QHash<QString, QByteArray> *KConfigDialogManager::changedMap()
00153 {
00154 initMaps();
00155 return s_changedMap;
00156 }
00157
00158 void KConfigDialogManager::init(bool trackChanges)
00159 {
00160 initMaps();
00161 d->trackChanges = trackChanges;
00162
00163
00164 (void) parseChildren(d->m_dialog, trackChanges);
00165 }
00166
00167 void KConfigDialogManager::addWidget(QWidget *widget)
00168 {
00169 (void) parseChildren(widget, true);
00170 }
00171
00172 void KConfigDialogManager::setupWidget(QWidget *widget, KConfigSkeletonItem *item)
00173 {
00174 QVariant minValue = item->minValue();
00175 if (minValue.isValid())
00176 {
00177
00178 if (widget->metaObject()->indexOfProperty("minValue") != -1)
00179 widget->setProperty("minValue", minValue);
00180 if (widget->metaObject()->indexOfProperty("minimum") != -1)
00181 widget->setProperty("minimum", minValue);
00182 }
00183 QVariant maxValue = item->maxValue();
00184 if (maxValue.isValid())
00185 {
00186
00187 if (widget->metaObject()->indexOfProperty("maxValue") != -1)
00188 widget->setProperty("maxValue", maxValue);
00189 if (widget->metaObject()->indexOfProperty("maximum") != -1)
00190 widget->setProperty("maximum", maxValue);
00191 }
00192
00193 if (widget->whatsThis().isEmpty())
00194 {
00195 QString whatsThis = item->whatsThis();
00196 if ( !whatsThis.isEmpty() )
00197 {
00198 widget->setWhatsThis(whatsThis );
00199 }
00200 }
00201
00202 if (widget->toolTip().isEmpty())
00203 {
00204 QString toolTip = item->toolTip();
00205 if ( !toolTip.isEmpty() )
00206 {
00207 widget->setToolTip(toolTip);
00208 }
00209 }
00210
00211 if(!item->isEqual( property(widget) ))
00212 setProperty( widget, item->property() );
00213 }
00214
00215 bool KConfigDialogManager::parseChildren(const QWidget *widget, bool trackChanges)
00216 {
00217 bool valueChanged = false;
00218 const QList<QObject*> listOfChildren = widget->children();
00219 if(listOfChildren.count()==0)
00220 return valueChanged;
00221
00222 foreach ( QObject *object, listOfChildren )
00223 {
00224 if(!object->isWidgetType())
00225 continue;
00226
00227 QWidget *childWidget = static_cast<QWidget *>(object);
00228
00229 QString widgetName = childWidget->objectName();
00230 bool bParseChildren = true;
00231 bool bSaveInsideGroupBox = d->insideGroupBox;
00232
00233 if (widgetName.startsWith(QLatin1String("kcfg_")))
00234 {
00235
00236 QString configId = widgetName.mid(5);
00237 KConfigSkeletonItem *item = d->m_conf->findItem(configId);
00238 if (item)
00239 {
00240 d->knownWidget.insert(configId, childWidget);
00241
00242 setupWidget(childWidget, item);
00243
00244 if ( d->trackChanges ) {
00245 QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap->constFind(childWidget->metaObject()->className());
00246
00247 if (changedIt == s_changedMap->constEnd())
00248 {
00249
00250
00251
00252
00253 if ( childWidget->metaObject()->superClass() )
00254 changedIt = s_changedMap->constFind(childWidget->metaObject()->superClass()->className());
00255 else
00256 changedIt = s_changedMap->constFind(0);
00257 }
00258
00259 if (changedIt == s_changedMap->constEnd())
00260 {
00261 kWarning(d->debugArea()) << "Don't know how to monitor widget '" << childWidget->metaObject()->className() << "' for changes!";
00262 }
00263 else
00264 {
00265 connect(childWidget, *changedIt,
00266 this, SIGNAL(widgetModified()));
00267
00268 QComboBox *cb = qobject_cast<QComboBox *>(childWidget);
00269 if (cb && cb->isEditable())
00270 connect(cb, SIGNAL(editTextChanged(const QString &)),
00271 this, SIGNAL(widgetModified()));
00272 }
00273 }
00274 QGroupBox *gb = qobject_cast<QGroupBox *>(childWidget);
00275 if (!gb)
00276 bParseChildren = false;
00277 else
00278 d->insideGroupBox = true;
00279 }
00280 else
00281 {
00282 kWarning(d->debugArea()) << "A widget named '" << widgetName << "' was found but there is no setting named '" << configId << "'";
00283 assert(false);
00284 }
00285 }
00286 else if (QLabel *label = qobject_cast<QLabel*>(childWidget))
00287 {
00288 QWidget *buddy = label->buddy();
00289 if (!buddy)
00290 continue;
00291 QString buddyName = buddy->objectName();
00292 if (buddyName.startsWith(QLatin1String("kcfg_")))
00293 {
00294
00295 QString configId = buddyName.mid(5);
00296 d->buddyWidget.insert(configId, childWidget);
00297 }
00298 }
00299 #ifndef NDEBUG
00300 else if (!widgetName.isEmpty() && d->trackChanges)
00301 {
00302 QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap->constFind(childWidget->metaObject()->className());
00303 if (changedIt != s_changedMap->constEnd())
00304 {
00305 if ((!d->insideGroupBox || !qobject_cast<QRadioButton*>(childWidget)) &&
00306 !qobject_cast<QGroupBox*>(childWidget) &&!qobject_cast<QTabWidget*>(childWidget) )
00307 kDebug(d->debugArea()) << "Widget '" << widgetName << "' (" << childWidget->metaObject()->className() << ") remains unmanaged.";
00308 }
00309 }
00310 #endif
00311
00312 if(bParseChildren)
00313 {
00314
00315
00316 valueChanged |= parseChildren(childWidget, trackChanges);
00317 }
00318 d->insideGroupBox = bSaveInsideGroupBox;
00319 }
00320 return valueChanged;
00321 }
00322
00323 void KConfigDialogManager::updateWidgets()
00324 {
00325 bool changed = false;
00326 bool bSignalsBlocked = signalsBlocked();
00327 blockSignals(true);
00328
00329 QWidget *widget;
00330 QHashIterator<QString, QWidget *> it( d->knownWidget );
00331 while(it.hasNext()) {
00332 it.next();
00333 widget = it.value();
00334
00335 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00336 if (!item)
00337 {
00338 kWarning(d->debugArea()) << "The setting '" << it.key() << "' has disappeared!";
00339 continue;
00340 }
00341
00342 if(!item->isEqual( property(widget) ))
00343 {
00344 setProperty( widget, item->property() );
00345
00346 changed = true;
00347 }
00348 if (item->isImmutable())
00349 {
00350 widget->setEnabled(false);
00351 QWidget *buddy = d->buddyWidget.value(it.key(), 0);
00352 if (buddy)
00353 buddy->setEnabled(false);
00354 }
00355 }
00356 blockSignals(bSignalsBlocked);
00357
00358 if (changed)
00359 QTimer::singleShot(0, this, SIGNAL(widgetModified()));
00360 }
00361
00362 void KConfigDialogManager::updateWidgetsDefault()
00363 {
00364 bool bUseDefaults = d->m_conf->useDefaults(true);
00365 updateWidgets();
00366 d->m_conf->useDefaults(bUseDefaults);
00367 }
00368
00369 void KConfigDialogManager::updateSettings()
00370 {
00371 bool changed = false;
00372
00373 QWidget *widget;
00374 QHashIterator<QString, QWidget *> it( d->knownWidget );
00375 while(it.hasNext()) {
00376 it.next();
00377 widget = it.value();
00378
00379 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00380 if (!item) {
00381 kWarning(d->debugArea()) << "The setting '" << it.key() << "' has disappeared!";
00382 continue;
00383 }
00384
00385 QVariant fromWidget = property(widget);
00386 if(!item->isEqual( fromWidget )) {
00387 item->setProperty( fromWidget );
00388 changed = true;
00389 }
00390 }
00391 if (changed)
00392 {
00393 d->m_conf->writeConfig();
00394 emit settingsChanged();
00395 }
00396 }
00397
00398 QByteArray KConfigDialogManager::getUserProperty(const QWidget *widget) const
00399 {
00400 if (!s_propertyMap->contains(widget->metaObject()->className())) {
00401 const QMetaObject *metaObject = widget->metaObject();
00402 const QMetaProperty user = metaObject->userProperty();
00403 if ( user.isValid() ) {
00404 s_propertyMap->insert( widget->metaObject()->className(), user.name() );
00405
00406
00407 }
00408 else {
00409 return QByteArray();
00410 }
00411 }
00412 return s_propertyMap->value( widget->metaObject()->className() );
00413 }
00414
00415 QByteArray KConfigDialogManager::getCustomProperty(const QWidget *widget) const
00416 {
00417 QVariant prop(widget->property("kcfg_property"));
00418 if (prop.isValid()) {
00419 if (!prop.canConvert(QVariant::ByteArray)) {
00420 kWarning(d->debugArea()) << "kcfg_property on" << widget->metaObject()->className()
00421 << "is not of type ByteArray";
00422 } else {
00423 return prop.toByteArray();
00424 }
00425 }
00426 return QByteArray();
00427 }
00428
00429 void KConfigDialogManager::setProperty(QWidget *w, const QVariant &v)
00430 {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 QByteArray userproperty = getCustomProperty(w);
00441 if (userproperty.isEmpty()) {
00442 userproperty = getUserProperty(w);
00443 }
00444 if (userproperty.isEmpty()) {
00445 QComboBox *cb = qobject_cast<QComboBox *>(w);
00446 if (cb) {
00447 if (cb->isEditable()) {
00448 int i = cb->findText(v.toString());
00449 if (i != -1) {
00450 cb->setCurrentIndex(i);
00451 } else {
00452 cb->setEditText(v.toString());
00453 }
00454 } else {
00455 cb->setCurrentIndex(v.toInt());
00456 }
00457 return;
00458 }
00459 kWarning(d->debugArea()) << w->metaObject()->className() << " widget not handled!";
00460 return;
00461 }
00462 w->setProperty(userproperty, v);
00463 }
00464
00465 QVariant KConfigDialogManager::property(QWidget *w) const
00466 {
00467
00468
00469
00470
00471 QByteArray userproperty = getCustomProperty(w);
00472 if (userproperty.isEmpty()) {
00473 userproperty = getUserProperty(w);
00474 }
00475 if (userproperty.isEmpty()) {
00476 QComboBox *cb = qobject_cast<QComboBox *>(w);
00477 if (cb) {
00478 if (cb->isEditable()) {
00479 return QVariant(cb->currentText());
00480 } else {
00481 return QVariant(cb->currentIndex());
00482 }
00483 }
00484 kWarning(d->debugArea()) << w->metaObject()->className() << " widget not handled!";
00485 return QVariant();
00486 }
00487
00488 return w->property(userproperty);
00489 }
00490
00491 bool KConfigDialogManager::hasChanged() const
00492 {
00493 QWidget *widget;
00494 QHashIterator<QString, QWidget *> it( d->knownWidget) ;
00495 while(it.hasNext()) {
00496 it.next();
00497 widget = it.value();
00498
00499 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00500 if (!item) {
00501 kWarning(d->debugArea()) << "The setting '" << it.key() << "' has disappeared!";
00502 continue;
00503 }
00504
00505 if(!item->isEqual( property(widget) )) {
00506
00507 return true;
00508 }
00509 }
00510 return false;
00511 }
00512
00513 bool KConfigDialogManager::isDefault() const
00514 {
00515 bool bUseDefaults = d->m_conf->useDefaults(true);
00516 bool result = !hasChanged();
00517 d->m_conf->useDefaults(bUseDefaults);
00518 return result;
00519 }
00520
00521 #include "kconfigdialogmanager.moc"
00522