Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
19 | |||
92 | Werner | 20 | /** @class GlobalSettings |
21 | This class contains various global structures/definitions. This class is a Singleton and accessed via the static instance() function. |
||
99 | Werner | 22 | @par various (textual) meta data (SettingMetaData) |
92 | Werner | 23 | |
99 | Werner | 24 | @par global database connections |
92 | Werner | 25 | There are two defined global database connections dbin() and dbout() with the names "in" and "out". |
26 | They are setup with setupDatabaseConnection(). Currently, only SQLite DBs are supported. |
||
27 | Use dbin() and dbout() to faciliate those database connections: |
||
28 | @code |
||
29 | ... |
||
30 | QSqlQuery query(GlobalSettings::instance()->dbin()); |
||
31 | query.exec(...); |
||
32 | ... |
||
33 | @endcode |
||
99 | Werner | 34 | |
35 | @par Helpers with file Paths |
||
36 | the actual project file is parsed for path defined in the <path> section. |
||
37 | Use the path() function to expand a @p fileName to a iLand-Path. To check if a file exists, you could |
||
38 | use fileExists(). |
||
39 | Available paths: |
||
40 | - home: the project's home directory. All other directories can be defined relative to this dir. |
||
41 | - lip: path for the storage of LIP (aka binary Stamp files) (default: home/lip) |
||
42 | - database: base path for SQLite database files (default: home/database) |
||
43 | - temp: path for storage of temporary files (default: home/temp) |
||
44 | - log: storage for log-files (default: home/log) |
||
45 | - exe: the path to the executable file. |
||
46 | @code |
||
47 | // home is "e:/iland/test", temp is "c:\temp" and log is omitted in project-file: |
||
48 | QString p; |
||
49 | p = Globals->path("somestuff.txt", "temp"); // > c:\temp\somestuff.txt |
||
50 | p = Globals->path("e:\averyspecial\place.txt", "temp"); // -> e:\averyspecial\place.txt |
||
51 | // (abs. path is not changed) |
||
52 | p = Globals->path("log123.txt", "log"); // -> e:/iland/test/log/log123.txt (default for log) |
||
53 | @endcode |
||
54 | |||
126 | Werner | 55 | @par Fine-Grained debugging outputs |
56 | The enumeration DebugOutputs defines a list of realms (uses binary notation: 1,2,4,8,...!). |
||
57 | Use setDebugOutput() to enable/disable such an output. Use isDebugEnabled() to test inside the |
||
58 | code if the generation of debug output for a specific type is enabled. Internally, this is a single |
||
59 | bitwise operation which is very fast. |
||
60 | Call debugLists() to retrieve a list of lists of data that fit specific criteria. |
||
61 | @code |
||
62 | // use something like that somewhere in a tree-growth-related routine: |
||
63 | DBGMODE( |
||
64 | if (GlobalSettings::instance()->isDebugEnabled(GlobalSettings::dTreeGrowth) { |
||
65 | DebugList &out = GlobalSettings::instance()->debugList(mId, GlobalSettings::dTreeGrowth); // get a ref to the list |
||
66 | out << hd_growth << factor_diameter << delta_d_estimate << d_increment; // fill with data |
||
67 | } |
||
68 | ); // only in debugmode |
||
69 | @endcode |
||
70 | |||
92 | Werner | 71 | */ |
126 | Werner | 72 | #include "globalsettings.h" |
87 | Werner | 73 | #include <QtCore> |
74 | #include <QtXml> |
||
91 | Werner | 75 | #include <QtSql> |
793 | werner | 76 | #include <QJSEngine> |
340 | werner | 77 | #include <algorithm> |
93 | Werner | 78 | #include "global.h" |
79 | #include "helper.h" |
||
99 | Werner | 80 | #include "xmlhelper.h" |
486 | werner | 81 | #include "stdint.h" |
126 | Werner | 82 | |
87 | Werner | 83 | #include "settingmetadata.h" |
615 | werner | 84 | #include "standstatistics.h" |
767 | werner | 85 | #include "scriptglobal.h" |
87 | Werner | 86 | |
615 | werner | 87 | |
202 | werner | 88 | #include "outputmanager.h" |
176 | werner | 89 | |
117 | Werner | 90 | // debug macro helpers |
91 | void dbg_helper(const char *where, const char *what,const char* file,int line) |
||
92 | { |
||
93 | qDebug() << "Warning in " << where << ":"<< what << ". (file: " << file << "line:" << line; |
||
94 | } |
||
95 | void dbg_helper_ext(const char *where, const char *what,const char* file,int line, const QString &s) |
||
96 | { |
||
97 | qDebug() << "Warning in " << where << ":"<< what << ". (file: " << file << "line:" << line << "more:" << s; |
||
98 | } |
||
99 | |||
431 | werner | 100 | int _loglevel=0; |
101 | // true, if detailed debug information is logged |
||
102 | bool logLevelDebug() |
||
103 | { |
||
104 | return _loglevel<1; |
||
105 | } |
||
117 | Werner | 106 | |
431 | werner | 107 | // true, if only important aggreate info is logged |
108 | bool logLevelInfo() |
||
109 | { |
||
110 | return _loglevel<2; |
||
111 | } |
||
112 | |||
113 | // true if only severe warnings/errors are logged. |
||
114 | bool logLevelWarning() |
||
115 | { |
||
116 | return _loglevel<3; |
||
117 | } |
||
118 | void setLogLevel(int loglevel) |
||
119 | { |
||
120 | _loglevel=loglevel; |
||
121 | switch (loglevel) { |
||
122 | case 0: qDebug() << "Loglevel set to Debug."; break; |
||
123 | case 1: qDebug() << "Loglevel set to Info."; break; |
||
124 | case 2: qDebug() << "Loglevel set to Warning."; break; |
||
125 | case 3: qDebug() << "Loglevel set to Error/Quiet."; break; |
||
126 | default: qDebug() << "invalid log level" << loglevel; break; |
||
127 | } |
||
128 | } |
||
129 | |||
87 | Werner | 130 | GlobalSettings *GlobalSettings::mInstance = 0; |
131 | |||
132 | GlobalSettings::GlobalSettings() |
||
133 | { |
||
126 | Werner | 134 | mDebugOutputs = 0; |
137 | Werner | 135 | mModel = 0; |
590 | werner | 136 | mModelController = 0; |
615 | werner | 137 | mSystemStatistics = new SystemStatistics; |
176 | werner | 138 | // create output manager |
139 | mOutputManager = new OutputManager(); |
||
767 | werner | 140 | mScriptEngine = 0; |
141 | |||
87 | Werner | 142 | } |
143 | |||
89 | Werner | 144 | |
145 | GlobalSettings::~GlobalSettings() |
||
146 | { |
||
147 | // meta data... really clear ressources... |
||
148 | qDeleteAll(mSettingMetaData.values()); |
||
615 | werner | 149 | delete mSystemStatistics; |
89 | Werner | 150 | mInstance = NULL; |
176 | werner | 151 | delete mOutputManager; |
265 | werner | 152 | // clear all databases |
153 | clearDatabaseConnections(); |
||
767 | werner | 154 | if (mScriptEngine) |
155 | delete mScriptEngine; |
||
89 | Werner | 156 | } |
157 | |||
767 | werner | 158 | QString GlobalSettings::executeJavascript(const QString &command) |
159 | { |
||
160 | return ScriptGlobal::executeScript(command); |
||
161 | } |
||
162 | |||
1157 | werner | 163 | QString GlobalSettings::executeJSFunction(const QString function_name) |
164 | { |
||
165 | return ScriptGlobal::executeJSFunction(function_name); |
||
166 | } |
||
167 | |||
767 | werner | 168 | void GlobalSettings::resetScriptEngine() |
169 | { |
||
170 | if (mScriptEngine) |
||
171 | delete mScriptEngine; |
||
172 | |||
793 | werner | 173 | mScriptEngine = new QJSEngine(); |
767 | werner | 174 | // globals object: instatiate here, but ownership goes to script engine |
175 | ScriptGlobal *global = new ScriptGlobal(); |
||
793 | werner | 176 | QJSValue glb = mScriptEngine->newQObject(global); |
767 | werner | 177 | mScriptEngine->globalObject().setProperty("Globals", glb); |
178 | } |
||
179 | |||
126 | Werner | 180 | // debugging |
181 | void GlobalSettings::setDebugOutput(const GlobalSettings::DebugOutputs dbg, const bool enable) |
||
182 | { |
||
183 | if (enable) |
||
184 | mDebugOutputs |= int(dbg); |
||
185 | else |
||
186 | mDebugOutputs &= int(dbg) ^ 0xffffffff; |
||
187 | } |
||
188 | |||
599 | werner | 189 | // storing the names of debug outputs |
190 | // enum DebugOutputs { dTreeNPP=1, dTreePartition=2, dTreeGrowth=4, |
||
191 | // dStandNPP=8, dWaterCycle=16, dDailyResponses=32, dEstablishment=64, dCarbonCycle=128 }; ///< defines available debug output types. |
||
615 | werner | 192 | const QStringList debug_output_names=QStringList() << "treeNPP" << "treePartition" << "treeGrowth" << "waterCycle" << "dailyResponse" << "establishment" << "carbonCycle" << "performance"; |
126 | Werner | 193 | |
599 | werner | 194 | ///< returns the name attached to 'd' or an empty string if not found |
195 | QString GlobalSettings::debugOutputName(const DebugOutputs d) |
||
196 | { |
||
197 | // this is a little hacky...(and never really tried!) |
||
198 | for (int i=0;i<debug_output_names.count();++i) { |
||
199 | if (d & (2<<i)) |
||
200 | return debug_output_names[i]; |
||
201 | } |
||
202 | return QString(); |
||
203 | } |
||
204 | |||
205 | ///< returns the DebugOutputs bit or 0 if not found |
||
206 | GlobalSettings::DebugOutputs GlobalSettings::debugOutputId(const QString debug_name) |
||
207 | { |
||
208 | int index = debug_output_names.indexOf(debug_name); |
||
209 | if (index==-1) return GlobalSettings::DebugOutputs(0); |
||
210 | return GlobalSettings::DebugOutputs(2 << index); // 1,2,4,8, ... |
||
211 | } |
||
212 | |||
213 | |||
214 | |||
135 | Werner | 215 | void GlobalSettings::clearDebugLists() |
216 | { |
||
217 | mDebugLists.clear(); |
||
218 | } |
||
219 | |||
382 | werner | 220 | QMutex debugListMutex; |
126 | Werner | 221 | DebugList &GlobalSettings::debugList(const int ID, const DebugOutputs dbg) |
222 | { |
||
382 | werner | 223 | QMutexLocker m(&debugListMutex); // serialize creation of debug outputs |
136 | Werner | 224 | DebugList dbglist; |
162 | werner | 225 | dbglist << ID << dbg << currentYear(); |
528 | werner | 226 | int id = ID; |
227 | // use negative values for debug-outputs on RU - level |
||
228 | // Note: at some point we will also have to handle RUS-level... |
||
1168 | werner | 229 | if (dbg == dEstablishment || dbg == dCarbonCycle || dbg == dSaplingGrowth) |
528 | werner | 230 | id = -id; |
231 | QMultiHash<int, DebugList>::iterator newitem = mDebugLists.insert(id, dbglist); |
||
136 | Werner | 232 | return *newitem; |
126 | Werner | 233 | } |
630 | werner | 234 | bool debuglist_sorter (const DebugList *i,const DebugList *j) |
339 | werner | 235 | { |
630 | werner | 236 | return ((*i)[0].toInt() < (*j)[0].toInt()); |
339 | werner | 237 | } |
630 | werner | 238 | const QList<const DebugList*> GlobalSettings::debugLists(const int ID, const DebugOutputs dbg) |
126 | Werner | 239 | { |
630 | werner | 240 | QList<const DebugList*> result_list; |
136 | Werner | 241 | if (ID==-1) { |
630 | werner | 242 | foreach(const DebugList &list, mDebugLists) |
136 | Werner | 243 | if (list.count()>2) // contains data |
126 | Werner | 244 | if (int(dbg)==-1 || (list[1]).toInt() & int(dbg) ) // type fits or is -1 for all |
630 | werner | 245 | result_list << &list; |
136 | Werner | 246 | } else { |
247 | // search a specific id |
||
630 | werner | 248 | QMultiHash<int, DebugList>::const_iterator res = mDebugLists.find(ID); |
136 | Werner | 249 | while (res != mDebugLists.end() && res.key() == ID) { |
630 | werner | 250 | const DebugList &list = res.value(); |
136 | Werner | 251 | if (list.count()>2) // contains data |
252 | if (int(dbg)==-1 || (list[1]).toInt() & int(dbg) ) // type fits or is -1 for all |
||
630 | werner | 253 | result_list << &list; |
136 | Werner | 254 | ++res; |
255 | } |
||
256 | } |
||
339 | werner | 257 | // sort result list |
780 | werner | 258 | //std::sort(result_list.begin(), result_list.end(), debuglist_sorter); // changed because of compiler warnings |
259 | qSort(result_list.begin(), result_list.end(), debuglist_sorter); |
||
126 | Werner | 260 | return result_list; |
261 | } |
||
262 | |||
263 | QStringList GlobalSettings::debugListCaptions(const DebugOutputs dbg) |
||
264 | { |
||
143 | Werner | 265 | QStringList treeCaps = QStringList() << "Id" << "Species" << "Dbh" << "Height" << "x" << "y" << "ru_index" << "LRI" |
266 | << "mWoody" << "mRoot" << "mFoliage" << "LA"; |
||
144 | Werner | 267 | if ( int(dbg)==0) |
268 | return treeCaps; |
||
126 | Werner | 269 | switch(dbg) { |
442 | werner | 270 | case dTreeNPP: return QStringList() << "id" << "type" << "year" << treeCaps |
1168 | werner | 271 | << "LRI_modRU" <<"lightResponse" << "effective_area" << "raw_gpp" << "gpp" << "npp" << "aging"; |
133 | Werner | 272 | |
442 | werner | 273 | case dTreeGrowth: return QStringList() << "id" << "type" << "year" << treeCaps |
1168 | werner | 274 | << "netNPPStem" << "massStemOld" << "hd_growth" << "factor_diameter" << "delta_d_estimate" << "d_increment"; |
129 | Werner | 275 | |
442 | werner | 276 | case dTreePartition: return QStringList() << "id" << "type" << "year" << treeCaps |
1168 | werner | 277 | << "npp_kg" << "apct_foliage" << "apct_wood" << "apct_root" |
278 | << "delta_foliage" << "delta_woody" << "delta_root" << "mNPPReserve" << "netStemInc" << "stress_index"; |
||
129 | Werner | 279 | |
1196 | werner | 280 | case dStandGPP: return QStringList() << "id" << "type" << "year" << "species" << "RU_index" << "rid" << "lai_factor" << "gpp_kg_m2" << "gpp_kg" << "avg_aging" << "f_env_yr"; |
442 | werner | 281 | |
605 | werner | 282 | case dWaterCycle: return QStringList() << "id" << "type" << "year" << "date" << "ruindex" << "rid" << "temp" << "vpd" << "prec" << "rad" << "combined_response" |
1168 | werner | 283 | << "after_intercept" << "after_snow" << "et_canopy" << "evapo_intercepted" |
284 | << "content" << "psi_kpa" << "excess_mm" << "snow_height"; |
||
442 | werner | 285 | |
605 | werner | 286 | case dDailyResponses: return QStringList() << "id" << "type" << "year" << "species" << "date" << "RU_index" << "rid" |
1168 | werner | 287 | << "waterResponse" << "tempResponse" << "VpdResponse" << "Radiation of day" << "util.Radiation"; |
442 | werner | 288 | |
605 | werner | 289 | case dEstablishment: return QStringList() << "id" << "type" << "year" << "species" << "RU_index" << "rid" |
1168 | werner | 290 | << "avgProbDensity" << "TACAminTemp" << "TACAchill" << "TACAfrostFree" << "TACAgdd" << "TACAFrostAfterBud" << "waterLimitation" << "TACAAbioticEnv" |
1174 | werner | 291 | << "fEnvYr" <<"N_Established" ; |
1168 | werner | 292 | |
293 | case dSaplingGrowth: return QStringList() << "id" << "type" << "year" << "species" << "RU_index" << "rid" |
||
294 | << "Living_cohorts" << "averageHeight" << "averageAge" << "avgDeltaHPot" << "avgDeltaHRealized" |
||
295 | << "Added" << "Died" << "Recruited" << "refRatio"; |
||
296 | |||
605 | werner | 297 | case dCarbonCycle: return QStringList() << "id" << "type" << "year" << "RU_index" << "rid" |
1168 | werner | 298 | << "SnagState_c" << "TotalC_in" << "TotalC_toAtm" << "SWDtoDWD_c" << "SWDtoDWD_n" << "toLabile_c" << "toLabile_n" << "toRefr_c" << "toRefr_n" |
299 | << "swd1_c" << "swd1_n" << "swd1_count" << "swd1_tsd" << "toSwd1_c" << "toSwd1_n" << "dbh1" << "height1" << "volume1" // pool of small dbhs |
||
300 | << "swd2_c" << "swd2_n" << "swd2_count" << "swd2_tsd" << "toSwd2_c" << "toSwd2_n" << "dbh2" << "height2" << "volume2" // standing woody debris medium dbhs |
||
301 | << "swd3_c" << "swd3_n" << "swd3_count" << "swd3_tsd" << "toSwd3_c" << "toSwd3_n" << "dbh3" << "height3" << "volume3" // large trees |
||
302 | << "otherWood1_c" << "otherWood1_n" << "otherWood2_c" << "otherWood2_n" << "otherWood3_c" << "otherWood3_n" << "otherWood4_c" << "otherWood4_n" << "otherWood5_c" << "otherWood5_n" |
||
303 | << "iLabC" << "iLabN" << "iKyl" << "iRefC" << "iRefN" << "iKyr" << "re" << "kyl" << "kyr" << "ylC" << "ylN" << "yrC" << "yrN" << "somC" << "somN" |
||
304 | << "NAvailable" << "NAVLab" << "NAVRef" << "NAVSom"; |
||
615 | werner | 305 | case dPerformance: return QStringList() << "id" << "type" << "year" << "treeCount" << "saplingCount" << "newSaplings" << "management" |
1168 | werner | 306 | << "applyPattern" << "readPattern" << "treeGrowth" << "seedDistribution" << "establishment"<< "saplingGrowth" << "carbonCycle" |
307 | << "writeOutput" << "totalYear"; |
||
526 | werner | 308 | |
126 | Werner | 309 | } |
310 | return QStringList() << "invalid debug output!"; |
||
311 | } |
||
312 | |||
613 | werner | 313 | QStringList GlobalSettings::debugDataTable(GlobalSettings::DebugOutputs type, const QString separator, const QString fileName) |
130 | Werner | 314 | { |
126 | Werner | 315 | |
130 | Werner | 316 | GlobalSettings *g = GlobalSettings::instance(); |
630 | werner | 317 | QList<const DebugList*> ddl = g->debugLists(-1, type); // get all debug data |
130 | Werner | 318 | |
319 | QStringList result; |
||
613 | werner | 320 | if (ddl.count()==0) |
321 | return result; |
||
602 | werner | 322 | |
613 | werner | 323 | QFile out_file(fileName); |
324 | QTextStream ts; |
||
325 | if (!fileName.isEmpty()) { |
||
326 | if (out_file.open(QFile::WriteOnly)) { |
||
327 | ts.setDevice(&out_file); |
||
328 | ts << g->debugListCaptions(type).join(separator) << endl; |
||
329 | } else { |
||
330 | qDebug() << "Cannot open debug output file" << fileName; |
||
331 | } |
||
332 | |||
333 | } |
||
334 | |||
656 | werner | 335 | for (int i=ddl.count()-1; i>=0; --i) { |
130 | Werner | 336 | QString line; |
337 | int c=0; |
||
656 | werner | 338 | foreach(const QVariant &value, *ddl.at(i)) { |
130 | Werner | 339 | if (c++) |
340 | line+=separator; |
||
341 | line += value.toString(); |
||
342 | } |
||
613 | werner | 343 | if (out_file.isOpen()) |
344 | ts << line << endl; |
||
345 | else |
||
346 | result << line; |
||
130 | Werner | 347 | } |
602 | werner | 348 | if (!result.isEmpty()) |
349 | result.push_front( g->debugListCaptions(type).join(separator) ); |
||
350 | |||
130 | Werner | 351 | return result; |
352 | } |
||
353 | |||
160 | werner | 354 | QList<QPair<QString, QVariant> > GlobalSettings::debugValues(const int ID) |
355 | { |
||
356 | |||
357 | QList<QPair<QString, QVariant> > result; |
||
358 | QMultiHash<int, DebugList>::iterator res = mDebugLists.find(ID); |
||
359 | while (res != mDebugLists.end() && res.key() == ID) { |
||
360 | DebugList &list = res.value(); |
||
361 | if (list.count()>2) { // contains data |
||
362 | QStringList cap = debugListCaptions( DebugOutputs(list[1].toInt()) ); |
||
363 | result.append(QPair<QString, QVariant>("Debug data", "Debug data") ); |
||
163 | werner | 364 | int first_index = 3; |
365 | if (list[3]=="Id") // skip default data fields (not needed for drill down) |
||
366 | first_index=14; |
||
367 | for (int i=first_index;i<list.count();++i) |
||
160 | werner | 368 | result.append(QPair<QString, QVariant>(cap[i], list[i])); |
369 | } |
||
370 | ++res; |
||
371 | } |
||
372 | return result; |
||
373 | } |
||
374 | |||
89 | Werner | 375 | /** retrieve a const pointer to a stored SettingMetaData object. |
160 | werner | 376 | if @p name is not found, NULL is returned. |
88 | Werner | 377 | */ |
89 | Werner | 378 | const SettingMetaData *GlobalSettings::settingMetaData(const QString &name) |
87 | Werner | 379 | { |
380 | if (mSettingMetaData.contains(name)) { |
||
88 | Werner | 381 | return mSettingMetaData[name]; |
87 | Werner | 382 | } |
89 | Werner | 383 | return NULL; |
87 | Werner | 384 | } |
385 | |||
88 | Werner | 386 | QVariant GlobalSettings::settingDefaultValue(const QString &name) |
387 | { |
||
89 | Werner | 388 | const SettingMetaData *smd = settingMetaData(name); |
389 | if (smd) |
||
390 | return smd->defaultValue(); |
||
391 | return QVariant(0); |
||
88 | Werner | 392 | } |
393 | |||
87 | Werner | 394 | void GlobalSettings::loadSettingsMetaDataFromFile(const QString &fileName) |
395 | { |
||
396 | QString metadata = Helper::loadTextFile(fileName); |
||
397 | } |
||
398 | |||
399 | QString childText(QDomElement &elem, const QString &name, const QString &def="") { |
||
400 | QDomElement e = elem.firstChildElement(name); |
||
401 | if (elem.isNull()) |
||
402 | return def; |
||
403 | else |
||
404 | return e.text(); |
||
405 | } |
||
406 | |||
88 | Werner | 407 | /** Load setting meta data from a piece of XML. |
408 | @p topNode is a XML node, that contains the "setting" nodes as childs: |
||
409 | @code |
||
410 | <topnode> |
||
411 | <setting>...</setting> |
||
412 | <setting>...</setting> |
||
413 | ... |
||
414 | </topnode> |
||
415 | @endcode |
||
416 | */ |
||
87 | Werner | 417 | void GlobalSettings::loadSettingsMetaDataFromXml(const QDomElement &topNode) |
418 | { |
||
419 | mSettingMetaData.clear(); |
||
420 | if (topNode.isNull()) |
||
421 | WARNINGRETURN( "GlobalSettings::loadSettingsMetaDataFromXml():: no globalsettings section!"); |
||
422 | |||
423 | QString settingName; |
||
424 | QDomElement elt = topNode.firstChildElement("setting"); |
||
425 | for (; !elt.isNull(); elt = elt.nextSiblingElement("setting")) { |
||
426 | settingName = elt.attribute("name", "invalid"); |
||
427 | if (mSettingMetaData.contains(settingName)) |
||
428 | WARNINGRETURN( "GlobalSettings::loadSettingsMetaDataFromXml():: setting" << settingName << "already exists in the settings list!") ; |
||
429 | |||
94 | Werner | 430 | SettingMetaData *md = new SettingMetaData(SettingMetaData::typeFromName(elt.attribute("type", "invalid")), // type |
87 | Werner | 431 | settingName, // name |
432 | childText(elt,"description"), // description |
||
433 | childText(elt, "url"), // url |
||
89 | Werner | 434 | QVariant(childText(elt,"default"))); |
435 | mSettingMetaData[settingName] = md; |
||
436 | |||
437 | qDebug() << md->dump(); |
||
88 | Werner | 438 | //mSettingMetaData[settingName].dump(); |
87 | Werner | 439 | } |
440 | qDebug() << "setup settingmetadata complete." << mSettingMetaData.count() << "items loaded."; |
||
441 | } |
||
91 | Werner | 442 | |
92 | Werner | 443 | void GlobalSettings::clearDatabaseConnections() |
444 | { |
||
445 | QSqlDatabase::removeDatabase("in"); |
||
446 | QSqlDatabase::removeDatabase("out"); |
||
194 | werner | 447 | QSqlDatabase::removeDatabase("climate"); |
92 | Werner | 448 | } |
91 | Werner | 449 | |
194 | werner | 450 | bool GlobalSettings::setupDatabaseConnection(const QString& dbname, const QString &fileName, bool fileMustExist) |
91 | Werner | 451 | { |
407 | werner | 452 | |
583 | werner | 453 | //QSqlDatabase::database(dbname).close(); // close database |
231 | werner | 454 | QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",dbname); // addDatabase replaces a connection with the same name |
94 | Werner | 455 | qDebug() << "setup database connection" << dbname << "to" << fileName; |
91 | Werner | 456 | //db.setDatabaseName(":memory:"); |
194 | werner | 457 | if (fileMustExist) |
458 | if (!QFile::exists(fileName)) |
||
459 | throw IException("Error setting up database connection: file " + fileName + " does not exist!"); |
||
91 | Werner | 460 | db.setDatabaseName(fileName); |
461 | if (!db.open()) { |
||
194 | werner | 462 | throw IException(QString("Error in setting up the database connection <%2> connection to file %1.\n").arg(fileName, dbname)); |
91 | Werner | 463 | } |
675 | werner | 464 | if (!fileMustExist) { |
465 | // for output databases: |
||
233 | werner | 466 | // some special commands (pragmas: see also: http://www.sqlite.org/pragma.html) |
467 | db.exec("pragma temp_store(2)"); // temp storage in memory |
||
468 | db.exec("pragma synchronous(1)"); // medium synchronization between memory and disk (faster than "full", more than "none") |
||
469 | } |
||
91 | Werner | 470 | return true; |
471 | } |
||
92 | Werner | 472 | |
99 | Werner | 473 | |
474 | ///////// Path functions |
||
1157 | werner | 475 | void GlobalSettings::printDirectories() const |
679 | werner | 476 | { |
477 | qDebug() << "current File Paths:"; |
||
478 | QHash<QString, QString>::const_iterator i; |
||
479 | for (i=mFilePath.constBegin(); i!=mFilePath.constEnd(); ++i) |
||
480 | qDebug() << i.key() << ": " << i.value(); |
||
481 | } |
||
99 | Werner | 482 | |
189 | iland | 483 | void GlobalSettings::setupDirectories(QDomElement pathNode, const QString &projectFilePath) |
99 | Werner | 484 | { |
485 | mFilePath.clear(); |
||
486 | mFilePath.insert("exe", QCoreApplication::applicationDirPath()); |
||
487 | XmlHelper xml(pathNode); |
||
189 | iland | 488 | QString homePath = xml.value("home", projectFilePath); |
99 | Werner | 489 | mFilePath.insert("home", homePath); |
490 | // make other paths relativ to "home" if given as relative paths |
||
491 | mFilePath.insert("lip", path(xml.value("lip", "lip"), "home")); |
||
492 | mFilePath.insert("database", path(xml.value("database", "database"), "home")); |
||
1157 | werner | 493 | mFilePath.insert("temp", path(xml.value("temp", ""), "home")); |
494 | mFilePath.insert("log", path(xml.value("log", ""), "home")); |
||
495 | mFilePath.insert("script", path(xml.value("script", ""), "home")); |
||
496 | mFilePath.insert("init", path(xml.value("init", ""), "home")); |
||
286 | werner | 497 | mFilePath.insert("output", path(xml.value("output", "output"), "home")); |
99 | Werner | 498 | } |
499 | |||
500 | /** extend the file to a full absoulte path of the given type (temp, home, ...). |
||
185 | werner | 501 | If @p file is already an absolute path, nothing is done. @sa setupDirectories(). |
99 | Werner | 502 | */ |
503 | QString GlobalSettings::path(const QString &fileName, const QString &type) |
||
504 | { |
||
247 | werner | 505 | if (!fileName.isEmpty()) { |
506 | QFileInfo fileinfo(fileName); |
||
507 | if (fileinfo.isAbsolute()) |
||
318 | werner | 508 | return QDir::cleanPath(fileName); |
247 | werner | 509 | } |
99 | Werner | 510 | |
511 | QDir d; |
||
512 | if (mFilePath.contains(type)) |
||
513 | d.setPath(mFilePath.value(type)); |
||
102 | Werner | 514 | else { |
515 | qDebug() << "GlobalSettings::path() called with unknown type" << type; |
||
99 | Werner | 516 | d = QDir::currentPath(); |
102 | Werner | 517 | } |
99 | Werner | 518 | |
318 | werner | 519 | return QDir::cleanPath(d.filePath(fileName)); // let QDir build the correct path |
99 | Werner | 520 | } |
521 | |||
522 | /// returns true if file @p fileName exists. |
||
523 | bool GlobalSettings::fileExists(const QString &fileName, const QString &type) |
||
524 | { |
||
525 | QString name = path(fileName, type); |
||
526 | |||
527 | if (!QFile::exists(name)) { |
||
528 | qDebug() << "Path" << fileName << "(expanded to:)"<< name << "does not exist!"; |
||
529 | return false; |
||
530 | } |
||
531 | return true; |
||
532 | } |
||
533 | |||
102 | Werner | 534 | |
535 | void GlobalSettings::loadProjectFile(const QString &fileName) |
||
536 | { |
||
537 | qDebug() << "Loading Project file" << fileName; |
||
538 | if (!QFile::exists(fileName)) |
||
539 | throw IException(QString("The project file %1 does not exist!").arg(fileName)); |
||
540 | mXml.loadFromFile(fileName); |
||
191 | werner | 541 | setupDirectories(mXml.node("system.path"),QFileInfo(fileName).path()); |
102 | Werner | 542 | |
543 | } |
||
544 |