From: Enar Väikene Date: Wed, 23 Nov 2011 10:10:10 +0000 (+0200) Subject: Added the eVaf::Common::iProp interface for global properties and variables. X-Git-Url: https://vaikene.ee/gitweb/index.html?a=commitdiff_plain;h=f01d61fb753b347bbff2ffb7f224650ac3f9d81e;p=evaf Added the eVaf::Common::iProp interface for global properties and variables. --- diff --git a/src/libs/Common/CMakeLists.txt b/src/libs/Common/CMakeLists.txt index f308c06..a9916b4 100644 --- a/src/libs/Common/CMakeLists.txt +++ b/src/libs/Common/CMakeLists.txt @@ -25,6 +25,7 @@ set(SRCS util.cpp inifile.cpp config.cpp + prop.cpp ) # Header files for the meta-object compiler @@ -34,11 +35,13 @@ set(MOC_HDRS ilogger.h iregistry.h iconfig.h + iprop.h app.h eventqueue.h logger.h registry.h config.h + prop.h ) # Version info resource file for Windows builds diff --git a/src/libs/Common/globals.cpp b/src/libs/Common/globals.cpp index b981fff..02aedd8 100644 --- a/src/libs/Common/globals.cpp +++ b/src/libs/Common/globals.cpp @@ -20,6 +20,7 @@ #include "globals.h" #include "app.h" #include "config.h" +#include "prop.h" #include "logger.h" #include "version.h" #include "ilogger.h" @@ -41,23 +42,29 @@ bool eVaf::Common::init() // Initialize all the common interface implementations in the proper sequence eVaf::Common::Internal::App * app = - qobject_cast(eVaf::Common::iApp::instance()); + qobject_cast(eVaf::Common::iApp::instance()); if (app) { if (!app->init()) return false; } eVaf::Common::Internal::Logger * logger = - qobject_cast(eVaf::Common::iLogger::instance()); + qobject_cast(eVaf::Common::iLogger::instance()); if (logger) { if (!logger->init()) return false; } eVaf::Common::Internal::Config * config = - qobject_cast(eVaf::Common::iConfig::instance()); + qobject_cast(eVaf::Common::iConfig::instance()); if (config) { if (!config->init()) return false; } + eVaf::Common::Internal::Prop * prop = + qobject_cast(eVaf::Common::iProp::instance()); + if (prop) { + if (!prop->init()) + return false; + } EVAF_INFO("%s-Globals initialized", VER_MODULE_NAME_STR); diff --git a/src/libs/Common/iProp b/src/libs/Common/iProp new file mode 100644 index 0000000..5a0b9d2 --- /dev/null +++ b/src/libs/Common/iProp @@ -0,0 +1 @@ +#include "iprop.h" diff --git a/src/libs/Common/iprop.h b/src/libs/Common/iprop.h new file mode 100644 index 0000000..864c8f5 --- /dev/null +++ b/src/libs/Common/iprop.h @@ -0,0 +1,122 @@ +/** + * @file Common/iprop.h + * @brief eVaf properties interface + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __COMMON_IPROP_H +# define __COMMON_IPROP_H + +#include "libcommon.h" + +#include +#include +#include + +namespace eVaf { +namespace Common { + +/** + * Global properties and variables for eVaf applications. + * @code#include @endcode + * + * Global properties and variables are shared by all the eVaf modules. Their function is similar to + * configuration parameters with the main difference that properties are not meant to be modified by + * users. For example, the 'applicationName' property contains the name of the current application. + * + * Properties are implemented as name/value pairs where the name uniquely identifies the property. + * The default implementation of the iProp interface does not enforce any rules for property names and any + * string is a valid name. + * + * Properties can be temporary or persistent. Temporary properties exist only as long as the application + * is running and will be lost when the application is restarted. Persistent properties are stored + * and reloaded when the application is restarted. + * + * Application's XML file section \ can be used to define default properties for the application. + * These are initialized when the application is started up. + * + * Individual properties are defined in \ nodes with the following attributes: + * @li name="\" - specifies the name of the global property; + * @li value="\" - specifies the value of the global property; + * @li config="\" - value of the property is read from the configuration file (used only if + * the 'value' attribute is missing); + * @li windowsonly="yes" - the property is initialized only on Windows; + * @li linuxonly="yes" - the property is initialized only on Linux. + */ +class COMMON_EXPORT iProp : public QObject +{ + Q_OBJECT + +public: + + /// Interface constructor + iProp() : QObject() {} + + /// Empty virtual dtor + virtual ~iProp() {} + + /** + * Returns the iProp interface instance + * @return The iProp interface instance + * + * This function returns the global iProp interface instance. If the eVaf module is linked against + * the common eVaf library, then this is the preferred method of obtaining the iProp interface. + * Another option would be using the eVaf::Common::iRegistry interface. + */ + static iProp * instance(); + + /** + * Returns the value of the global property or variable + * @param name Name of the property + * @param defaultValue Default value + * @return The value of the global property or the default value if the property cannot be found + * + * The getValue() function returns a global property or variable identified by the name. If the property + * is not found, returns the default value. + */ + virtual QVariant getValue(QString const & name, QVariant const & defaultValue = QVariant()) const = 0; + + /** + * Sets the global property or variable + * @param name Name of the property + * @param value Value of the property + * @param persistent If True, then the property is stored permanently + * + * The setValue() function sets the value of a global property or variable identified by the name. The property + * is added if it does not exist. Set the persistent argument to True to make the change permanent. + * + * The valueChanged() signal is emitted indicating that a property changed. + */ + virtual void setValue(QString const & name, QVariant const & value, bool persistent = false) = 0; + + +signals: + + /** + * Global property or variable changed + * @param name Name of the property + * @param value New value of the property + * + * The valueChanged() signal is emitted when a global property or variable is changed. + */ + void valueChanged(QString const & name, QVariant const & value); + +}; + +} // namespace eVaf::Common +} // namespace eVaf + +#endif // iprop.h diff --git a/src/libs/Common/prop.cpp b/src/libs/Common/prop.cpp new file mode 100644 index 0000000..b3ccb6f --- /dev/null +++ b/src/libs/Common/prop.cpp @@ -0,0 +1,170 @@ +/** + * @file Common/prop.h + * @brief Implementation of the iProp interface + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "prop.h" +#include "iregistry.h" +#include "ilogger.h" +#include "iapp.h" +#include "iconfig.h" +#include "util.h" +#include "version.h" + +#include + +//------------------------------------------------------------------- + +using namespace eVaf::Common; + +iProp * iProp::instance() +{ + static Internal::Prop singleton; + return singleton.interface(); +} + + +//------------------------------------------------------------------- + +using namespace eVaf::Common::Internal; + +Prop::Prop() + : iProp() + , mPersistentProps(0) +{ + setObjectName(QString("%1.iProp").arg(VER_MODULE_NAME_STR)); +} + +Prop::~Prop() +{ + done(); +} + +iProp * Prop::interface() const +{ + return evafQueryInterface("iProp"); +} + +bool Prop::init() +{ + // Register the iProp interface + iRegistry::instance()->registerInterface("iProp", this); + + // Set application name and language properties + setValue("applicationName", iApp::instance()->name()); + setValue("applicationLanguage", iApp::instance()->language()); + + // Initialize properties defined in the application's XML file + QFile xmlFile(iApp::instance()->etcDir() + iApp::instance()->xmlFileName()); + if (xmlFile.open(QFile::ReadOnly)) { + bool isProp = false; + QXmlStreamReader xml(&xmlFile); + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == "properties") { + isProp = true; + } + else if (isProp && xml.name() == "property") { +#ifdef Q_OS_LINUX + if (isTrue(xml.attributes().value("windowsonly").toString())) + continue; +#endif +#ifdef Q_OS_WIN32 + if (isTrue(xml.attributes().value("linuxonly").toString())) + continue; +#endif + // Get the name/value pair + QString name = xml.attributes().value("name").toString(); + if (name.isEmpty()) + continue; + QString value = xml.attributes().value("value").toString(); + + // If value is empty, try the configuration + if (value.isEmpty()) { + QString paramName = xml.attributes().value("config").toString(); + if (!paramName.isEmpty()) + value = iConfig::instance()->getValue(paramName, "").toString(); + } + + setValue(name, value); + } + } + else if (xml.isEndElement()) { + if (xml.name() == "properties") + isProp = false; + } + } + if (xml.hasError()) { + EVAF_FATAL_ERROR("Error in the application's XML file %s : %s", qPrintable(xmlFile.fileName()), qPrintable(xml.errorString())); + return false; + } + } + + // Initialize persistent properties + if (mPersistentProps) + delete mPersistentProps; + mPersistentProps = new QSettings(QString("%1/.%2.dat").arg(iApp::instance()->dataRootDir()).arg(iApp::instance()->name()), QSettings::IniFormat); + QStringList keys = mPersistentProps->allKeys(); + for (int i = 0; i < keys.size(); ++i) { + QString key = keys.at(i); + setValue(key, mPersistentProps->value(key)); + } + + return true; +} + +void Prop::done() +{ + if (mPersistentProps) { + delete mPersistentProps; + mPersistentProps = 0; + } +} + +QVariant Prop::getValue(QString const & name, QVariant const & defaultValue) const +{ + QHash::const_iterator it = mProps.constFind(name); + if (it != mProps.constEnd()) { + QVariant value = *it; + if (value.type() == defaultValue.type()) + return value; + else + return toVariant(value.toString(), defaultValue); + } + else + return defaultValue; +} + +void Prop::setValue(QString const & name, QVariant const & value, bool persistent) +{ + bool isChanged = true; + + QHash::iterator it = mProps.find(name); + if (it != mProps.end()) { + isChanged = *it != value; + *it = value; + } + else + mProps.insert(name, value); + + if (persistent && mPersistentProps && mPersistentProps->isWritable()) + mPersistentProps->setValue(name, value); + + if (isChanged) + emit valueChanged(name, value); +} diff --git a/src/libs/Common/prop.h b/src/libs/Common/prop.h new file mode 100644 index 0000000..4e44e27 --- /dev/null +++ b/src/libs/Common/prop.h @@ -0,0 +1,90 @@ +/** + * @file Common/prop.h + * @brief Implementation of the iProp interface + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __COMMON_PROP_H +# define __COMMON_PROP_H + +#include "iprop.h" + +#include + +class QSettings; + +namespace eVaf { +namespace Common { +namespace Internal { + +/** + * Implementation of the iProp interface. + * + * This class implements the iProp interface for global properties and variables. + * Persistent properties are stored in the file '.\.dat' in the directory + * returned with the eVaf::Common::iApp::dataRootDir() function. The file is in the + * QSettings::IniFormat format. + */ +class Prop : public iProp +{ + Q_OBJECT + +public: + + Prop(); + + virtual ~Prop(); + + /** + * Returns the current implementation of the iProp interface + */ + iProp * interface() const; + + /** + * Initializes the iProp interface implementation + * @return True if succeeded; false if not + */ + bool init(); + + /** + * Finalizes the iProp interface implementation + */ + void done(); + + /* + iProp interface + */ + + virtual QVariant getValue(QString const & name, QVariant const & defaultValue) const; + + virtual void setValue(QString const & name, QVariant const & value, bool persistent = false); + + +private: // Members + + /// List of properties + QHash mProps; + + /// Persistent property values + QSettings * mPersistentProps; + +}; + +} // namespace eVaf::Common::Internal +} // namespace eVaf::Common +} // namespace eVaf + +#endif // prop.h