# HG changeset patch # User thomas_-_s # Date 1274812763 0 # Node ID ca1bafc93ee2254a78ff143a22e02da3708af646 # Parent d38b69f9987c728a880383c159ac49df019dc33b Drastically simplified the connection between QObject properties and the settings. Thus the UiGuiSettingsDialog widgets do no longer need to have a special object name. Instead they need custom properties "connectedPropertyName" and "connectedSettingName" set, which then can be used to create the connection to the setting. git-svn-id: svn://svn.code.sf.net/p/universalindent/code/trunk@1008 59b1889a-e5ac-428c-b0c7-476e01d41282 diff -r d38b69f9987c -r ca1bafc93ee2 src/UiGuiSettings.cpp --- a/src/UiGuiSettings.cpp Mon May 24 21:55:34 2010 +0000 +++ b/src/UiGuiSettings.cpp Tue May 25 18:39:23 2010 +0000 @@ -1,594 +1,688 @@ -/*************************************************************************** -* Copyright (C) 2006-2010 by Thomas Schweitzer * -* thomas-schweitzer(at)arcor.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License version 2.0 as * -* published by the Free Software Foundation. * -* * -* This program 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 General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program in the file LICENSE.GPL; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ - -#include "UiGuiSettings.h" - -#include "SettingsPaths.h" - -#include -#include -#include - -//! \defgroup grp_Settings All concerning the settings. - -/*! - \class UiGuiSettings - \ingroup grp_Settings - \brief Handles the settings of the program. Reads them on startup and saves them on exit. - Is a singleton class and can only be accessed via getInstance(). -*/ - -// Inits the single class instance pointer. -UiGuiSettings* UiGuiSettings::instance = NULL; - -/*! - \brief The constructor for the settings. -*/ -UiGuiSettings::UiGuiSettings() : QObject() { - // Create the main application settings object from the UniversalIndentGUI.ini file. - qsettings = new QSettings(SettingsPaths::getSettingsPath() + "/UniversalIndentGUI.ini", QSettings::IniFormat, this); - - indenterDirctoryStr = SettingsPaths::getGlobalFilesPath() + "/indenters"; - readAvailableTranslations(); - initSettings(); -} - - -/*! - \brief Returns the instance of the settings class. If no instance exists, ONE will be created. - */ -UiGuiSettings* UiGuiSettings::getInstance() { - if ( instance == NULL ) { - // Create the settings object, which loads all UiGui settings from a file. - instance = new UiGuiSettings(); - } - - return instance; -} - -/*! - \brief Deletes the existing instance of UiGuiSettings and removes the created temp dir. - */ -void UiGuiSettings::deleteInstance() { - SettingsPaths::cleanAndRemoveTempDir(); - if ( instance != NULL ) { - delete instance; - instance = NULL; - } -} - - -/*! - \brief The destructor saves the settings to a file. - */ -UiGuiSettings::~UiGuiSettings() { - // Convert the language setting from an integer index to a string. - int index = qsettings->value("UniversalIndentGUI/language", 0).toInt(); - if ( index < 0 || index >= availableTranslations.size() ) - index = 0; - - qsettings->setValue( "UniversalIndentGUI/language", availableTranslations.at(index) ); -} - - -/*! - \brief Scans the translations directory for available translation files and - stores them in the QList \a availableTranslations. - */ -void UiGuiSettings::readAvailableTranslations() { - QString languageShort; - QStringList languageFileList; - - // English is the default language. A translation file does not exist but to have a menu entry, added here. - languageFileList << "universalindent_en.qm"; - - // Find all translation files in the "translations" directory. - QDir translationDirectory = QDir( SettingsPaths::getGlobalFilesPath() + "/translations" ); - languageFileList << translationDirectory.entryList( QStringList("universalindent_*.qm") ); - - // Loop for each found translation file - foreach ( languageShort, languageFileList ) { - // Remove the leading string "universalindent_" from the filename. - languageShort.remove(0,16); - // Remove trailing file extension ".qm". - languageShort.chop(3); - - availableTranslations.append(languageShort); - } -} - - -/*! - \brief Returns a list of the mnemonics of the available translations. - */ -QStringList UiGuiSettings::getAvailableTranslations() { - return availableTranslations; -} - - -/*! - \brief Returns the value of the by \a settingsName defined setting as QVariant. - - If the named setting does not exist, 0 is being returned. -*/ -QVariant UiGuiSettings::getValueByName(QString settingName) { - return qsettings->value("UniversalIndentGUI/" + settingName); -} - - -/*! - \brief Loads the settings for the main application. - - Settings are for example last selected indenter, last loaded source code file and so on. -*/ -bool UiGuiSettings::initSettings() -{ - // Read the version string saved in the settings file. - qsettings->setValue( "UniversalIndentGUI/version", qsettings->value("UniversalIndentGUI/version", "") ); - - // Read windows last size and position from the settings file. - qsettings->setValue( "UniversalIndentGUI/maximized", qsettings->value("UniversalIndentGUI/maximized", false) ); - qsettings->setValue( "UniversalIndentGUI/position", qsettings->value("UniversalIndentGUI/position", QPoint(50, 50)) ); - qsettings->setValue( "UniversalIndentGUI/size", qsettings->value("UniversalIndentGUI/size", QSize(800, 600)) ); - - // Read last selected encoding for the opened source code file. - qsettings->setValue( "UniversalIndentGUI/encoding", qsettings->value("UniversalIndentGUI/encoding", "UTF-8") ); - - // Read maximum length of list for recently opened files. - qsettings->setValue( "UniversalIndentGUI/recentlyOpenedListSize", qsettings->value("UniversalIndentGUI/recentlyOpenedListSize", 5) ); - - // Read if last opened source code file should be loaded on startup. - qsettings->setValue( "UniversalIndentGUI/loadLastSourceCodeFileOnStartup", qsettings->value("UniversalIndentGUI/loadLastSourceCodeFileOnStartup", true) ); - - // Read last opened source code file from the settings file. - qsettings->setValue( "UniversalIndentGUI/lastSourceCodeFile", qsettings->value("UniversalIndentGUI/lastSourceCodeFile", indenterDirctoryStr+"/example.cpp") ); - - // Read last selected indenter from the settings file. - int selectedIndenter = qsettings->value("UniversalIndentGUI/selectedIndenter", 0).toInt(); - if ( selectedIndenter < 0 ) { - selectedIndenter = 0; - } - qsettings->setValue( "UniversalIndentGUI/selectedIndenter", selectedIndenter ); - - // Read if syntax highlighting is enabled. - qsettings->setValue( "UniversalIndentGUI/SyntaxHighlightingEnabled", qsettings->value("UniversalIndentGUI/SyntaxHighlightingEnabled", true) ); - - // Read if white space characters should be displayed. - qsettings->setValue( "UniversalIndentGUI/whiteSpaceIsVisible", qsettings->value("UniversalIndentGUI/whiteSpaceIsVisible", false) ); - - // Read if indenter parameter tool tips are enabled. - qsettings->setValue( "UniversalIndentGUI/indenterParameterTooltipsEnabled", qsettings->value("UniversalIndentGUI/indenterParameterTooltipsEnabled", true) ); - - // Read the tab width from the settings file. - qsettings->setValue( "UniversalIndentGUI/tabWidth", qsettings->value("UniversalIndentGUI/tabWidth", 4) ); - - // Read the last selected language and stores the index it has in the list of available translations. - qsettings->setValue( "UniversalIndentGUI/language", availableTranslations.indexOf( qsettings->value("UniversalIndentGUI/language", "").toString() ) ); - - // Read the update check settings from the settings file. - qsettings->setValue( "UniversalIndentGUI/CheckForUpdate", qsettings->value("UniversalIndentGUI/CheckForUpdate", true) ); - qsettings->setValue( "UniversalIndentGUI/LastUpdateCheck", qsettings->value("UniversalIndentGUI/LastUpdateCheck", QDate(1900,1,1)) ); - - // Read the main window state. - qsettings->setValue( "UniversalIndentGUI/MainWindowState", qsettings->value("UniversalIndentGUI/MainWindowState", QByteArray()) ); - - return true; -} - - -/*! - \brief Register the by \a propertyName defined property of \a obj to be connected to the setting defined by \a settingName. - - The \a propertyName must be one of those that are listed in the Qt "Properties" documentation section of a Qt Object. - All further needed info is retrieved via the \a obj's MetaObject, like the to the property bound signal. - */ -bool UiGuiSettings::registerObjectProperty( QObject *obj, const QString &propertyName, const QString &settingName ) -{ - const QMetaObject *metaObject = obj->metaObject(); - bool connectSuccess = false; - - // Connect to the objects destroyed signal, so that it will be correctly unregistered. - connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); - - int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); - if ( connectSuccess && indexOfProp > -1 ) { - QMetaProperty mProp = metaObject->property(indexOfProp); - - // Connect to the property's value changed signal. - if ( mProp.hasNotifySignal() ) { - QMetaMethod signal = mProp.notifySignal(); - //QString teststr = qPrintable(SIGNAL() + QString(signal.signature())); - // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL. - connectSuccess = connect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange())); - } - - if ( connectSuccess ) { - registeredObjectProperties[obj] = QStringList() << propertyName << settingName; - } - else { - //TODO: Write a debug warning to the log. - disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); - return false; - } - - // If setting already exists, set the objects property to the setting value. - if ( qsettings->contains("UniversalIndentGUI/" + settingName) ) { - mProp.write(obj, qsettings->value("UniversalIndentGUI/" + settingName)); - } - // Otherwise add the setting and set it to the value of the objects property. - else { - qsettings->setValue("UniversalIndentGUI/" + settingName, mProp.read(obj)); - } - } - else { - //TODO: Write a debug warning to the log. - disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); - return false; - } - - return true; -} - - -/*! - \brief Searches the child QWidgets of \a obj for a property name and setting name definition within - their style sheet string and registers this property to that setting if both were found. - - Returns true, if all found property and setting definitions could be successfully registered. - Returns false, if any of those registrations fails. - */ -bool UiGuiSettings::registerObjectPropertyRecursive(QObject *obj) { - - QRegExp regExpPropertyName("(PropertyName\\s*:\\s*)(\\w+)", Qt::CaseInsensitive); - QRegExp regExpSettingName("(SettingName\\s*:\\s*)(\\w+)", Qt::CaseInsensitive); - bool success = true; - - // Find all widgets that have PropertyName and SettingName defined in their style sheet. - QList allWidgets = obj->findChildren(); - foreach (QWidget *widget, allWidgets) { - QString styleSheetString = widget->styleSheet(); - // Test if style sheet string is set at all. If so get the property and setting name. - if ( !styleSheetString.isEmpty() ) { - QString propertyName; - QString settingName; - if (regExpPropertyName.indexIn(styleSheetString) != -1) { - propertyName = regExpPropertyName.cap(2); - } - if (regExpSettingName.indexIn(styleSheetString) != -1) { - settingName = regExpSettingName.cap(2); - } - - // If property and setting name were found, register that widget with the settings. - if ( !propertyName.isEmpty() && !settingName.isEmpty() ) { - success &= registerObjectProperty( widget, propertyName, settingName ); - } - } - } - - return success; -} - - -/*! - \brief The with a certain property registered \a obj gets unregistered. - */ -void UiGuiSettings::unregisterObjectProperty(QObject *obj) { - if ( registeredObjectProperties.contains(obj) ) { - const QMetaObject *metaObject = obj->metaObject(); - QString propertyName = registeredObjectProperties[obj].first(); - QString settingName = registeredObjectProperties[obj].last(); - - bool connectSuccess = false; - int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); - if ( indexOfProp > -1 ) { - QMetaProperty mProp = metaObject->property(indexOfProp); - - // Disconnect to the property's value changed signal. - if ( mProp.hasNotifySignal() ) { - QMetaMethod signal = mProp.notifySignal(); - // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL. - connectSuccess = disconnect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange())); - } - } - registeredObjectProperties.remove(obj); - } -} - - -/*! - \brief Registers a slot form the \a obj by its \a slotName to be invoked, if the by \a settingName defined - setting changes. - - The registered slot may have no parameters or exactly one. If it accepts one parameter, whenever the setting - \a settingName changes the slot gets tried to be invoked with the settings value as parameter. This only works, - if the slot parameter is of the same type as the setting. - */ -bool UiGuiSettings::registerObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) { - - const QMetaObject *metaObject = obj->metaObject(); - - bool connectSuccess = false; - // Connect to the objects destroyed signal, so that it will be correctly unregistered. - connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); - - QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) ); - int indexOfMethod = metaObject->indexOfMethod( qPrintable(normalizedSlotName) ); - if ( connectSuccess && indexOfMethod > -1 ) { - QMetaMethod mMethod = metaObject->method(indexOfMethod); - QMetaMethod::Access access = mMethod.access(); - QMetaMethod::MethodType methType = mMethod.methodType(); - - // Since the method can at maximum be invoked with the setting value as argument, - // only methods taking max one argument are allowed. - if ( mMethod.parameterTypes().size() <= 1 ) { - registeredObjectSlots.insert(obj, QStringList() << normalizedSlotName << settingName); - } - else { - //TODO: Write a debug warning to the log. - disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); - return false; - } - } - else { - //TODO: Write a debug warning to the log. - disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); - return false; - } - - return true; -} - - -/*! - \brief If \a obj, \a slotName and \a settingName are given, that certain connection is unregistered. - If only \a obj is given, all to this object registered slot-setting connections are unregistered. - */ -void UiGuiSettings::unregisterObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) { - const QMetaObject *metaObject = obj->metaObject(); - QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) ); - QMutableMapIterator it(registeredObjectSlots); - while (it.hasNext()) { - it.next(); - if (it.key() == obj && slotName.isEmpty() && settingName.isEmpty()) - it.remove(); - else if (it.key() == obj && it.value().first() == slotName && it.value().last() == settingName) - it.remove(); - } -} - - -/*! - \brief This private slot gets invoked whenever a registered objects property changes - and distributes the new value to all other to the same settingName registered objects. - */ -void UiGuiSettings::handleObjectPropertyChange() { - QObject *obj = QObject::sender(); - QString className = obj->metaObject()->className(); - const QMetaObject *metaObject = obj->metaObject(); - QString propertyName = registeredObjectProperties[obj].first(); - QString settingName = registeredObjectProperties[obj].last(); - - int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); - if ( indexOfProp > -1 ) { - QMetaProperty mProp = metaObject->property(indexOfProp); - setValueByName(settingName, mProp.read(obj)); - } -} - - -/*! - \brief Sets the setting defined by \a settingName to \a value. - - When setting a changed value, all to this settingName registered objects get - the changed value set too. - If the \a settingName didn't exist yet, it will be created. - */ -void UiGuiSettings::setValueByName(const QString &settingName, const QVariant &value) { - // Do the updating only, if the setting was really changed. - if ( qsettings->value("UniversalIndentGUI/" + settingName) != value ) { - qsettings->setValue("UniversalIndentGUI/" + settingName, value); - - // Set the new value for all registered object properties for settingName. - for ( QMap::ConstIterator it = registeredObjectProperties.begin(); it != registeredObjectProperties.end(); ++it ) { - if ( it.value().last() == settingName ) { - QObject *obj = it.key(); - const QMetaObject *metaObject = obj->metaObject(); - QString propertyName = it.value().first(); - - int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); - if ( indexOfProp > -1 ) { - QMetaProperty mProp = metaObject->property(indexOfProp); - mProp.write(obj, value); - } - } - } - - // Invoke all registered object methods for settingName. - for ( QMap::ConstIterator it = registeredObjectSlots.begin(); it != registeredObjectSlots.end(); ++it ) { - if ( it.value().last() == settingName ) { - QObject *obj = it.key(); - const QMetaObject *metaObject = obj->metaObject(); - QString slotName = it.value().first(); - - int indexOfMethod = metaObject->indexOfMethod( qPrintable(slotName) ); - if ( indexOfMethod > -1 ) { - QMetaMethod mMethod = metaObject->method(indexOfMethod); - QMetaMethod::Access access = mMethod.access(); - QMetaMethod::MethodType methType = mMethod.methodType(); - - bool success = false; - - // Handle registered slots taking one parameter. - if ( mMethod.parameterTypes().size() == 1 ) { - if ( mMethod.parameterTypes().first() == value.typeName() ) { - success = invokeMethodWithValue(obj, mMethod, value); - } - } - // Handle registered slots taking zero parameters. - else { - success = mMethod.invoke( obj, Qt::DirectConnection ); - } - - if ( success == false ) { - // TODO: Write a warning to the log if no success. - } - } - } - } - } -} - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_VERSION >= 0x040600 -#include -#include -#endif - -bool UiGuiSettings::invokeMethodWithValue( QObject *obj, QMetaMethod mMethod, QVariant value ) -{ - switch (value.type()) { - case QVariant::BitArray : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitArray, value.toBitArray()) ); - case QVariant::Bitmap : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitmap, value.value()) ); - case QVariant::Bool : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(bool, value.toBool()) ); - case QVariant::Brush : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBrush, value.value()) ); - case QVariant::ByteArray : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QByteArray, value.toByteArray()) ); - case QVariant::Char : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QChar, value.toChar()) ); - case QVariant::Color : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QColor, value.value()) ); - case QVariant::Cursor : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QCursor, value.value()) ); - case QVariant::Date : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDate, value.toDate()) ); - case QVariant::DateTime : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDateTime, value.toDateTime()) ); - case QVariant::Double : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(double, value.toDouble()) ); - case QVariant::Font : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QFont, value.value()) ); - case QVariant::Hash : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantHash, value.toHash()) ); - case QVariant::Icon : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QIcon, value.value()) ); - case QVariant::Image : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QImage, value.value()) ); - case QVariant::Int : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(int, value.toInt()) ); - case QVariant::KeySequence : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QKeySequence, value.value()) ); - case QVariant::Line : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLine, value.toLine()) ); - case QVariant::LineF : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLineF, value.toLineF()) ); - case QVariant::List : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantList, value.toList()) ); - case QVariant::Locale : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLocale, value.toLocale()) ); - case QVariant::LongLong : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qlonglong, value.toLongLong()) ); - case QVariant::Map : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantMap, value.toMap()) ); - case QVariant::Matrix : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix, value.value()) ); - case QVariant::Transform : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTransform, value.value()) ); -#if QT_VERSION >= 0x040600 - case QVariant::Matrix4x4 : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix4x4, value.value()) ); -#endif - case QVariant::Palette : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPalette, value.value()) ); - case QVariant::Pen : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPen, value.value()) ); - case QVariant::Pixmap : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPixmap, value.value()) ); - case QVariant::Point : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPoint, value.toPoint()) ); - // case QVariant::PointArray : - // return Q_ARG(QPointArray, value.value()) ); - case QVariant::PointF : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPointF, value.toPointF()) ); - case QVariant::Polygon : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPolygon, value.value()) ); -#if QT_VERSION >= 0x040600 - case QVariant::Quaternion : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QQuaternion, value.value()) ); -#endif - case QVariant::Rect : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRect, value.toRect()) ); - case QVariant::RectF : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRectF, value.toRectF()) ); - case QVariant::RegExp : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegExp, value.toRegExp()) ); - case QVariant::Region : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegion, value.value()) ); - case QVariant::Size : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSize, value.toSize()) ); - case QVariant::SizeF : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizeF, value.toSizeF()) ); - case QVariant::SizePolicy : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizePolicy, value.value()) ); - case QVariant::String : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QString, value.toString()) ); - case QVariant::StringList : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QStringList, value.toStringList()) ); - case QVariant::TextFormat : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextFormat, value.value()) ); - case QVariant::TextLength : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextLength, value.value()) ); - case QVariant::Time : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTime, value.toTime()) ); - case QVariant::UInt : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(uint, value.toUInt()) ); - case QVariant::ULongLong : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qulonglong, value.toULongLong()) ); - case QVariant::Url : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QUrl, value.toUrl()) ); -#if QT_VERSION >= 0x040600 - case QVariant::Vector2D : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector2D, value.value()) ); - case QVariant::Vector3D : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector3D, value.value()) ); - case QVariant::Vector4D : - return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector4D, value.value()) ); -#endif - default: - return false; - } -} +/*************************************************************************** +* Copyright (C) 2006-2010 by Thomas Schweitzer * +* thomas-schweitzer(at)arcor.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License version 2.0 as * +* published by the Free Software Foundation. * +* * +* This program 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 General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program in the file LICENSE.GPL; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "UiGuiSettings.h" + +#include "SettingsPaths.h" + +#include +#include +#include + +//! \defgroup grp_Settings All concerning the settings. + +/*! + \class UiGuiSettings + \ingroup grp_Settings + \brief Handles the settings of the program. Reads them on startup and saves them on exit. + Is a singleton class and can only be accessed via getInstance(). +*/ + +// Inits the single class instance pointer. +UiGuiSettings* UiGuiSettings::instance = NULL; + +/*! + \brief The constructor for the settings. +*/ +UiGuiSettings::UiGuiSettings() : QObject() { + // Create the main application settings object from the UniversalIndentGUI.ini file. + qsettings = new QSettings(SettingsPaths::getSettingsPath() + "/UniversalIndentGUI.ini", QSettings::IniFormat, this); + + indenterDirctoryStr = SettingsPaths::getGlobalFilesPath() + "/indenters"; + readAvailableTranslations(); + initSettings(); +} + + +/*! + \brief Returns the instance of the settings class. If no instance exists, ONE will be created. + */ +UiGuiSettings* UiGuiSettings::getInstance() { + if ( instance == NULL ) { + // Create the settings object, which loads all UiGui settings from a file. + instance = new UiGuiSettings(); + } + + return instance; +} + +/*! + \brief Deletes the existing instance of UiGuiSettings and removes the created temp dir. + */ +void UiGuiSettings::deleteInstance() { + SettingsPaths::cleanAndRemoveTempDir(); + if ( instance != NULL ) { + delete instance; + instance = NULL; + } +} + + +/*! + \brief The destructor saves the settings to a file. + */ +UiGuiSettings::~UiGuiSettings() { + // Convert the language setting from an integer index to a string. + int index = qsettings->value("UniversalIndentGUI/language", 0).toInt(); + if ( index < 0 || index >= availableTranslations.size() ) + index = 0; + + qsettings->setValue( "UniversalIndentGUI/language", availableTranslations.at(index) ); +} + + +/*! + \brief Scans the translations directory for available translation files and + stores them in the QList \a availableTranslations. + */ +void UiGuiSettings::readAvailableTranslations() { + QString languageShort; + QStringList languageFileList; + + // English is the default language. A translation file does not exist but to have a menu entry, added here. + languageFileList << "universalindent_en.qm"; + + // Find all translation files in the "translations" directory. + QDir translationDirectory = QDir( SettingsPaths::getGlobalFilesPath() + "/translations" ); + languageFileList << translationDirectory.entryList( QStringList("universalindent_*.qm") ); + + // Loop for each found translation file + foreach ( languageShort, languageFileList ) { + // Remove the leading string "universalindent_" from the filename. + languageShort.remove(0,16); + // Remove trailing file extension ".qm". + languageShort.chop(3); + + availableTranslations.append(languageShort); + } +} + + +/*! + \brief Returns a list of the mnemonics of the available translations. + */ +QStringList UiGuiSettings::getAvailableTranslations() { + return availableTranslations; +} + + +/*! + \brief Returns the value of the by \a settingsName defined setting as QVariant. + + If the named setting does not exist, 0 is being returned. +*/ +QVariant UiGuiSettings::getValueByName(QString settingName) { + return qsettings->value("UniversalIndentGUI/" + settingName); +} + + +/*! + \brief Loads the settings for the main application. + + Settings are for example last selected indenter, last loaded source code file and so on. +*/ +bool UiGuiSettings::initSettings() +{ + // Read the version string saved in the settings file. + qsettings->setValue( "UniversalIndentGUI/version", qsettings->value("UniversalIndentGUI/version", "") ); + + // Read windows last size and position from the settings file. + qsettings->setValue( "UniversalIndentGUI/maximized", qsettings->value("UniversalIndentGUI/maximized", false) ); + qsettings->setValue( "UniversalIndentGUI/position", qsettings->value("UniversalIndentGUI/position", QPoint(50, 50)) ); + qsettings->setValue( "UniversalIndentGUI/size", qsettings->value("UniversalIndentGUI/size", QSize(800, 600)) ); + + // Read last selected encoding for the opened source code file. + qsettings->setValue( "UniversalIndentGUI/encoding", qsettings->value("UniversalIndentGUI/encoding", "UTF-8") ); + + // Read maximum length of list for recently opened files. + qsettings->setValue( "UniversalIndentGUI/recentlyOpenedListSize", qsettings->value("UniversalIndentGUI/recentlyOpenedListSize", 5) ); + + // Read if last opened source code file should be loaded on startup. + qsettings->setValue( "UniversalIndentGUI/loadLastSourceCodeFileOnStartup", qsettings->value("UniversalIndentGUI/loadLastSourceCodeFileOnStartup", true) ); + + // Read last opened source code file from the settings file. + qsettings->setValue( "UniversalIndentGUI/lastSourceCodeFile", qsettings->value("UniversalIndentGUI/lastSourceCodeFile", indenterDirctoryStr+"/example.cpp") ); + + // Read last selected indenter from the settings file. + int selectedIndenter = qsettings->value("UniversalIndentGUI/selectedIndenter", 0).toInt(); + if ( selectedIndenter < 0 ) { + selectedIndenter = 0; + } + qsettings->setValue( "UniversalIndentGUI/selectedIndenter", selectedIndenter ); + + // Read if syntax highlighting is enabled. + qsettings->setValue( "UniversalIndentGUI/SyntaxHighlightingEnabled", qsettings->value("UniversalIndentGUI/SyntaxHighlightingEnabled", true) ); + + // Read if white space characters should be displayed. + qsettings->setValue( "UniversalIndentGUI/whiteSpaceIsVisible", qsettings->value("UniversalIndentGUI/whiteSpaceIsVisible", false) ); + + // Read if indenter parameter tool tips are enabled. + qsettings->setValue( "UniversalIndentGUI/indenterParameterTooltipsEnabled", qsettings->value("UniversalIndentGUI/indenterParameterTooltipsEnabled", true) ); + + // Read the tab width from the settings file. + qsettings->setValue( "UniversalIndentGUI/tabWidth", qsettings->value("UniversalIndentGUI/tabWidth", 4) ); + + // Read the last selected language and stores the index it has in the list of available translations. + qsettings->setValue( "UniversalIndentGUI/language", availableTranslations.indexOf( qsettings->value("UniversalIndentGUI/language", "").toString() ) ); + + // Read the update check settings from the settings file. + qsettings->setValue( "UniversalIndentGUI/CheckForUpdate", qsettings->value("UniversalIndentGUI/CheckForUpdate", true) ); + qsettings->setValue( "UniversalIndentGUI/LastUpdateCheck", qsettings->value("UniversalIndentGUI/LastUpdateCheck", QDate(1900,1,1)) ); + + // Read the main window state. + qsettings->setValue( "UniversalIndentGUI/MainWindowState", qsettings->value("UniversalIndentGUI/MainWindowState", QByteArray()) ); + + return true; +} + + +/*! + \brief Register the by \a propertyName defined property of \a obj to be connected to the setting defined by \a settingName. + + The \a propertyName must be one of those that are listed in the Qt "Properties" documentation section of a Qt Object. + All further needed info is retrieved via the \a obj's MetaObject, like the to the property bound signal. + */ +bool UiGuiSettings::registerObjectProperty( QObject *obj, const QString &propertyName, const QString &settingName ) +{ + const QMetaObject *metaObject = obj->metaObject(); + bool connectSuccess = false; + + // Connect to the objects destroyed signal, so that it will be correctly unregistered. + connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); + + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( connectSuccess && indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + + // Connect to the property's value changed signal. + if ( mProp.hasNotifySignal() ) { + QMetaMethod signal = mProp.notifySignal(); + //QString teststr = qPrintable(SIGNAL() + QString(signal.signature())); + // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL. + connectSuccess = connect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange())); + } + + if ( connectSuccess ) { + registeredObjectProperties[obj] = QStringList() << propertyName << settingName; + } + else { + //TODO: Write a debug warning to the log. + disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); + return false; + } + + // If setting already exists, set the objects property to the setting value. + if ( qsettings->contains("UniversalIndentGUI/" + settingName) ) { + mProp.write(obj, qsettings->value("UniversalIndentGUI/" + settingName)); + } + // Otherwise add the setting and set it to the value of the objects property. + else { + qsettings->setValue("UniversalIndentGUI/" + settingName, mProp.read(obj)); + } + } + else { + //TODO: Write a debug warning to the log. + disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*))); + return false; + } + + return true; +} + + +/*! + \brief Searches the child QObjects of \a obj for a property name and setting name definition within + their custom properties and registers this property name to that setting name if both were found. + + The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName", + where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and + "connectedSettingName" is the name of a setting here within UiGuiSettings. If the mentioned setting + name doesn't exist, it will be created. + + Returns true, if all found property and setting definitions could be successfully registered. + Returns false, if any of those registrations fails. + */ +bool UiGuiSettings::registerObjectPropertyRecursive(QObject *obj) { + return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::registerObjectProperty); +} + + +/*! + \brief Assigns the by \a settingName defined setting value to the by \a propertyName defined property of \a obj. + + Returns true, if the value could be assigned, otherwise returns false, which is the case if settingName doesn't exist + within the settings or if the mentioned propertyName wasn't found for the \a obj. + */ +bool UiGuiSettings::setObjectPropertyToSettingValue( QObject *obj, const QString &propertyName, const QString &settingName ) +{ + const QMetaObject *metaObject = obj->metaObject(); + + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + + // If setting already exists, set the objects property to the setting value. + if ( qsettings->contains("UniversalIndentGUI/" + settingName) ) { + mProp.write(obj, qsettings->value("UniversalIndentGUI/" + settingName)); + } + // The setting didn't exist so return that setting the objects property failed. + else { + //TODO: Write a debug warning to the log. + return false; + } + } + else { + //TODO: Write a debug warning to the log. + return false; + } + + return true; +} + + +/*! + \brief Searches the child QObjects of \a obj for a property name and setting name definition within + their custom properties and sets each property to settings value. + + The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName", + where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and + "connectedSettingName" is the name of a setting here within UiGuiSettings. + + Returns true, if all found property and setting definitions could be successfully registered. + Returns false, if any of those registrations fails. + */ +bool UiGuiSettings::setObjectPropertyToSettingValueRecursive(QObject *obj) { + return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::setObjectPropertyToSettingValue); +} + + +/*! + \brief Assigns the by \a propertyName defined property's value of \a obj to the by \a settingName defined setting. + + If the \a settingName didn't exist yet, it will be created. + + Returns true, if the value could be assigned, otherwise returns false, which is the case if the mentioned + propertyName wasn't found for the \a obj. + */ +bool UiGuiSettings::setSettingToObjectPropertyValue( QObject *obj, const QString &propertyName, const QString &settingName ) +{ + const QMetaObject *metaObject = obj->metaObject(); + + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + + setValueByName(settingName, mProp.read(obj)); + } + else { + //TODO: Write a debug warning to the log. + return false; + } + + return true; +} + + +/*! + \brief Searches the child QObjects of \a obj for a property name and setting name definition within + their custom properties and sets each setting to the property value. + + The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName", + where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and + "connectedSettingName" is the name of a setting here within UiGuiSettings. If the settingName + didn't exist yet, it will be created. + + Returns true, if all found property and setting definitions could be successfully registered. + Returns false, if any of those registrations fails. + */ +bool UiGuiSettings::setSettingToObjectPropertyValueRecursive(QObject *obj) { + return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::setSettingToObjectPropertyValue); +} + + +/*! + \brief Iterates over all \a objs child QObjects and checks whether they have the custom properties + "connectedPropertyName" and "connectedSettingName" set. If both are set, it invokes the \a callBackFunc + with both. + */ +bool UiGuiSettings::checkCustomPropertiesAndCallFunction(QObject *obj, bool (UiGuiSettings::*callBackFunc)(QObject *obj, const QString &propertyName, const QString &settingName)) { + bool success = true; + + // Find all widgets that have PropertyName and SettingName defined in their style sheet. + QList allObjects = obj->findChildren(); + foreach (QObject *object, allObjects) { + QString propertyName = object->property("connectedPropertyName").toString(); + QString settingName = object->property("connectedSettingName").toString(); + + // If property and setting name were found, register that widget with the settings. + if ( !propertyName.isEmpty() && !settingName.isEmpty() ) { + success &= (this->*callBackFunc)( object, propertyName, settingName ); + } + } + + return success; +} + +/*! + \brief The with a certain property registered \a obj gets unregistered. + */ +void UiGuiSettings::unregisterObjectProperty(QObject *obj) { + if ( registeredObjectProperties.contains(obj) ) { + const QMetaObject *metaObject = obj->metaObject(); + QString propertyName = registeredObjectProperties[obj].first(); + QString settingName = registeredObjectProperties[obj].last(); + + bool connectSuccess = false; + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + + // Disconnect to the property's value changed signal. + if ( mProp.hasNotifySignal() ) { + QMetaMethod signal = mProp.notifySignal(); + // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL. + connectSuccess = disconnect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange())); + } + } + registeredObjectProperties.remove(obj); + } +} + + +/*! + \brief Registers a slot form the \a obj by its \a slotName to be invoked, if the by \a settingName defined + setting changes. + + The registered slot may have no parameters or exactly one. If it accepts one parameter, whenever the setting + \a settingName changes the slot gets tried to be invoked with the settings value as parameter. This only works, + if the slot parameter is of the same type as the setting. + */ +bool UiGuiSettings::registerObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) { + + const QMetaObject *metaObject = obj->metaObject(); + + bool connectSuccess = false; + // Connect to the objects destroyed signal, so that it will be correctly unregistered. + connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); + + QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) ); + int indexOfMethod = metaObject->indexOfMethod( qPrintable(normalizedSlotName) ); + if ( connectSuccess && indexOfMethod > -1 ) { + QMetaMethod mMethod = metaObject->method(indexOfMethod); + QMetaMethod::Access access = mMethod.access(); + QMetaMethod::MethodType methType = mMethod.methodType(); + + // Since the method can at maximum be invoked with the setting value as argument, + // only methods taking max one argument are allowed. + if ( mMethod.parameterTypes().size() <= 1 ) { + registeredObjectSlots.insert(obj, QStringList() << normalizedSlotName << settingName); + } + else { + //TODO: Write a debug warning to the log. + disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); + return false; + } + } + else { + //TODO: Write a debug warning to the log. + disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*))); + return false; + } + + return true; +} + + +/*! + \brief If \a obj, \a slotName and \a settingName are given, that certain connection is unregistered. + If only \a obj is given, all to this object registered slot-setting connections are unregistered. + */ +void UiGuiSettings::unregisterObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) { + const QMetaObject *metaObject = obj->metaObject(); + QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) ); + QMutableMapIterator it(registeredObjectSlots); + while (it.hasNext()) { + it.next(); + if (it.key() == obj && slotName.isEmpty() && settingName.isEmpty()) + it.remove(); + else if (it.key() == obj && it.value().first() == slotName && it.value().last() == settingName) + it.remove(); + } +} + + +/*! + \brief This private slot gets invoked whenever a registered objects property changes + and distributes the new value to all other to the same settingName registered objects. + */ +void UiGuiSettings::handleObjectPropertyChange() { + QObject *obj = QObject::sender(); + QString className = obj->metaObject()->className(); + const QMetaObject *metaObject = obj->metaObject(); + QString propertyName = registeredObjectProperties[obj].first(); + QString settingName = registeredObjectProperties[obj].last(); + + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + setValueByName(settingName, mProp.read(obj)); + } +} + + +/*! + \brief Sets the setting defined by \a settingName to \a value. + + When setting a changed value, all to this settingName registered objects get + the changed value set too. + If the \a settingName didn't exist yet, it will be created. + */ +void UiGuiSettings::setValueByName(const QString &settingName, const QVariant &value) { + // Do the updating only, if the setting was really changed. + if ( qsettings->value("UniversalIndentGUI/" + settingName) != value ) { + qsettings->setValue("UniversalIndentGUI/" + settingName, value); + + // Set the new value for all registered object properties for settingName. + for ( QMap::ConstIterator it = registeredObjectProperties.begin(); it != registeredObjectProperties.end(); ++it ) { + if ( it.value().last() == settingName ) { + QObject *obj = it.key(); + const QMetaObject *metaObject = obj->metaObject(); + QString propertyName = it.value().first(); + + int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) ); + if ( indexOfProp > -1 ) { + QMetaProperty mProp = metaObject->property(indexOfProp); + mProp.write(obj, value); + } + } + } + + // Invoke all registered object methods for settingName. + for ( QMap::ConstIterator it = registeredObjectSlots.begin(); it != registeredObjectSlots.end(); ++it ) { + if ( it.value().last() == settingName ) { + QObject *obj = it.key(); + const QMetaObject *metaObject = obj->metaObject(); + QString slotName = it.value().first(); + + int indexOfMethod = metaObject->indexOfMethod( qPrintable(slotName) ); + if ( indexOfMethod > -1 ) { + QMetaMethod mMethod = metaObject->method(indexOfMethod); + QMetaMethod::Access access = mMethod.access(); + QMetaMethod::MethodType methType = mMethod.methodType(); + + bool success = false; + + // Handle registered slots taking one parameter. + if ( mMethod.parameterTypes().size() == 1 ) { + if ( mMethod.parameterTypes().first() == value.typeName() ) { + success = invokeMethodWithValue(obj, mMethod, value); + } + } + // Handle registered slots taking zero parameters. + else { + success = mMethod.invoke( obj, Qt::DirectConnection ); + } + + if ( success == false ) { + // TODO: Write a warning to the log if no success. + } + } + } + } + } +} + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= 0x040600 +#include +#include +#endif + +bool UiGuiSettings::invokeMethodWithValue( QObject *obj, QMetaMethod mMethod, QVariant value ) +{ + switch (value.type()) { + case QVariant::BitArray : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitArray, value.toBitArray()) ); + case QVariant::Bitmap : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitmap, value.value()) ); + case QVariant::Bool : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(bool, value.toBool()) ); + case QVariant::Brush : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBrush, value.value()) ); + case QVariant::ByteArray : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QByteArray, value.toByteArray()) ); + case QVariant::Char : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QChar, value.toChar()) ); + case QVariant::Color : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QColor, value.value()) ); + case QVariant::Cursor : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QCursor, value.value()) ); + case QVariant::Date : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDate, value.toDate()) ); + case QVariant::DateTime : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDateTime, value.toDateTime()) ); + case QVariant::Double : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(double, value.toDouble()) ); + case QVariant::Font : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QFont, value.value()) ); + case QVariant::Hash : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantHash, value.toHash()) ); + case QVariant::Icon : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QIcon, value.value()) ); + case QVariant::Image : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QImage, value.value()) ); + case QVariant::Int : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(int, value.toInt()) ); + case QVariant::KeySequence : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QKeySequence, value.value()) ); + case QVariant::Line : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLine, value.toLine()) ); + case QVariant::LineF : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLineF, value.toLineF()) ); + case QVariant::List : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantList, value.toList()) ); + case QVariant::Locale : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLocale, value.toLocale()) ); + case QVariant::LongLong : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qlonglong, value.toLongLong()) ); + case QVariant::Map : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantMap, value.toMap()) ); + case QVariant::Matrix : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix, value.value()) ); + case QVariant::Transform : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTransform, value.value()) ); +#if QT_VERSION >= 0x040600 + case QVariant::Matrix4x4 : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix4x4, value.value()) ); +#endif + case QVariant::Palette : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPalette, value.value()) ); + case QVariant::Pen : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPen, value.value()) ); + case QVariant::Pixmap : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPixmap, value.value()) ); + case QVariant::Point : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPoint, value.toPoint()) ); + // case QVariant::PointArray : + // return Q_ARG(QPointArray, value.value()) ); + case QVariant::PointF : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPointF, value.toPointF()) ); + case QVariant::Polygon : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPolygon, value.value()) ); +#if QT_VERSION >= 0x040600 + case QVariant::Quaternion : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QQuaternion, value.value()) ); +#endif + case QVariant::Rect : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRect, value.toRect()) ); + case QVariant::RectF : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRectF, value.toRectF()) ); + case QVariant::RegExp : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegExp, value.toRegExp()) ); + case QVariant::Region : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegion, value.value()) ); + case QVariant::Size : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSize, value.toSize()) ); + case QVariant::SizeF : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizeF, value.toSizeF()) ); + case QVariant::SizePolicy : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizePolicy, value.value()) ); + case QVariant::String : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QString, value.toString()) ); + case QVariant::StringList : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QStringList, value.toStringList()) ); + case QVariant::TextFormat : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextFormat, value.value()) ); + case QVariant::TextLength : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextLength, value.value()) ); + case QVariant::Time : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTime, value.toTime()) ); + case QVariant::UInt : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(uint, value.toUInt()) ); + case QVariant::ULongLong : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qulonglong, value.toULongLong()) ); + case QVariant::Url : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QUrl, value.toUrl()) ); +#if QT_VERSION >= 0x040600 + case QVariant::Vector2D : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector2D, value.value()) ); + case QVariant::Vector3D : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector3D, value.value()) ); + case QVariant::Vector4D : + return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector4D, value.value()) ); +#endif + default: + return false; + } +} diff -r d38b69f9987c -r ca1bafc93ee2 src/UiGuiSettings.h --- a/src/UiGuiSettings.h Mon May 24 21:55:34 2010 +0000 +++ b/src/UiGuiSettings.h Tue May 25 18:39:23 2010 +0000 @@ -45,6 +45,10 @@ bool registerObjectProperty(QObject *obj, const QString &propertyName, const QString &settingName); bool registerObjectPropertyRecursive(QObject *obj); + bool setObjectPropertyToSettingValue(QObject *obj, const QString &propertyName, const QString &settingName); + bool setObjectPropertyToSettingValueRecursive(QObject *obj); + bool setSettingToObjectPropertyValue(QObject *obj, const QString &propertyName, const QString &settingName); + bool setSettingToObjectPropertyValueRecursive(QObject *obj); bool registerObjectSlot(QObject *obj, const QString &slotName, const QString &settingName); QVariant getValueByName(QString settingName); QStringList getAvailableTranslations(); @@ -57,6 +61,7 @@ protected: bool initSettings(); bool invokeMethodWithValue(QObject *obj, QMetaMethod mMethod, QVariant value); + bool checkCustomPropertiesAndCallFunction(QObject *obj, bool (UiGuiSettings::*callBackFunc)(QObject *obj, const QString &propertyName, const QString &settingName)); private slots: void handleObjectPropertyChange(); diff -r d38b69f9987c -r ca1bafc93ee2 src/UiGuiSettingsDialog.cpp --- a/src/UiGuiSettingsDialog.cpp Mon May 24 21:55:34 2010 +0000 +++ b/src/UiGuiSettingsDialog.cpp Tue May 25 18:39:23 2010 +0000 @@ -39,15 +39,6 @@ // with the settings dialog. groupBoxSyntaxHighlighterProperties->setToolTip( "(Will be implemented soon)" + groupBoxSyntaxHighlighterProperties->toolTip() ); - // Get all check boxes that are used for settings. - checkBoxes = findChildren( QRegExp("uiGui*") ); - - // Get all spin boxes that are used for settings. - spinBoxes = findChildren( QRegExp("uiGui*") ); - - // Get all combo boxes that are used for settings. - comboBoxes = findChildren( QRegExp("uiGui*") ); - // Connect the accepted signal to own function, to write values back to the UiGuiSettings object. connect(this, SIGNAL(accepted()), this, SLOT(writeWidgetValuesToSettings()) ); @@ -64,35 +55,35 @@ */ void UiGuiSettingsDialog::initTranslationSelection() { // First empty the combo box. - uiGuiLanguageSelectionComboBox->clear(); + languageSelectionComboBox->clear(); // Now add an entry into the box for every language short. foreach (QString languageShort, settings->getAvailableTranslations() ) { // Identify the language mnemonic and set the full name. if ( languageShort == "en" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("English") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("English") ); } else if ( languageShort == "fr" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("French") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("French") ); } else if ( languageShort == "de" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("German") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("German") ); } else if ( languageShort == "zh_TW" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Chinese (Taiwan)") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Chinese (Taiwan)") ); } else if ( languageShort == "ja_jp" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Japanese") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Japanese") ); } else if ( languageShort == "ru" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Russian") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Russian") ); } else if ( languageShort == "uk" ) { - uiGuiLanguageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Ukrainian") ); + languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Ukrainian") ); } else { - uiGuiLanguageSelectionComboBox->addItem( tr("Unknown language mnemonic ") + languageShort ); + languageSelectionComboBox->addItem( tr("Unknown language mnemonic ") + languageShort ); } } } @@ -104,53 +95,8 @@ Before it gets all the values needed from the UiGuiSettings object. */ int UiGuiSettingsDialog::showDialog() { - // Get the values for the check boxes from the settings object. - foreach (QCheckBox* checkBox, checkBoxes) { - // Get the corresponding setting name from the check boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = checkBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = checkBox->objectName(); - settingName.remove(0,5); - } - - // Get value from settings and assign it to the checkbox. - bool value = settings->getValueByName( settingName ).toBool(); - checkBox->setChecked(value); - } - - // Get the values for the spin boxes from the settings object. - foreach (QSpinBox* spinBox, spinBoxes) { - // Get the corresponding setting name from the spin boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = spinBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = spinBox->objectName(); - settingName.remove(0,5); - } - - // Get value from settings and assign it to the checkbox. - int value = settings->getValueByName( settingName ).toInt(); - spinBox->setValue(value); - } - - // Get the values for the combo boxes from the settings object. - foreach (QComboBox* comboBox, comboBoxes) { - // Get the corresponding setting name from the combo boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = comboBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = comboBox->objectName(); - settingName.remove(0,5); - } - - // Get value from settings and assign it to the checkbox. - int value = settings->getValueByName( settingName ).toInt(); - comboBox->setCurrentIndex(value); - } + // Init all settings dialog objects with values from settings. + settings->setObjectPropertyToSettingValueRecursive(this); // Execute the dialog. return exec(); @@ -163,50 +109,8 @@ Writes all settings to the UiGuiSettings object. */ void UiGuiSettingsDialog::writeWidgetValuesToSettings() { - // Write the values of the check boxes to the settings object. - foreach (QCheckBox* checkBox, checkBoxes) { - // Get the corresponding setting name from the check boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = checkBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = checkBox->objectName(); - settingName.remove(0,5); - } - - // Write the check box value to the settings. - settings->setValueByName( settingName, checkBox->isChecked() ); - } - - // Write the values for the spin boxes to the settings object. - foreach (QSpinBox* spinBox, spinBoxes) { - // Get the corresponding setting name from the spin boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = spinBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = spinBox->objectName(); - settingName.remove(0,5); - } - - // Write the spin box value to the settings. - settings->setValueByName( settingName, spinBox->value() ); - } - - // Write the values for the spin boxes to the settings object. - foreach (QComboBox* comboBox, comboBoxes) { - // Get the corresponding setting name from the combo boxs property and remove "DONOTTRANSLATE:" from its beginning. - QString settingName = comboBox->property("connectedSettingName").toString().remove(0, 15); - // If the property is not set, try using the objects name for convenience. - if ( settingName.isEmpty() ) { - // Get the objects name and remove "uiGui" from its beginning and use that as setting name. - settingName = comboBox->objectName(); - settingName.remove(0,5); - } - - // Write the spin box value to the settings. - settings->setValueByName( settingName, comboBox->currentIndex() ); - } + // Write settings dialog object values to settings. + settings->setSettingToObjectPropertyValueRecursive(this); } @@ -230,28 +134,28 @@ // Identify the language mnemonic and set the full name. if ( languageShort == "en" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("English") ); + languageSelectionComboBox->setItemText( i, tr("English") ); } else if ( languageShort == "fr" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("French") ); + languageSelectionComboBox->setItemText( i, tr("French") ); } else if ( languageShort == "de" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("German") ); + languageSelectionComboBox->setItemText( i, tr("German") ); } else if ( languageShort == "zh_TW" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("Chinese (Taiwan)") ); + languageSelectionComboBox->setItemText( i, tr("Chinese (Taiwan)") ); } else if ( languageShort == "ja_jp" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("Japanese") ); + languageSelectionComboBox->setItemText( i, tr("Japanese") ); } else if ( languageShort == "ru" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("Russian") ); + languageSelectionComboBox->setItemText( i, tr("Russian") ); } else if ( languageShort == "uk" ) { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("Ukrainian") ); + languageSelectionComboBox->setItemText( i, tr("Ukrainian") ); } else { - uiGuiLanguageSelectionComboBox->setItemText( i, tr("Unknown language mnemonic ") + languageShort ); + languageSelectionComboBox->setItemText( i, tr("Unknown language mnemonic ") + languageShort ); } } } diff -r d38b69f9987c -r ca1bafc93ee2 src/UiGuiSettingsDialog.h --- a/src/UiGuiSettingsDialog.h Mon May 24 21:55:34 2010 +0000 +++ b/src/UiGuiSettingsDialog.h Tue May 25 18:39:23 2010 +0000 @@ -42,9 +42,6 @@ void initTranslationSelection(); UiGuiSettings* settings; - QList checkBoxes; - QList spinBoxes; - QList comboBoxes; }; #endif // UIGUISETTINGSDIALOG_H diff -r d38b69f9987c -r ca1bafc93ee2 src/UiGuiSettingsDialog.ui --- a/src/UiGuiSettingsDialog.ui Mon May 24 21:55:34 2010 +0000 +++ b/src/UiGuiSettingsDialog.ui Tue May 25 18:39:23 2010 +0000 @@ -46,12 +46,12 @@ Application language - uiGuiLanguageSelectionComboBox + languageSelectionComboBox - + 0 @@ -62,7 +62,10 @@ Displays all available translations for UniversalIndentGui and lets you choose one. - DONOTTRANSLATE:language + language + + + currentIndex @@ -82,7 +85,7 @@ - + If selected opens the source code file on startup that was opened last time. @@ -90,12 +93,15 @@ Automatically open last file on startup - DONOTTRANSLATE:loadLastSourceCodeFileOnStartup + loadLastSourceCodeFileOnStartup + + + checked - + If checked, tool tips will show up if the mouse cursor remains over an indenter parameter for a while. @@ -103,7 +109,10 @@ Enable Parameter Tooltips - DONOTTRANSLATE:indenterParameterTooltipsEnabled + indenterParameterTooltipsEnabled + + + checked @@ -120,7 +129,7 @@ - + 0 @@ -140,7 +149,10 @@ 1 - DONOTTRANSLATE:recentlyOpenedListSize + recentlyOpenedListSize + + + value @@ -184,7 +196,7 @@ - + Enables or disables displaying of white space characters in the editor. @@ -192,7 +204,10 @@ Display white space character (tabs, spaces, etc.) - DONOTTRANSLATE:whiteSpaceIsVisible + whiteSpaceIsVisible + + + checked @@ -212,7 +227,7 @@ - + 0 @@ -232,7 +247,10 @@ 1 - DONOTTRANSLATE:tabWidth + tabWidth + + + value @@ -276,7 +294,7 @@ - + Checks whether a new version of UniversalIndentGUI exists on program start, but only once a day. @@ -284,7 +302,10 @@ Check online for update on program start - DONOTTRANSLATE:CheckForUpdate + CheckForUpdate + + + checked @@ -295,7 +316,7 @@ - + If checked, the made proxy settings will be applied for all network connections. Type of the used proxy is SOCKS5. @@ -303,7 +324,10 @@ Enable proxy - DONOTTRANSLATE:ProxyEnabled + ProxyEnabled + + + checked @@ -319,17 +343,20 @@ Host name: - uiGuiProxyHostNameLineEdit + proxyHostNameLineEdit - + Host name of the to be used proxy. E.g.: proxy.example.com - DONOTTRANSLATE:ProxyHostName + ProxyHostName + + + text @@ -339,12 +366,12 @@ Port: - uiGuiProxyPortSpinBox + proxyPortSpinBox - + Port number to connect to the before named proxy. @@ -355,7 +382,10 @@ QAbstractSpinBox::NoButtons - DONOTTRANSLATE:ProxyPort + ProxyPort + + + text @@ -365,17 +395,20 @@ User name: - uiGuiProxyUserNameLineEdit + proxyUserNameLineEdit - + If the proxy needs authentification, enter the login name here. - DONOTTRANSLATE:ProxyUserName + ProxyUserName + + + text @@ -385,12 +418,12 @@ Password: - uiGuiProxyPasswordLineEdit + proxyPasswordLineEdit - + If the proxy needs authentification, enter the password here. @@ -398,7 +431,10 @@ QLineEdit::Password - DONOTTRANSLATE:ProxyPassword + ProxyPassword + + + text @@ -420,7 +456,7 @@ - + By enabling special key words of the source code are highlighted. @@ -428,7 +464,10 @@ Enable syntax highlighting - DONOTTRANSLATE:SyntaxHighlightingEnabled + SyntaxHighlightingEnabled + + + checked @@ -564,7 +603,7 @@ - uiGuiEnableProxyCheckBox + enableProxyCheckBox toggled(bool) widget setEnabled(bool)