Subversion Repositories public iLand

Rev

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