/* * This file is part of the KDE libraries * Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kautoconfig.h" #include <kglobal.h> #include <tqsqlpropertymap.h> #include <tqobjectlist.h> #include <kconfig.h> #include <kapplication.h> #include <kdeversion.h> /** * Macro function to warn developers when they are making calls * that can never return anything of value */ #ifndef NDEBUG #include "kdebug.h" #define functionCallPreOrderCheck(functionName, returnValue) \ if(!d->retrievedSettings){ \ kdDebug(180) << "KAutoConfig::"functionName"() was called before " \ "KAutoConfig::retrieveSettings(). This should NEVER happen because " \ "it will do nothing. Please Fix." << endl; \ return returnValue; \ } #define functionCallPostOrderCheck(functionName, returnValue) \ if(d->retrievedSettings){ \ kdDebug(180) << "KAutoConfig::"functionName"() was called after " \ "KAutoConfig::retrieveSettings(). This should NEVER happen because " \ "it will do nothing. Please Fix." << endl; \ return returnValue; \ } #else #define functionCallPostOrderCheck(functionName, returnValue) #define functionCallPreOrderCheck(functionName, returnValue) #endif class KAutoConfig::KAutoConfigPrivate { public: KAutoConfigPrivate() : changed(false) #ifndef NDEBUG , retrievedSettings(false) #endif { init(); } // Widgets to parse TQPtrList<TQWidget> widgets; // Name of the group that KConfig should be set to for each widget. TQMap<TQWidget*, TQString> groups; // Child widgets of widgets to ignore TQPtrList<TQWidget> ignore; // Reset to false after saveSettings returns true. bool changed; #ifndef NDEBUG // Many functions require this to be true to be of any value. bool retrievedSettings; #endif // Known widgets that can be configured TQMap<TQWidget*, TQPtrList<TQWidget> > autoWidgets; // Default values for the widgets. TQMap<TQWidget*, TQVariant> defaultValues; // Widgets to not get properties on (TQLabel etc) TQAsciiDict<int> ignoreTheseWidgets; void init(){ ignoreTheseWidgets.insert("TQLabel", new int(1)); ignoreTheseWidgets.insert("TQFrame", new int(2)); ignoreTheseWidgets.insert("TQGroupBox", new int(3)); ignoreTheseWidgets.insert("TQButtonGroup", new int(4)); ignoreTheseWidgets.insert("TQWidget", new int(5)); ignoreTheseWidgets.setAutoDelete(true); static bool defaultKDEPropertyMapInstalled = false; if ( !defaultKDEPropertyMapInstalled && kapp ) { kapp->installKDEPropertyMap(); defaultKDEPropertyMapInstalled = true; } } }; KAutoConfig::KAutoConfig(KConfig *kconfig, TQObject *parent, const char *name) : TQObject(parent, name), config(kconfig) { d = new KAutoConfigPrivate(); } KAutoConfig::KAutoConfig(TQObject *parent, const char *name) : TQObject(parent, name), config(KGlobal::config()) { d = new KAutoConfigPrivate(); } KAutoConfig::~KAutoConfig(){ delete d; } void KAutoConfig::addWidget(TQWidget *widget, const TQString &group){ functionCallPostOrderCheck("addWidget",); d->groups.insert(widget, group); d->widgets.append(widget); TQPtrList<TQWidget> newAutoConfigWidget; d->autoWidgets.insert(widget, newAutoConfigWidget ); } void KAutoConfig::ignoreSubWidget(TQWidget *widget){ functionCallPostOrderCheck("ignoreSubWidget",); d->ignore.append(widget); } bool KAutoConfig::retrieveSettings(bool trackChanges){ #ifndef NDEBUG if(d->retrievedSettings){ kdDebug(180) << "This should not happen. Function " "KAutoConfig::retrieveSettings() was called more then once, returning " "false. Please fix." << endl; return false; } d->retrievedSettings = true; #endif if(trackChanges){ // QT changedMap.insert(TQString::fromLatin1("TQButton"), TQT_SIGNAL(stateChanged(int))); changedMap.insert(TQString::fromLatin1("TQCheckBox"), TQT_SIGNAL(stateChanged(int))); changedMap.insert(TQString::fromLatin1("TQPushButton"), TQT_SIGNAL(stateChanged(int))); changedMap.insert(TQString::fromLatin1("TQRadioButton"), TQT_SIGNAL(stateChanged(int))); changedMap.insert(TQString::fromLatin1("TQComboBox"), TQT_SIGNAL(activated (int))); //qsqlproperty map doesn't store the text, but the value! //changedMap.insert(TQString::fromLatin1("TQComboBox"), TQT_SIGNAL(textChanged(const TQString &))); changedMap.insert(TQString::fromLatin1("QDateEdit"), TQT_SIGNAL(valueChanged(const TQDate &))); changedMap.insert(TQString::fromLatin1("QDateTimeEdit"), TQT_SIGNAL(valueChanged(const TQDateTime &))); changedMap.insert(TQString::fromLatin1("TQDial"), TQT_SIGNAL(valueChanged (int))); changedMap.insert(TQString::fromLatin1("TQLineEdit"), TQT_SIGNAL(textChanged(const TQString &))); changedMap.insert(TQString::fromLatin1("TQSlider"), TQT_SIGNAL(valueChanged(int))); changedMap.insert(TQString::fromLatin1("TQSpinBox"), TQT_SIGNAL(valueChanged(int))); changedMap.insert(TQString::fromLatin1("QTimeEdit"), TQT_SIGNAL(valueChanged(const TQTime &))); changedMap.insert(TQString::fromLatin1("TQTextEdit"), TQT_SIGNAL(textChanged())); changedMap.insert(TQString::fromLatin1("TQTextBrowser"), TQT_SIGNAL(sourceChanged(const TQString &))); changedMap.insert(TQString::fromLatin1("TQMultiLineEdit"), TQT_SIGNAL(textChanged())); changedMap.insert(TQString::fromLatin1("TQListBox"), TQT_SIGNAL(selectionChanged())); changedMap.insert(TQString::fromLatin1("TQTabWidget"), TQT_SIGNAL(currentChanged(TQWidget *))); // KDE changedMap.insert( TQString::fromLatin1("KComboBox"), TQT_SIGNAL(activated (int))); changedMap.insert( TQString::fromLatin1("KFontCombo"), TQT_SIGNAL(activated (int))); changedMap.insert( TQString::fromLatin1("KFontRequester"), TQT_SIGNAL(fontSelected(const TQFont &))); changedMap.insert( TQString::fromLatin1("KFontChooser"), TQT_SIGNAL(fontSelected(const TQFont &))); changedMap.insert( TQString::fromLatin1("KHistoryCombo"), TQT_SIGNAL(activated (int))); changedMap.insert( TQString::fromLatin1("KColorButton"), TQT_SIGNAL(changed(const TQColor &))); changedMap.insert( TQString::fromLatin1("KDatePicker"), TQT_SIGNAL(dateSelected (TQDate))); changedMap.insert( TQString::fromLatin1("KEditListBox"), TQT_SIGNAL(changed())); changedMap.insert( TQString::fromLatin1("KListBox"), TQT_SIGNAL(selectionChanged())); changedMap.insert( TQString::fromLatin1("KLineEdit"), TQT_SIGNAL(textChanged(const TQString &))); changedMap.insert( TQString::fromLatin1("KPasswordEdit"), TQT_SIGNAL(textChanged(const TQString &))); changedMap.insert( TQString::fromLatin1("KRestrictedLine"), TQT_SIGNAL(textChanged(const TQString &))); changedMap.insert( TQString::fromLatin1("KTextBrowser"), TQT_SIGNAL(sourceChanged(const TQString &))); changedMap.insert( TQString::fromLatin1("KTextEdit"), TQT_SIGNAL(textChanged())); changedMap.insert( TQString::fromLatin1("KURLRequester"), TQT_SIGNAL(textChanged (const TQString& ))); changedMap.insert( TQString::fromLatin1("KIntNumInput"), TQT_SIGNAL(valueChanged (int))); changedMap.insert( TQString::fromLatin1("KIntSpinBox"), TQT_SIGNAL(valueChanged (int))); changedMap.insert( TQString::fromLatin1("KDoubleNumInput"), TQT_SIGNAL(valueChanged (double))); } // Go through all of the children of the widgets and find all known widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *widget; bool usingDefaultValues = false; while ( (widget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[widget]); usingDefaultValues |= parseChildren(widget, d->autoWidgets[widget], trackChanges); } return usingDefaultValues; } bool KAutoConfig::saveSettings() { functionCallPreOrderCheck("saveSettings", false); TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); // Go through all of the widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *widget; while ( (widget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[widget]); // Go through the known autowidgets of this widget and save TQPtrListIterator<TQWidget> it( d->autoWidgets[widget] ); TQWidget *groupWidget; bool widgetChanged = false; while ( (groupWidget = it.current()) != 0 ){ ++it; TQVariant defaultValue = d->defaultValues[groupWidget]; TQVariant currentValue = propertyMap->property(groupWidget); #if KDE_IS_VERSION( 3, 1, 90 ) if(!config->hasDefault(TQString::fromLatin1(groupWidget->name())) && currentValue == defaultValue){ config->revertToDefault(TQString::fromLatin1(groupWidget->name())); widgetChanged = true; } else{ #endif TQVariant savedValue = config->readPropertyEntry(groupWidget->name(), defaultValue); if(savedValue != currentValue){ config->writeEntry(groupWidget->name(), currentValue); widgetChanged = true; } #if KDE_IS_VERSION( 3, 1, 90 ) } #endif } d->changed |= widgetChanged; if(widgetChanged) emit( settingsChanged(widget) ); } if(d->changed){ emit( settingsChanged() ); d->changed = false; config->sync(); return true; } return false; } bool KAutoConfig::hasChanged() const { functionCallPreOrderCheck("hasChanged", false); TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); // Go through all of the widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *widget; while ( (widget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[widget]); // Go through the known autowidgets of this widget and save TQPtrListIterator<TQWidget> it( d->autoWidgets[widget] ); TQWidget *groupWidget; while ( (groupWidget = it.current()) != 0 ){ ++it; TQVariant defaultValue = d->defaultValues[groupWidget]; TQVariant currentValue = propertyMap->property(groupWidget); TQVariant savedValue = config->readPropertyEntry(groupWidget->name(), defaultValue); // Return once just one item is found to have changed. if((currentValue == defaultValue && savedValue != currentValue) || (savedValue != currentValue)) return true; } } return false; } bool KAutoConfig::isDefault() const { functionCallPreOrderCheck("isDefault", false); TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); // Go through all of the widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *widget; while ( (widget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[widget]); // Go through the known autowidgets of this widget and save TQPtrListIterator<TQWidget> it( d->autoWidgets[widget] ); TQWidget *groupWidget; while ( (groupWidget = it.current()) != 0 ){ ++it; TQVariant defaultValue = d->defaultValues[groupWidget]; TQVariant currentValue = propertyMap->property(groupWidget); if(currentValue != defaultValue){ //qDebug("groupWidget %s, has changed: default: %s new: %s", groupWidget->name(), defaultValue.toString().latin1(), currentValue.toString().latin1()); return false; } } } return true; } void KAutoConfig::resetSettings() const { functionCallPreOrderCheck("resetSettings",); TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); // Go through all of the widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *widget; while ( (widget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[widget]); // Go through the known autowidgets of this widget and save TQPtrListIterator<TQWidget> it( d->autoWidgets[widget] ); TQWidget *groupWidget; while ( (groupWidget = it.current()) != 0 ){ ++it; TQVariant defaultValue = d->defaultValues[groupWidget]; if(defaultValue != propertyMap->property(groupWidget)){ propertyMap->setProperty(groupWidget, defaultValue); d->changed = true; } } } } void KAutoConfig::reloadSettings() const { functionCallPreOrderCheck("reloadSettings", ); TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); // Go through all of the widgets TQPtrListIterator<TQWidget> it( d->widgets ); TQWidget *pageWidget; while ( (pageWidget = it.current()) != 0 ) { ++it; config->setGroup(d->groups[pageWidget]); // Go through the known widgets of this page and reload TQPtrListIterator<TQWidget> it( d->autoWidgets[pageWidget] ); TQWidget *widget; while ( (widget = it.current()) != 0 ){ ++it; TQVariant defaultSetting = d->defaultValues[widget]; TQVariant setting = config->readPropertyEntry(widget->name(), defaultSetting); propertyMap->setProperty(widget, setting); } } d->changed = false; } bool KAutoConfig::parseChildren(const TQWidget *widget, TQPtrList<TQWidget>& currentGroup, bool trackChanges){ bool valueChanged = false; const TQPtrList<TQObject> *listOfChildren = widget->children(); if(!listOfChildren) return valueChanged; TQSqlPropertyMap *propertyMap = TQSqlPropertyMap::defaultMap(); TQPtrListIterator<TQObject> it( *listOfChildren ); TQObject *object; while ( (object = it.current()) != 0 ) { ++it; if(!object->isWidgetType()){ continue; } TQWidget *childWidget = (TQWidget *)object; if(d->ignore.containsRef(childWidget)){ continue; } bool parseTheChildren = true; #ifndef NDEBUG if(d->ignoreTheseWidgets[childWidget->className()] == 0 && childWidget->name(0) == NULL){ // Without a name the widget is just skipped over. kdDebug(180) << "KAutoConfig::retrieveSettings, widget with " "NULL name. className: " << childWidget->className() << endl; } #endif if( d->ignoreTheseWidgets[childWidget->className()] == 0 && childWidget->name(0) != NULL ) { TQVariant defaultSetting = propertyMap->property(childWidget); if(defaultSetting.isValid()) { parseTheChildren = false; // Disable the widget if it is immutable? if(config->entryIsImmutable( TQString::fromLatin1(childWidget->name()))) childWidget->setEnabled(false); else { // FOR THOSE WHO ARE LOOKING // Here is the code were the widget is actually marked to watch. //qDebug("KAutoConfig: Adding widget(%s)",childWidget->name()); currentGroup.append(childWidget); d->defaultValues.insert(childWidget, defaultSetting); } // Get/Set settings and connect up the changed signal TQVariant setting = config->readPropertyEntry(childWidget->name(), defaultSetting); if(setting != defaultSetting) { propertyMap->setProperty(childWidget, setting); valueChanged = true; } if(trackChanges && changedMap.find(TQString::fromLatin1(childWidget->className())) != changedMap.end()) { connect(childWidget, changedMap[TQString::fromLatin1(childWidget->className())], this, TQT_SIGNAL(widgetModified())); } #ifndef NDEBUG else if(trackChanges && changedMap.find(TQString::fromLatin1(childWidget->className())) == changedMap.end()) { // Without a signal kautoconfigdialog could incorectly // enable/disable the buttons kdDebug(180) << "KAutoConfig::retrieveSettings, Unknown changed " "signal for widget:" << childWidget->className() << endl; } #endif } #ifndef NDEBUG else { // If kautoconfig doesn't know how to get/set the widget's value // nothing can be done to it and it is skipped. kdDebug(180) << "KAutoConfig::retrieveSettings, Unknown widget:" << childWidget->className() << endl; } #endif } if(parseTheChildren) { // this widget is not known as something we can store. // Maybe we can store one of its children. valueChanged |= parseChildren(childWidget, currentGroup, trackChanges); } } return valueChanged; } #include "kautoconfig.moc"