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

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal