• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kconfigdialogmanager.cpp

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net)
00004  *  Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public License
00017  *  along with this library; see the file COPYING.LIB.  If not, write to
00018  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA 02110-1301, USA.
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 
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     //s_propertyMap->insert( "KUrlRequester", "url" );
00089     //s_propertyMap->insert( "KUrlComboRequester", "url" );
00090   }
00091 
00092   if( s_changedMap->isEmpty() )
00093   {
00094     // QT
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     // We can only store one thing, so you can't have
00099     // a ButtonGroup that is checkable.
00100 //    s_changedMap->insert("QButtonGroup", SIGNAL(buttonClicked(int)));
00101     s_changedMap->insert("QGroupBox", SIGNAL(toggled(bool)));
00102     s_changedMap->insert("QComboBox", SIGNAL(activated (int)));
00103     //qsqlproperty map doesn't store the text, but the value!
00104     //s_changedMap->insert("QComboBox", SIGNAL(textChanged(const QString &)));
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     // KDE
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   // Go through all of the children of the widgets and find all known widgets
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     // Only q3datetimeedit is using this property we can remove it if we stop supporting Qt3Support
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     // Only q3datetimeedit is using that property we can remove it if we stop supporting Qt3Support
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) //?? XXX
00220     return valueChanged;
00221 
00222   foreach ( QObject *object, listOfChildren )
00223   {
00224     if(!object->isWidgetType())
00225       continue; // Skip non-widgets
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       // This is one of our widgets!
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            // If the class name of the widget wasn't in the monitored widgets map, then look for
00250            // it again using the super class name. This fixes a problem with using QtRuby/Korundum
00251            // widgets with KConfigXT where 'Qt::Widget' wasn't being seen a the real deal, even
00252            // though it was a 'QWidget'.
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         // This is one of our widgets!
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       // this widget is not known as something we can store.
00315       // Maybe we can store one of its children.
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 //        kDebug(d->debugArea()) << "The setting '" << it.key() << "' [" << widget->className() << "] has changed";
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         //kDebug(d->debugArea()) << "class name: '" << widget->metaObject()->className()
00406         //<< " 's USER property: " << metaProperty.name() << endl;
00407     }
00408     else {
00409         return QByteArray(); //no USER property
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 /*  QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00432   if (bg)
00433   {
00434     QAbstractButton *b = bg->button(v.toInt());
00435     if (b)
00436         b->setDown(true);
00437     return;
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 /*  QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00468   if (bg && bg->checkedButton())
00469     return QVariant(bg->id(bg->checkedButton()));*/
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             // kDebug(d->debugArea()) << "Widget for '" << it.key() << "' has changed.";
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 

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  •     Sodep
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal