]> vaikene.ee Git - evaf/blob - src/libs/Common/config.cpp
c4f09970ff13e5ccf47a7a5ae2afb63f5612c5ce
[evaf] / src / libs / Common / config.cpp
1 /**
2 * @file Common/config.cpp
3 * @brief eVaf configuration interface implementation
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2011 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "config.h"
21 #include "inifile.h"
22 #include "iregistry.h"
23 #include "ilogger.h"
24 #include "iapp.h"
25 #include "version.h"
26
27 #include <QtCore>
28
29 //-------------------------------------------------------------------
30
31 using namespace eVaf::Common;
32
33 iConfig * iConfig::instance()
34 {
35 static Internal::Config singleton;
36 return singleton.interface();
37 }
38
39
40 //-------------------------------------------------------------------
41
42 using namespace eVaf::Common::Internal;
43
44 Config::Config()
45 : iConfig()
46 {
47 setObjectName(QString("%1.iConfig").arg(VER_MODULE_NAME_STR));
48
49 // Register the iConfig interface
50 iRegistry::instance()->registerInterface("iConfig", this);
51 }
52
53 Config::~Config()
54 {
55 done();
56 }
57
58 iConfig * Config::interface() const
59 {
60 return evafQueryInterface<iConfig>("iConfig");
61 }
62
63 bool Config::init()
64 {
65 // Finalize first in case this is not the first time init() is called
66 done();
67
68 return true;
69 }
70
71 void Config::done()
72 {
73 // Commit any queued parameters
74 commitValues();
75
76 // Clear the list of opened INI files
77 QHash<QString, IniFile *>::iterator it = mIniFiles.begin();
78 while (it != mIniFiles.end()) {
79 delete it.value();
80 it = mIniFiles.erase(it);
81 }
82 }
83
84 QVariant Config::getValue(QString const & paramName, QVariant const & defaultValue) const
85 {
86 // Get the optional file part
87 int idx = paramName.indexOf('/');
88 if (idx < 0) {
89 EVAF_ERROR("Invalid parameter name '%s'", qPrintable(paramName));
90 return defaultValue;
91 }
92 QString file = paramName.left(idx);
93 QString name = paramName.mid(idx + 1);
94
95 // Ignore the optional backend identifier in the file name
96 idx = file.indexOf(':');
97 if (idx >= 0)
98 file.remove(0, idx + 1);
99
100 // If the file name is empty or '*', use the application's name
101 if (file.isEmpty() || file == "*")
102 file = iApp::instance()->name();
103
104 IniFile * ini = 0;
105
106 // Is this INI file already opened?
107 QHash<QString, IniFile *>::const_iterator it = mIniFiles.constFind(file);
108
109 // The file is opened and we can reuse it
110 if (it != mIniFiles.constEnd()) {
111 ini = *it;
112 }
113
114 // The file is not opened
115 else {
116 ini = new IniFile(QString("%1/%2.ini").arg(iApp::instance()->etcDir()).arg(file));
117 if (!ini->isValid()) {
118 EVAF_ERROR("Failed to open '%s' : %s", qPrintable(name), qPrintable(ini->errorString()));
119 delete ini;
120 return defaultValue;
121 }
122 mIniFiles.insert(file, ini);
123 }
124
125 // Read the value
126 return ini->getValue(name.toLocal8Bit(), defaultValue);
127 }
128
129 bool Config::setValue(QString const & paramName, QVariant const & value, bool commit)
130 {
131 if (!commit) {
132 // Queue the write operation
133 mCommitQueue.enqueue(NameValuePair(paramName, value));
134 }
135 else {
136 // Commit any queued parameters
137 if (!commitValues())
138 return false;
139
140 // Write the parameter
141 if (!writeValue(paramName, value))
142 return false;
143 }
144
145 return true;
146 }
147
148 bool Config::commitValues()
149 {
150 while (!mCommitQueue.isEmpty()) {
151 if (!writeValue(mCommitQueue.dequeue())) {
152 mCommitQueue.clear();
153 return false;
154 }
155 }
156 return true;
157 }
158
159 bool Config::writeValue(QString const & paramName, QVariant const & value)
160 {
161 // Get the optional file part
162 int idx = paramName.indexOf('/');
163 if (idx < 0) {
164 EVAF_ERROR("Invalid parameter name '%s'", qPrintable(paramName));
165 return false;
166 }
167 QString file = paramName.left(idx);
168 QString name = paramName.mid(idx + 1);
169
170 // Ignore the optional backend identifier in the file name
171 idx = file.indexOf(':');
172 if (idx >= 0)
173 file.remove(0, idx + 1);
174
175 // If the file name is empty or '*', use the application's name
176 if (file.isEmpty() || file == "*")
177 file = iApp::instance()->name();
178
179 IniFile * ini = 0;
180
181 // Is this INI file already opened?
182 QHash<QString, IniFile *>::const_iterator it = mIniFiles.constFind(file);
183
184 // The file is opened and we can reuse it
185 if (it != mIniFiles.constEnd()) {
186 ini = *it;
187 }
188
189 // The file is not opened
190 else {
191 ini = new IniFile(QString("%1/%2.ini").arg(iApp::instance()->etcDir()).arg(file));
192 if (!ini->isValid()) {
193 EVAF_ERROR("Failed to open '%s' : %s", qPrintable(name), qPrintable(ini->errorString()));
194 delete ini;
195 return false;
196 }
197 mIniFiles.insert(file, ini);
198 }
199
200 // Write the value
201 if (!ini->setValue(name.toLocal8Bit(), value))
202 return false;
203
204 return true;
205 }