Subversion Repositories public iLand

Rev

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