]> vaikene.ee Git - evaf/blob - src/libs/Common/app.cpp
60ee5bf698d00b809e6050bd2b6f17c9b4f8d76c
[evaf] / src / libs / Common / app.cpp
1 /**
2 * @file Common/app.cpp
3 * @brief Application 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 "app.h"
21 #include "globals.h"
22 #include "iregistry.h"
23 #include "ieventqueue.h"
24 #include "event.h"
25 #include "version.h"
26
27 #include <QtCore>
28
29
30 //-------------------------------------------------------------------
31
32 using namespace eVaf::Common;
33
34 iApp * iApp::instance()
35 {
36 static Internal::App singleton;
37 return &singleton;
38 }
39
40 char const * const iApp::EV_QUIT = "iApp::quit";
41 char const * const iApp::EV_RESTART = "iApp::restart";
42 char const * const iApp::EV_READY = "iApp::ready";
43 char const * const iApp::EV_TERMINATING = "iApp::terminating";
44
45
46 //-------------------------------------------------------------------
47
48 using namespace eVaf::Common::Internal;
49
50 App::App()
51 : iApp()
52 , mReady(false)
53 , mName(VER_PRODUCT_NAME_STR)
54 , mEvQuit(0)
55 , mEvRestart(0)
56 , mEvReady(0)
57 , mEvTerminating(0)
58 {
59 setObjectName(QString("%1.iApp").arg(VER_MODULE_NAME_STR));
60
61 }
62
63 App::~App()
64 {
65 }
66
67 bool App::init()
68 {
69 // Register our interface
70 iRegistry::instance()->registerInterface("iApp", this);
71
72 // Register events
73 mEvQuit = iEventQueue::instance()->subscribeEvent(iEventQueue::instance()->registerEvent(EV_QUIT), this);
74 mEvRestart = iEventQueue::instance()->subscribeEvent(iEventQueue::instance()->registerEvent(EV_RESTART), this);
75 mEvReady = iEventQueue::instance()->registerEvent(EV_READY);
76 mEvTerminating = iEventQueue::instance()->registerEvent(EV_TERMINATING);
77
78 // Set the default application name and language
79 mName = VER_PRODUCT_NAME_STR;
80 mLanguage = QLocale::system().name();
81
82 // Clear the XML file name
83 mXmlFile.clear();
84
85 // Set initial bin and root directories
86 mRootDir = mBinDir = qApp->applicationDirPath();
87 int t = mBinDir.lastIndexOf(QChar('/'), -1);
88 if (t >= 0)
89 mRootDir = mBinDir.left(t);
90
91 if (!mBinDir.endsWith('/'))
92 mBinDir.append('/');
93 if (!mRootDir.endsWith('/'))
94 mRootDir.append('/');
95
96 // Clear other directories
97 mDataRootDir.clear();
98 mQtPluginsDir.clear();
99 mEtcDir.clear();
100 mLogDir.clear();
101 mDocDir.clear();
102
103 // Process environment variables
104 QStringList env = QProcess::systemEnvironment();
105 for (int i = 0; i < env.size(); ++i) {
106 // Get the name/value pair
107 QString name = env.at(i).section('=', 0, 0).trimmed();
108 QString value = env.at(i).section('=', 1).trimmed();
109
110 if (name == "EVAF_APP_NAME")
111 mName = value;
112 else if (name == "EVAF_LANGUAGE")
113 mLanguage = value;
114 else if (name == "EVAF_ROOT_DIR") {
115 mRootDir = value;
116 if (!mRootDir.endsWith('/'))
117 mRootDir.append('/');
118 }
119 else if (name == "EVAF_DATA_ROOT_DIR") {
120 mDataRootDir = value;
121 if (!mDataRootDir.endsWith('/'))
122 mDataRootDir.append('/');
123 }
124 else if (name == "EVAF_ETC_DIR") {
125 mEtcDir = value;
126 if (!mEtcDir.endsWith('/'))
127 mEtcDir.append('/');
128 }
129 else if (name == "EVAF_LOG_DIR") {
130 mLogDir = value;
131 if (!mLogDir.endsWith('/'))
132 mLogDir.append('/');
133 }
134 else if (name == "EVAF_DOC_DIR") {
135 mDocDir = value;
136 if (!mDocDir.endsWith('/'))
137 mDocDir.append('/');
138 }
139 else if (name == "EVAF_QT_PLUGINS_DIR") {
140 mQtPluginsDir = value;
141 if (!mQtPluginsDir.endsWith('/'))
142 mQtPluginsDir.append('/');
143 }
144 }
145
146 // Then process command-line arguments
147 env = QCoreApplication::arguments();
148 for (int i = 0; i < env.size(); ++i) {
149 // Get the name and optional value
150 QStringList arg = env.at(i).simplified().split('=');
151
152 if (QRegExp("-[-]?app(lication)?").exactMatch(arg.at(0)) && arg.size() > 1)
153 mName = arg.at(1);
154 else if (QRegExp("-[-]?lang(uage)?").exactMatch(arg.at(0)) && arg.size() > 1)
155 mLanguage = arg.at(1);
156 else if (QRegExp("-[-]?root(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
157 mRootDir = arg.at(1);
158 if (!mRootDir.endsWith('/'))
159 mRootDir.append('/');
160 }
161 else if (QRegExp("-[-]?dataroot(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
162 mDataRootDir = arg.at(1);
163 if (!mDataRootDir.endsWith('/'))
164 mDataRootDir.append('/');
165 }
166 else if (QRegExp("-[-]?etc(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
167 mEtcDir = arg.at(1);
168 if (!mEtcDir.endsWith('/'))
169 mEtcDir.append('/');
170 }
171 else if (QRegExp("-[-]?log(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
172 mLogDir = arg.at(1);
173 if (!mLogDir.endsWith('/'))
174 mLogDir.append('/');
175 }
176 else if (QRegExp("-[-]?doc(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
177 mDocDir = arg.at(1);
178 if (!mDocDir.endsWith('/'))
179 mDocDir.append('/');
180 }
181 else if (QRegExp("-[-]?qtplugins(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
182 mQtPluginsDir = arg.at(1);
183 if (!mQtPluginsDir.endsWith('/'))
184 mQtPluginsDir.append('/');
185 }
186 }
187
188 return true;
189 }
190
191 bool App::event(QEvent * e)
192 {
193 if (e->type() == Event::eVafEvent) {
194 Event * event = static_cast<Event *>(e);
195 if (event->id() == mEvQuit)
196 quit();
197 else if (event->id() == mEvRestart)
198 restart();
199
200 return false;
201 }
202 else
203 return iApp::event(e);
204 }
205
206 QString const App::dataRootDir() const
207 {
208 if (mDataRootDir.isEmpty()) {
209 #ifdef Q_OS_LINUX
210 QString dataLoc = QDir::homePath();
211 if (!dataLoc.endsWith('/'))
212 dataLoc.append('/');
213 dataLoc.append(".local/share/data/");
214 mDataRootDir = dataLoc + name();
215 if (!mDataRootDir.endsWith('/'))
216 mDataRootDir.append('/');
217 #endif
218 /// @TODO: Needs local data directory on Windows
219 mDataRootDir = rootDir();
220 }
221
222 return mDataRootDir;
223 }
224
225 QString const App::etcDir() const
226 {
227 if (mEtcDir.isEmpty())
228 mEtcDir = dataRootDir() + "etc/";
229 return mEtcDir;
230 }
231
232 QString const App::logDir() const
233 {
234 if (mLogDir.isEmpty())
235 mLogDir = dataRootDir() + "log/";
236 return mLogDir;
237 }
238
239 QString const App::docDir() const
240 {
241 if (mDocDir.isEmpty())
242 mDocDir = rootDir() + "doc/";
243 return mDocDir;
244 }
245
246 QString const App::qtPluginsDir() const
247 {
248 if (mQtPluginsDir.isEmpty())
249 mQtPluginsDir = binDir();
250 return mQtPluginsDir;
251 }
252
253 QString const App::xmlFileName() const
254 {
255 if (mXmlFile.isEmpty()) {
256 QFileInfo fi;
257
258 // Try the full application name + country + language combination
259 QString name = mName + "_" + mLanguage + ".xml";
260 fi.setFile(etcDir() + name);
261 if (fi.isReadable())
262 mXmlFile = name;
263 else {
264 // Try application name + country
265 name = mName + "_" + mLanguage.left(2) + ".xml";
266 fi.setFile(etcDir() + name);
267 if (fi.isReadable())
268 mXmlFile = name;
269 else
270 // Fall-back to the generic name
271 mXmlFile = mName + ".xml";
272 }
273 }
274 return mXmlFile;
275 }
276
277 int App::exec()
278 {
279 setReady(true);
280 int rval = QCoreApplication::exec();
281 setReady(false);
282 return rval;
283 }
284
285 void App::restart()
286 {
287 QCoreApplication::exit(RC_Restart);
288 }
289
290 void App::quit(bool err)
291 {
292 QCoreApplication::exit(err ? RC_Error : RC_Quit);
293 }
294
295 void App::setReady(bool value)
296 {
297 if (mReady != value) {
298 mReady = value;
299 iEventQueue::instance()->broadcastEvent(new Event(mReady ? mEvReady : mEvTerminating));
300 if (mReady)
301 emit ready();
302 else
303 emit terminating();
304 }
305 }