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

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
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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