+/**
+ * @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 <QtCore>
+
+//-------------------------------------------------------------------
+
+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>("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<QString, QVariant>::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<QString, QVariant>::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);
+}