/** * @file Common/prop.h * @brief Implementation of the iProp interface * @author Enar Vaikene * * Copyright (c) 2011-2019 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; namespace { static Internal::Prop * singleton = nullptr; } iProp * iProp::instance() { if (nullptr == singleton) { singleton = new Internal::Prop; } return singleton->_interface(); } //------------------------------------------------------------------- using namespace eVaf::Common::Internal; void Prop::destroyInstance() { if (nullptr != singleton) { delete singleton; singleton = nullptr; } } Prop::Prop() : iProp() { setObjectName(QString("%1.iProp").arg(VER_MODULE_NAME_STR)); // Register the iProp interface iRegistry::instance()->registerInterface("iProp", this); EVAF_INFO("%s-Prop created", VER_MODULE_NAME_STR); } Prop::~Prop() { done(); EVAF_INFO("%s-Prop destroyed", VER_MODULE_NAME_STR); } iProp * Prop::_interface() const { return evafQueryInterface("iProp"); } bool Prop::init() { // 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") { #if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) 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 mPersistentProps.reset(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() { mPersistentProps.reset(); } 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); }