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