• Skip to content
  • Skip to link menu
KDE 4.3 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 
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     //s_propertyMap->insert( "KUrlRequester", "url" );
00087     //s_propertyMap->insert( "KUrlComboRequester", "url" );
00088   }
00089 
00090   if( s_changedMap->isEmpty() )
00091   {
00092     // QT
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     // We can only store one thing, so you can't have
00097     // a ButtonGroup that is checkable.
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     //qsqlproperty map doesn't store the text, but the value!
00102     //s_changedMap->insert("QComboBox", SIGNAL(textChanged(const QString &)));
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     // KDE
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   // Go through all of the children of the widgets and find all known widgets
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     // Only q3datetimeedit is using this property we can remove it if we stop supporting Qt3Support
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     // Only q3datetimeedit is using that property we can remove it if we stop supporting Qt3Support
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) //?? XXX
00218     return valueChanged;
00219 
00220   foreach ( QObject *object, listOfChildren )
00221   {
00222     if(!object->isWidgetType())
00223       continue; // Skip non-widgets
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       // This is one of our widgets!
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            // If the class name of the widget wasn't in the monitored widgets map, then look for
00248            // it again using the super class name. This fixes a problem with using QtRuby/Korundum
00249            // widgets with KConfigXT where 'Qt::Widget' wasn't being seen a the real deal, even
00250            // though it was a 'QWidget'.
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         // This is one of our widgets!
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       // this widget is not known as something we can store.
00313       // Maybe we can store one of its children.
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 //        kDebug(178) << "The setting '" << it.key() << "' [" << widget->className() << "] has changed";
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         //kDebug(178) << "class name: '" << widget->metaObject()->className()
00404         //<< " 's USER property: " << metaProperty.name() << endl;
00405     }
00406     else {
00407         return QByteArray(); //no USER property
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 /*  QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00430   if (bg)
00431   {
00432     QAbstractButton *b = bg->button(v.toInt());
00433     if (b)
00434         b->setDown(true);
00435     return;
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 /*  QButtonGroup *bg = qobject_cast<QButtonGroup *>(w);
00466   if (bg && bg->checkedButton())
00467     return QVariant(bg->id(bg->checkedButton()));*/
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             // kDebug(178) << "Widget for '" << it.key() << "' has changed.";
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 

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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