registry.cpp
util.cpp
inifile.cpp
+ config.cpp
)
# Header files for the meta-object compiler
ieventqueue.h
ilogger.h
iregistry.h
+ iconfig.h
app.h
eventqueue.h
logger.h
registry.h
+ config.h
)
# Version info resource file for Windows builds
--- /dev/null
+/**
+ * @file Common/config.cpp
+ * @brief eVaf configuration interface implementation
+ * @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 "config.h"
+#include "inifile.h"
+#include "iregistry.h"
+#include "ilogger.h"
+#include "iapp.h"
+#include "version.h"
+
+#include <QtCore>
+
+//-------------------------------------------------------------------
+
+using namespace eVaf::Common;
+
+iConfig * iConfig::instance()
+{
+ static Internal::Config singleton;
+ return singleton.interface();
+}
+
+
+//-------------------------------------------------------------------
+
+using namespace eVaf::Common::Internal;
+
+Config::Config()
+ : iConfig()
+{
+ setObjectName(QString("%1.iConfig").arg(VER_MODULE_NAME_STR));
+
+ // Register the iConfig interface
+ iRegistry::instance()->registerInterface("iConfig", this);
+}
+
+Config::~Config()
+{
+ done();
+}
+
+iConfig * Config::interface() const
+{
+ return evafQueryInterface<iConfig>("iConfig");
+}
+
+bool Config::init()
+{
+ // Finalize first in case this is not the first time init() is called
+ done();
+
+ return true;
+}
+
+void Config::done()
+{
+ // Commit any queued parameters
+ commitValues();
+
+ // Clear the list of opened INI files
+ QHash<QString, IniFile *>::iterator it = mIniFiles.begin();
+ while (it != mIniFiles.end()) {
+ delete it.value();
+ it = mIniFiles.erase(it);
+ }
+}
+
+QVariant Config::getValue(QString const & paramName, QVariant const & defaultValue) const
+{
+ // Get the optional file part
+ int idx = paramName.indexOf('/');
+ if (idx < 0) {
+ EVAF_ERROR("Invalid parameter name '%s'", qPrintable(paramName));
+ return defaultValue;
+ }
+ QString file = paramName.left(idx);
+ QString name = paramName.mid(idx + 1);
+
+ // Ignore the optional backend identifier in the file name
+ idx = file.indexOf(':');
+ if (idx >= 0)
+ file.remove(0, idx + 1);
+
+ // If the file name is empty or '*', use the application's name
+ if (file.isEmpty() || file == "*")
+ file = iApp::instance()->name();
+
+ IniFile * ini = 0;
+
+ // Is this INI file already opened?
+ QHash<QString, IniFile *>::const_iterator it = mIniFiles.constFind(file);
+
+ // The file is opened and we can reuse it
+ if (it != mIniFiles.constEnd()) {
+ ini = *it;
+ }
+
+ // The file is not opened
+ else {
+ ini = new IniFile(QString("%1/%2.ini").arg(iApp::instance()->etcDir()).arg(file));
+ if (!ini->isValid()) {
+ EVAF_ERROR("Failed to open '%s' : %s", qPrintable(name), qPrintable(ini->errorString()));
+ delete ini;
+ return defaultValue;
+ }
+ mIniFiles.insert(file, ini);
+ }
+
+ // Read the value
+ return ini->getValue(name, defaultValue);
+}
+
+bool Config::setValue(QString const & paramName, QVariant const & value, bool commit)
+{
+ if (!commit) {
+ // Queue the write operation
+ mCommitQueue.enqueue(NameValuePair(paramName, value));
+ }
+ else {
+ // Commit any queued parameters
+ if (!commitValues())
+ return false;
+
+ // Write the parameter
+ if (!writeValue(paramName, value))
+ return false;
+ }
+
+ return true;
+}
+
+bool Config::commitValues()
+{
+ while (!mCommitQueue.isEmpty()) {
+ if (!writeValue(mCommitQueue.dequeue())) {
+ mCommitQueue.clear();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Config::writeValue(QString const & paramName, QVariant const & value)
+{
+ // Get the optional file part
+ int idx = paramName.indexOf('/');
+ if (idx < 0) {
+ EVAF_ERROR("Invalid parameter name '%s'", qPrintable(paramName));
+ return false;
+ }
+ QString file = paramName.left(idx);
+ QString name = paramName.mid(idx + 1);
+
+ // Ignore the optional backend identifier in the file name
+ idx = file.indexOf(':');
+ if (idx >= 0)
+ file.remove(0, idx + 1);
+
+ // If the file name is empty or '*', use the application's name
+ if (file.isEmpty() || file == "*")
+ file = iApp::instance()->name();
+
+ IniFile * ini = 0;
+
+ // Is this INI file already opened?
+ QHash<QString, IniFile *>::const_iterator it = mIniFiles.constFind(file);
+
+ // The file is opened and we can reuse it
+ if (it != mIniFiles.constEnd()) {
+ ini = *it;
+ }
+
+ // The file is not opened
+ else {
+ ini = new IniFile(QString("%1/%2.ini").arg(iApp::instance()->etcDir()).arg(file));
+ if (!ini->isValid()) {
+ EVAF_ERROR("Failed to open '%s' : %s", qPrintable(name), qPrintable(ini->errorString()));
+ delete ini;
+ return false;
+ }
+ mIniFiles.insert(file, ini);
+ }
+
+ // Write the value
+ if (!ini->setValue(name, value))
+ return false;
+
+ return true;
+}
--- /dev/null
+/**
+ * @file Common/config.h
+ * @brief eVaf configuration interface implementation
+ * @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_CONFIG_H
+# define __COMMON_CONFIG_H
+
+#include "iconfig.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QHash>
+#include <QQueue>
+
+namespace eVaf {
+namespace Common {
+ class IniFile;
+namespace Internal {
+
+/**
+ * Structure for queued write operations
+ */
+struct NameValuePair
+{
+ NameValuePair(QString const & n, QVariant const & v)
+ : name(n)
+ , value(v)
+ {}
+
+ QString name;
+ QVariant value;
+};
+
+/**
+ * Default implementation of the iConfig interface.
+ *
+ * This class implements the iConfig interface using INI files in the eVaf::Common::iApp::instance()->etcDir() directory.
+ */
+class Config : public iConfig
+{
+ Q_OBJECT
+
+public:
+
+ Config();
+
+ virtual ~Config();
+
+ /**
+ * Returns the current implementation of the iConfig interface
+ */
+ iConfig * interface() const;
+
+ /**
+ * Initializes the iConfig interface implementation.
+ * @return True if succeeded; false if not
+ */
+ bool init();
+
+ /**
+ * Finalizes the iConfig interface implementation.
+ */
+ void done();
+
+ /*
+ iConfig interface
+ */
+
+ virtual QVariant getValue(QString const & paramName, QVariant const & defaultValue) const;
+
+ virtual bool setValue(QString const & paramName, QVariant const & value, bool commit);
+
+
+private: // Members
+
+ /// List of already opened INI files
+ mutable QHash<QString, IniFile *> mIniFiles;
+
+ /// Commit queue
+ QQueue<NameValuePair> mCommitQueue;
+
+
+private: // Methods
+
+ /// Commits queued parameters
+ bool commitValues();
+
+ /// Writes a parameter value to the INI file
+ bool writeValue(QString const & paramName, QVariant const & value);
+
+ /// Writes a name/value pair to the INI file
+ inline bool writeValue(NameValuePair const & param)
+ {
+ return writeValue(param.name, param.value);
+ }
+
+};
+
+} // namespace eVaf::Common::Internal
+} // namespace eVaf::Common
+} // namespace eVaf
+
+#endif // config.h
#include "globals.h"
#include "app.h"
+#include "config.h"
#include "logger.h"
#include "version.h"
#include "ilogger.h"
if (!logger->init())
return false;
}
+ eVaf::Common::Internal::Config * config =
+ qobject_cast<eVaf::Common::Internal::Config *>(eVaf::Common::iConfig::instance());
+ if (config) {
+ if (!config->init())
+ return false;
+ }
EVAF_INFO("%s-Globals initialized", VER_MODULE_NAME_STR);
--- /dev/null
+#include "iconfig.h"
--- /dev/null
+/**
+ * @file Common/iconfig.h
+ * @brief eVaf configuration 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_ICONFIG_H
+# define __COMMON_ICONFIG_H
+
+#include "libcommon.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+
+namespace eVaf {
+namespace Common {
+
+/**
+ * eVaf configuration interface.
+ * @code#include <iConfig>@endcode
+ *
+ * The iConfig interface provides access to configuration parameters. Methods in this interface can be
+ * used to read and write configuration parameters.
+ *
+ * The default implementation of the iConfig interface uses INI files in the eVaf::Common::iApp::instance()->etcDir()
+ * directory. Additional configuration backends can be provided by re-implementing the interface.
+ *
+ * Configuration parameters are identified by a name in the following format:
+ * [\<backend:\>][\<file\>]/\<section\>/\<key\>
+ *
+ * Where:
+ * @li \<backend:\> is an optional identifier for the configuration backend. This part is ignored by the default
+ * iConfig interface implementation and is reserved for custom modules. For example, a custom module could look
+ * for the 'db:' backend identifier and store parameters in a database. Any other requests would be forwarded to
+ * the default implementation.
+ * @li \<file\> is an optional configuration file name. The default iConfig interface implementation uses the file
+ * name part to locate the INI file in the eVaf::Common::iApp::instance()->etcDir() directory. If the file name part
+ * is '*' or empty, uses eVaf::Common::iApp::instance()->name() for the file name.
+ * @li \<section\> is the name of the section. Section names can contain extra '/' characters to build a structured
+ * tree of configuration sections.
+ * @li \<key\> is the name of the key.
+ *
+ * For example:
+ * @li 'db:local/extensions/help/module' - backend 'db:', file or database name 'local', section name 'extensions/help' and
+ * the key 'module';
+ * @li '/extensions/help/module' - default backend, default file name, section name 'extensions/help' and the key 'module'.
+ */
+class COMMON_EXPORT iConfig : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /// Interface constructor
+ iConfig() : QObject() {}
+
+ /// Empty virtual destructor
+ virtual ~iConfig() {}
+
+ /**
+ * Returns the current iConfig interface instance
+ * @return The iConfig interface
+ *
+ * This method returns the current iConfig interface instance as shown in the following example:
+ * @code
+ * QString moduleName = eVaf::Common::iConfig::instance()->getValue("/extensions/help/module", "libHelp.so").toString();
+ * @endcode
+ */
+ static iConfig * instance();
+
+ /**
+ * Reads a configuration parameter value
+ * @param paramName Name of the parameter
+ * @param defaultValue Default value
+ * @return The parameter value or the default value if the parameter cannot be found
+ *
+ * The getValue() method returns a configuration parameter value identified by the parameter name. If the parameter
+ * cannot be read or is not found, returns the default value.
+ *
+ * The default value is used to determine the type of the value. For example, if the default value is an integer, then
+ * the returned value is also an integer. The default iConfig interface implementation validates parameter values and
+ * makes sure that the parameter value is of the proper type. If the value cannot be converted to the proper type,
+ * returns the default value. Other implementations of the iConfig interface are encouraged to do the same.
+ */
+ virtual QVariant getValue(QString const & paramName, QVariant const & defaultValue) const = 0;
+
+ /**
+ * Writes a configuration parameter value
+ * @param paramName Name of the parameter
+ * @param value The parameter value
+ * @param commit If true, then commits new parameter values
+ * @return True if succeeded; false if not
+ *
+ * The setValue() method writes new configuration parameter values identified by the parameter name.
+ *
+ * The commit argument can be used to improve the performance of writing several parameter values at once. Use
+ * commit = false for all except the last parameter's write operation.
+ * @code
+ * iConfig * conf = eVaf::Common::iConfig::instance();
+ * conf->setValue("/main/param1", 1, false);
+ * conf->setValue("/main/param2", 2, false);
+ * conf->setValue("/main/param3", 3); // Last parameter in the block
+ * @endcode
+ */
+ virtual bool setValue(QString const & paramName, QVariant const & value, bool commit = true) = 0;
+
+};
+
+
+} // namespace eVaf::Common
+} // namespace eVaf
+
+#endif // iconfig.h