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 #include <QButtonGroup>
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 s_changedMap->insert("QButtonGroup", SIGNAL(buttonClicked(int)));
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(!item->isEqual( property(widget) ))
00201 setProperty( widget, item->property() );
00202 }
00203
00204 bool KConfigDialogManager::parseChildren(const QWidget *widget, bool trackChanges)
00205 {
00206 bool valueChanged = false;
00207 const QList<QObject*> listOfChildren = widget->children();
00208 if(listOfChildren.count()==0)
00209 return valueChanged;
00210
00211 foreach ( QObject *object, listOfChildren )
00212 {
00213 if(!object->isWidgetType())
00214 continue;
00215
00216 QWidget *childWidget = static_cast<QWidget *>(object);
00217
00218 QString widgetName = childWidget->objectName();
00219 bool bParseChildren = true;
00220 bool bSaveInsideGroupBox = d->insideGroupBox;
00221
00222 if (widgetName.startsWith("kcfg_"))
00223 {
00224
00225 QString configId = widgetName.mid(5);
00226 KConfigSkeletonItem *item = d->m_conf->findItem(configId);
00227 if (item)
00228 {
00229 d->knownWidget.insert(configId, childWidget);
00230
00231 setupWidget(childWidget, item);
00232
00233 if ( d->trackChanges ) {
00234 QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap->find(childWidget->metaObject()->className());
00235
00236 if (changedIt == s_changedMap->end())
00237 {
00238
00239
00240
00241
00242 if ( childWidget->metaObject()->superClass() )
00243 changedIt = s_changedMap->find(childWidget->metaObject()->superClass()->className());
00244 else
00245 changedIt = s_changedMap->find(0);
00246 }
00247
00248 if (changedIt == s_changedMap->end())
00249 {
00250 kWarning(178) << "Don't know how to monitor widget '" << childWidget->metaObject()->className() << "' for changes!";
00251 }
00252 else
00253 {
00254 connect(childWidget, *changedIt,
00255 this, SIGNAL(widgetModified()));
00256
00257 QComboBox *cb = qobject_cast<QComboBox *>(childWidget);
00258 if (cb && cb->isEditable())
00259 connect(cb, SIGNAL(editTextChanged(const QString &)),
00260 this, SIGNAL(widgetModified()));
00261 }
00262 }
00263 QGroupBox *gb = qobject_cast<QGroupBox *>(childWidget);
00264 if (!gb)
00265 bParseChildren = false;
00266 else
00267 d->insideGroupBox = true;
00268 }
00269 else
00270 {
00271 kWarning(178) << "A widget named '" << widgetName << "' was found but there is no setting named '" << configId << "'";
00272 assert(false);
00273 }
00274 }
00275 else if (QLabel *label = qobject_cast<QLabel*>(childWidget))
00276 {
00277 QWidget *buddy = label->buddy();
00278 if (!buddy)
00279 continue;
00280 QString buddyName = buddy->objectName();
00281 if (buddyName.startsWith("kcfg_"))
00282 {
00283
00284 QString configId = buddyName.mid(5);
00285 d->buddyWidget.insert(configId, childWidget);
00286 }
00287 }
00288 #ifndef NDEBUG
00289 else if (!widgetName.isEmpty() && d->trackChanges)
00290 {
00291 QHash<QString, QByteArray>::const_iterator changedIt = s_changedMap->find(childWidget->metaObject()->className());
00292 if (changedIt != s_changedMap->end())
00293 {
00294 if ((!d->insideGroupBox || !qobject_cast<QRadioButton*>(childWidget)) &&
00295 !qobject_cast<QGroupBox*>(childWidget) &&!qobject_cast<QTabWidget*>(childWidget) )
00296 kDebug(178) << "Widget '" << widgetName << "' (" << childWidget->metaObject()->className() << ") remains unmanaged.";
00297 }
00298 }
00299 #endif
00300
00301 if(bParseChildren)
00302 {
00303
00304
00305 valueChanged |= parseChildren(childWidget, trackChanges);
00306 }
00307 d->insideGroupBox = bSaveInsideGroupBox;
00308 }
00309 return valueChanged;
00310 }
00311
00312 void KConfigDialogManager::updateWidgets()
00313 {
00314 bool changed = false;
00315 bool bSignalsBlocked = signalsBlocked();
00316 blockSignals(true);
00317
00318 QWidget *widget;
00319 QHashIterator<QString, QWidget *> it( d->knownWidget );
00320 while(it.hasNext()) {
00321 it.next();
00322 widget = it.value();
00323
00324 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00325 if (!item)
00326 {
00327 kWarning(178) << "The setting '" << it.key() << "' has disappeared!";
00328 continue;
00329 }
00330
00331 if(!item->isEqual( property(widget) ))
00332 {
00333 setProperty( widget, item->property() );
00334
00335 changed = true;
00336 }
00337 if (item->isImmutable())
00338 {
00339 widget->setEnabled(false);
00340 QWidget *buddy = d->buddyWidget.value(it.key(), 0);
00341 if (buddy)
00342 buddy->setEnabled(false);
00343 }
00344 }
00345 blockSignals(bSignalsBlocked);
00346
00347 if (changed)
00348 QTimer::singleShot(0, this, SIGNAL(widgetModified()));
00349 }
00350
00351 void KConfigDialogManager::updateWidgetsDefault()
00352 {
00353 bool bUseDefaults = d->m_conf->useDefaults(true);
00354 updateWidgets();
00355 d->m_conf->useDefaults(bUseDefaults);
00356 }
00357
00358 void KConfigDialogManager::updateSettings()
00359 {
00360 bool changed = false;
00361
00362 QWidget *widget;
00363 QHashIterator<QString, QWidget *> it( d->knownWidget );
00364 while(it.hasNext()) {
00365 it.next();
00366 widget = it.value();
00367
00368 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00369 if (!item) {
00370 kWarning(178) << "The setting '" << it.key() << "' has disappeared!";
00371 continue;
00372 }
00373
00374 QVariant fromWidget = property(widget);
00375 if(!item->isEqual( fromWidget )) {
00376 item->setProperty( fromWidget );
00377 changed = true;
00378 }
00379 }
00380 if (changed)
00381 {
00382 d->m_conf->writeConfig();
00383 emit settingsChanged();
00384 }
00385 }
00386
00387 QByteArray KConfigDialogManager::getUserProperty(const QWidget *widget) const
00388 {
00389 if (!s_propertyMap->contains(widget->metaObject()->className())) {
00390 const QMetaObject *metaObject = widget->metaObject();
00391 const QMetaProperty user = metaObject->userProperty();
00392 if ( user.isValid() ) {
00393 s_propertyMap->insert( widget->metaObject()->className(), user.name() );
00394
00395
00396 }
00397 else {
00398 return QByteArray();
00399 }
00400 }
00401 return s_propertyMap->value( widget->metaObject()->className() );
00402 }
00403
00404 void KConfigDialogManager::setProperty(QWidget *w, const QVariant &v)
00405 {
00406 QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00407 if (bg)
00408 {
00409 QAbstractButton *b = bg->button(v.toInt());
00410 if (b)
00411 b->setDown(true);
00412 return;
00413 }
00414
00415 QByteArray userproperty = getUserProperty( w );
00416 if ( userproperty.isEmpty() ) {
00417 QComboBox *cb = qobject_cast<QComboBox *>(w);
00418 if (cb) {
00419 if ( cb->isEditable() )
00420 {
00421 int i = cb->findText(v.toString());
00422 if (i != -1)
00423 cb->setCurrentIndex(i);
00424 else
00425 cb->setEditText(v.toString());
00426 } else {
00427 cb->setCurrentIndex( v.toInt() );
00428 }
00429 return;
00430 }
00431 kWarning(178) << w->metaObject()->className() << " widget not handled!";
00432 return;
00433 }
00434 w->setProperty( userproperty, v );
00435 }
00436
00437 QVariant KConfigDialogManager::property(QWidget *w) const
00438 {
00439 QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00440 if (bg && bg->checkedButton())
00441 return QVariant(bg->id(bg->checkedButton()));
00442
00443 QByteArray userproperty = getUserProperty( w );
00444 if ( userproperty.isEmpty() ) {
00445 QComboBox *cb = qobject_cast<QComboBox *>(w);
00446 if (cb) {
00447 if ( cb->isEditable() )
00448 return QVariant(cb->currentText());
00449 else
00450 return QVariant(cb->currentIndex());
00451 }
00452 kWarning(178) << w->metaObject()->className() << " widget not handled!";
00453 return QVariant();
00454 }
00455
00456 return w->property( userproperty );
00457 }
00458
00459 bool KConfigDialogManager::hasChanged() const
00460 {
00461 QWidget *widget;
00462 QHashIterator<QString, QWidget *> it( d->knownWidget) ;
00463 while(it.hasNext()) {
00464 it.next();
00465 widget = it.value();
00466
00467 KConfigSkeletonItem *item = d->m_conf->findItem(it.key());
00468 if (!item) {
00469 kWarning(178) << "The setting '" << it.key() << "' has disappeared!";
00470 continue;
00471 }
00472
00473 if(!item->isEqual( property(widget) )) {
00474
00475 return true;
00476 }
00477 }
00478 return false;
00479 }
00480
00481 bool KConfigDialogManager::isDefault() const
00482 {
00483 bool bUseDefaults = d->m_conf->useDefaults(true);
00484 bool result = !hasChanged();
00485 d->m_conf->useDefaults(bUseDefaults);
00486 return result;
00487 }
00488
00489 #include "kconfigdialogmanager.moc"
00490