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