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
 
142 Werner 20
#include <QtCore>
780 werner 21
#include <QtWidgets>
145 Werner 22
#include <QtXml>
879 werner 23
#include <QQuickView>
24
#include <QQmlEngine>
25
#include <QQmlContext>
3 Werner 26
 
452 werner 27
#include <signal.h>
28
 
216 werner 29
#include "global.h"
30
#include "mainwindow.h"
31
#include "ui_mainwindow.h"
323 werner 32
#include "aboutdialog.h"
216 werner 33
 
104 Werner 34
#include "model.h"
106 Werner 35
#include "standloader.h"
105 Werner 36
#include "stampcontainer.h"
189 iland 37
#include "resourceunit.h"
105 Werner 38
#include "speciesset.h"
85 Werner 39
#include "tree.h"
493 werner 40
#include "species.h"
1179 werner 41
#include "seeddispersal.h"
1117 werner 42
#include "saplings.h"
1078 werner 43
#include "climate.h"
3 Werner 44
 
105 Werner 45
#include "exception.h"
808 werner 46
#include "helper.h"
877 werner 47
#include "colors.h"
808 werner 48
#include "debugtimer.h"
49
#include "statdata.h"
105 Werner 50
 
39 Werner 51
#include "paintarea.h"
52
 
142 Werner 53
#include "expression.h"
54
#include "expressionwrapper.h"
216 werner 55
#include "management.h"
229 werner 56
#include "outputmanager.h"
104 Werner 57
 
157 werner 58
#include "tests.h"
596 werner 59
#include "mapgrid.h"
647 werner 60
#include "layeredgrid.h"
1009 werner 61
#include "dem.h"
202 werner 62
 
896 werner 63
#include "forestmanagementengine.h" // ABE
64
 
9 Werner 65
// global settings
1157 werner 66
static QDomDocument xmldoc;
67
static QDomNode xmlparams;
20 Werner 68
 
698 werner 69
/** @class MainWindow
70
   @ingroup GUI
71
   The main window of the iLand viewer.
72
 
73
 
74
  */
75
 
20 Werner 76
 
40 Werner 77
double distance(const QPointF &a, const QPointF &b)
78
{
79
    return sqrt( (a.x()-b.x())*(a.x()-b.x()) + (a.y()-b.y())*(a.y()-b.y()) );
80
}
39 Werner 81
 
30 Werner 82
 
6 Werner 83
double nrandom(const float& p1, const float& p2)
84
{
85
    return p1 + (p2-p1)*(rand()/float(RAND_MAX));
86
}
87
 
1157 werner 88
static bool showDebugMessages=true;
89
static QStringList bufferedMessages;
90
static bool doBufferMessages = false;
91
static bool doLogToWindow = false;
360 werner 92
void logToWindow(bool mode)
93
{
94
   doLogToWindow = mode;
95
}
96
class LogToWindow
97
{
98
public:
99
    LogToWindow() { logToWindow(true);}
100
    ~LogToWindow() { logToWindow(false);}
101
};
267 werner 102
 
359 werner 103
 
1157 werner 104
static QMutex qdebug_mutex;
611 werner 105
void dumpMessages();
780 werner 106
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
7 Werner 107
 {
138 Werner 108
 
780 werner 109
    Q_UNUSED(context);
374 werner 110
    QMutexLocker m(&qdebug_mutex);
780 werner 111
     //QByteArray localMsg = msg.toLocal8Bit();
138 Werner 112
    switch (type) {
1053 werner 113
    case QtDebugMsg:
194 werner 114
        if (showDebugMessages) {
884 werner 115
            if (qstrcmp(context.category, "default")!=0)
116
                bufferedMessages.append(QString("%1: %2").arg(context.category).arg(msg));
117
            else
118
                bufferedMessages.append(QString(msg));
194 werner 119
        }
120
 
1053 werner 121
        break;
122
    case QtWarningMsg:
1054 werner 123
    //case QtInfoMsg:
1053 werner 124
        //MainWindow::logSpace()->appendPlainText(QString("WARNING: %1").arg(msg));
125
        //MainWindow::logSpace()->ensureCursorVisible();
126
        bufferedMessages.append(msg);
127
        break;
128
    case QtCriticalMsg: {
780 werner 129
        QByteArray localMsg = msg.toLocal8Bit();
1053 werner 130
        fprintf(stderr, "Critical: %s\n", localMsg.constData());
131
        break; }
132
    case QtFatalMsg: {
780 werner 133
        QByteArray localMsg = msg.toLocal8Bit();
1053 werner 134
        fprintf(stderr, "Fatal: %s\n", localMsg.constData());
135
        bufferedMessages.append(msg);
265 werner 136
 
1053 werner 137
        QString file_name = GlobalSettings::instance()->path("fatallog.txt","log");
138
        Helper::msg(QString("Fatal message encountered:\n%1\nFatal-Log-File: %2").arg(msg, file_name));
139
        dumpMessages();
140
        Helper::saveToTextFile(file_name, MainWindow::logSpace()->toPlainText() + bufferedMessages.join("\n"));
141
    }
142
    }
362 werner 143
     if (!doBufferMessages || bufferedMessages.count()>5000)
267 werner 144
             dumpMessages();
145
 }
7 Werner 146
 
1157 werner 147
static QMutex dump_message_mutex;
611 werner 148
void dumpMessages()
149
{
150
    QMutexLocker m(&dump_message_mutex); // serialize access
151
    // 2011-03-08: encountered "strange" crashes
152
    // when a warning within Qt lead to a infinite loop/deadlock (also caused by mutex locking)
153
    // now we prevent this by installing temporarily a 0-handler
780 werner 154
    qInstallMessageHandler(0);
611 werner 155
 
156
    if (MainWindow::logStream() && !doLogToWindow) {
157
        foreach(const QString &s, bufferedMessages)
158
            *MainWindow::logStream() << s << endl;
734 werner 159
        MainWindow::logStream()->flush();
611 werner 160
 
161
    } else {
162
        foreach(const QString &s, bufferedMessages)
163
            MainWindow::logSpace()->appendPlainText(s);
164
 
165
        // it does *not* work to just MainWindow::logSpace()->textCursor().movePosition()!
166
        // you have to "setTextCursor()".
167
        QTextCursor cursor = MainWindow::logSpace()->textCursor();
168
        cursor.movePosition(QTextCursor::End);
169
        MainWindow::logSpace()->setTextCursor(cursor);
170
        MainWindow::logSpace()->ensureCursorVisible();
171
    }
172
 
173
    bufferedMessages.clear();
780 werner 174
    qInstallMessageHandler(myMessageOutput);
611 werner 175
}
176
 
177
 
452 werner 178
// handle signal...
179
// source: http://cplusplus.com/forum/unices/13455/
180
void handle_signal( int signo ) {
508 werner 181
    Helper::msg(QString("Received Signal:\n%1").arg(signo));
452 werner 182
    qDebug() << "*** Received signal "<< signo << "****";
183
    dumpMessages();
184
 
185
}
186
 
267 werner 187
void MainWindow::bufferedLog(bool bufferLog)
188
{
359 werner 189
    doBufferMessages = bufferLog;
362 werner 190
    if (bufferLog==false)
191
        dumpMessages();
267 werner 192
}
40 Werner 193
 
360 werner 194
void MainWindow::setupFileLogging(const bool do_start)
195
{
196
    if (mLogStream) {
197
        if (mLogStream->device())
198
            delete mLogStream->device();
199
        delete mLogStream;
200
        mLogStream = NULL;
201
    }
202
    if (!do_start)
203
        return;
204
 
205
    if (GlobalSettings::instance()->settings().value("system.logging.logTarget", "console") == "file") {
206
        QString fname = GlobalSettings::instance()->settings().value("system.logging.logFile", "logfile.txt");
207
        QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
208
        fname.replace("$date$", timestamp);
362 werner 209
        fname = GlobalSettings::instance()->path(fname, "log");
210
        QFile *file = new QFile(fname);
360 werner 211
 
212
        if (!file->open(QIODevice::WriteOnly)) {
213
            qDebug() << "cannot open logfile" << fname;
214
        } else {
215
            qDebug() << "Log output is redirected to logfile" << fname;
216
            mLogStream = new QTextStream(file);
217
        }
218
    }
219
 
220
}
221
 
222
 
7 Werner 223
QPlainTextEdit *MainWindow::mLogSpace=NULL;
359 werner 224
QTextStream *MainWindow::mLogStream=NULL;
7 Werner 225
 
226
 
3 Werner 227
MainWindow::MainWindow(QWidget *parent)
228
    : QMainWindow(parent), ui(new Ui::MainWindowClass)
229
{
230
    ui->setupUi(this);
127 Werner 231
 
3 Werner 232
    connect( ui->PaintWidget, SIGNAL(needsPainting(QPainter&)),
233
             this, SLOT(repaintArea(QPainter&)) );
6 Werner 234
    connect (ui->PaintWidget, SIGNAL(mouseClick(QPoint)),
235
             this, SLOT(mouseClick(const QPoint&)));
113 Werner 236
    connect(ui->PaintWidget, SIGNAL(mouseDrag(QPoint,QPoint,Qt::MouseButton)),
237
            this, SLOT(mouseDrag(const QPoint&, const QPoint &, const Qt::MouseButton)));
49 Werner 238
    connect(ui->PaintWidget, SIGNAL(mouseMove(QPoint)),
239
            this, SLOT(mouseMove(const QPoint&)));
113 Werner 240
    connect(ui->PaintWidget, SIGNAL(mouseWheel(QPoint, int)),
241
            this, SLOT(mouseWheel(const QPoint&, int)));
40 Werner 242
 
129 Werner 243
    // dock windows
244
    ui->menuView->addAction( ui->dockEditor->toggleViewAction() );
245
    ui->menuView->addAction( ui->dockLogviewer->toggleViewAction() );
246
    ui->menuView->addAction( ui->dockWidget->toggleViewAction() );
150 iland 247
    ui->menuView->addAction( ui->dockModelDrill->toggleViewAction() );
113 Werner 248
 
67 Werner 249
    ui->pbResults->setMenu(ui->menuOutput_menu);
250
 
7 Werner 251
    mLogSpace = ui->logOutput;
816 werner 252
    mLogSpace->setMaximumBlockCount(1000000); // set a maximum for the in-GUI size of messages. // removed in Qt5 (because it works ;) )
780 werner 253
    qInstallMessageHandler(myMessageOutput);
452 werner 254
    // install signal handler
255
    signal( SIGSEGV, handle_signal );
127 Werner 256
 
716 werner 257
    readSettings();
258
 
767 werner 259
    // create global scripting context
260
    GlobalSettings::instance()->resetScriptEngine();
261
 
320 werner 262
    // load xml file: use either a command-line argument (if present), or load the content of a small text file....
119 Werner 263
    QString argText = QApplication::arguments().last();
320 werner 264
    if (QApplication::arguments().count()>1 && !argText.isEmpty()) {
119 Werner 265
        ui->initFileName->setText(argText);
320 werner 266
    } else {
716 werner 267
        QString lastXml = QSettings().value("project/lastxmlfile").toString();
268
        //QString lastXml = Helper::loadTextFile( QCoreApplication::applicationDirPath()+ "/lastxmlfile.txt" );
320 werner 269
        if (!lastXml.isEmpty() && QFile::exists(lastXml))
270
            ui->initFileName->setText(lastXml);
271
    }
19 Werner 272
    QString xmlFile = Helper::loadTextFile(ui->initFileName->text());
3 Werner 273
 
65 Werner 274
    if (!xmlFile.isEmpty()) {
275
        ui->iniEdit->setPlainText(xmlFile);
189 iland 276
        QString errMsg;
277
        int errLine, errCol;
278
        if (!xmldoc.setContent(xmlFile, &errMsg, &errLine, &errCol)) {
279
            QMessageBox::information(this, "title text", QString("Cannot set content of XML file %1. \nat line %2 col %3: %4 ")
280
                                     .arg(ui->initFileName->text()).arg(errLine).arg(errCol).arg(errMsg));
1053 werner 281
            //return;
65 Werner 282
        }
19 Werner 283
    }
284
 
20 Werner 285
    on_actionEdit_XML_settings_triggered();
19 Werner 286
 
118 Werner 287
    qDebug() << "threadcount: " << QThread::idealThreadCount();
151 iland 288
 
289
    // load window settings
290
    QString fileName = QDir::current().filePath("gui.txt");
291
    if (QFile::exists(fileName)) {
292
 
293
        QByteArray state = Helper::loadFile(fileName);
294
        restoreState(state);
295
    }
129 Werner 296
    checkModelState();
220 werner 297
    ui->statusBar->addPermanentWidget(ui->modelRunProgress);
221 werner 298
    ui->modelRunProgress->setValue(0);
493 werner 299
    mStatusLabel = new QLabel(this);
300
    labelMessage("no model created.");
301
    ui->statusBar->addWidget(mStatusLabel);
222 werner 302
    // remote control of model
303
    connect(&mRemoteControl, SIGNAL(year(int)),this,SLOT(yearSimulated(int)));
304
    connect(&mRemoteControl, SIGNAL(finished(QString)), this, SLOT(modelFinished(QString)));
776 werner 305
    connect(&mRemoteControl, SIGNAL(stateChanged()), this, SLOT(checkModelState()));
503 werner 306
 
307
    // log levels
308
    ui->actionDebug->setProperty("logLevel", QVariant(0));
309
    ui->actionInfo->setProperty("logLevel", QVariant(1));
310
    ui->actionWarning->setProperty("logLevel", QVariant(2));
311
    ui->actionError->setProperty("logLevel", QVariant(3));
312
 
514 werner 313
    // species filter
314
    connect( ui->speciesFilterBox, SIGNAL(currentIndexChanged(int)), SLOT(repaint()));
643 werner 315
    connect( ui->paintGridBox, SIGNAL(currentIndexChanged(int)), SLOT(repaint()));
316
    updatePaintGridList();
514 werner 317
 
590 werner 318
    // model controller
319
    mRemoteControl.setMainWindow( this );
320
    mRemoteControl.connectSignals();
321
    GlobalSettings::instance()->setModelController( &mRemoteControl );
322
 
657 werner 323
    // automatic run
324
    if (QApplication::arguments().contains("run")) {
325
        QTimer::singleShot(3000, this, SLOT(automaticRun()));
326
    }
327
 
965 werner 328
    // to silence some warnings during startup - maybe not required (anymore):
329
    qRegisterMetaType<QTextBlock>("QTextBlock");
330
    qRegisterMetaType<QTextCursor>("QTextCursor");
1046 werner 331
 
332
    ui->iniEdit->setVisible(false);
333
    ui->editStack->setTabEnabled(3,false); // the "other" tab
879 werner 334
    // qml setup
335
    QQuickView *view = new QQuickView();
336
    mRuler = view;
337
    QWidget *container = QWidget::createWindowContainer(view, this);
880 werner 338
    mRulerColors = new Colors();
339
    view->engine()->rootContext()->setContextProperty("rulercolors", mRulerColors);
340
    view->setResizeMode(QQuickView::SizeRootObjectToView);
1042 werner 341
    ui->pbReloadQml->setVisible(false); // enable for debug...
342
    //view->setSource(QUrl::fromLocalFile("E:/dev/iland_port_qt5_64bit/src/iland/qml/ruler.qml"));
343
    view->setSource(QUrl("qrc:/qml/ruler.qml"));
879 werner 344
    //view->show();
345
    ui->qmlRulerLayout->addWidget(container);
1046 werner 346
    ui->qmlRulerLayout->addWidget(container);
880 werner 347
//    QDir d(":/qml");
348
//    qDebug() << d.entryList();
879 werner 349
 
3 Werner 350
}
351
 
265 werner 352
 
3 Werner 353
MainWindow::~MainWindow()
354
{
901 werner 355
    mRemoteControl.destroy(); // delete model and free resources.
3 Werner 356
    delete ui;
357
}
657 werner 358
 
359
void MainWindow::batchLog(const QString s)
360
{
361
    QFile outfile(QCoreApplication::applicationDirPath()+ "/batchlog.txt");
362
    if (outfile.open(QIODevice::Append | QIODevice::Text)) {
363
        QTextStream str(&outfile);
364
        str << s << endl;
365
    }
366
}
367
 
368
/// automatically start a simulation...
369
void MainWindow::automaticRun()
370
{
371
    // start a simulation
372
    setWindowTitle("iLand viewer --- batch mode");
373
    batchLog("*** iland batch mode ***");
374
    batchLog(QString("%1 Loading project %2").arg(QDateTime::currentDateTime().toString(Qt::ISODate),
375
           ui->initFileName->text()));
376
    batchLog(QString("%1 Loading the model...").arg(QDateTime::currentDateTime().toString(Qt::ISODate)));
377
    setupModel();
378
 
379
    int count = QCoreApplication::arguments()[QCoreApplication::arguments().count()-2].toInt();
380
    if (count==0) {
381
        qDebug() << "invalid number of years....";
382
        return;
383
    }
384
    ui->modelRunProgress->setMaximum(count-1);
385
    batchLog(QString("%1 Running the model (%2 years)...").arg(QDateTime::currentDateTime().toString(Qt::ISODate)).arg(count));
658 werner 386
    // note the "+1": this is similar to the normal way of starting
387
    // "1" means in Globals.year that we are in the 1st year.
388
    // the simulation stops when reaching the count+1 year.
389
    mRemoteControl.run(count + 1);
657 werner 390
 
661 werner 391
    // see the finsished() slot
657 werner 392
}
393
 
200 werner 394
// simply command an update of the painting area
395
void MainWindow::repaint()
396
{
397
    ui->PaintWidget->update();
655 werner 398
    QCoreApplication::processEvents();
200 werner 399
}
3 Werner 400
 
129 Werner 401
// control GUI actions
402
void MainWindow::checkModelState()
403
{
776 werner 404
    ui->actionModelCreate->setEnabled(mRemoteControl.canCreate()&& !mRemoteControl.isRunning());
405
    ui->actionModelDestroy->setEnabled(mRemoteControl.canDestroy() && !mRemoteControl.isRunning());
964 werner 406
    ui->actionModelRun->setEnabled(mRemoteControl.canRun() && !mRemoteControl.isPaused() && !mRemoteControl.isRunning());
776 werner 407
    ui->actionRun_one_year->setEnabled(mRemoteControl.canRun() && !mRemoteControl.isPaused()&& !mRemoteControl.isRunning());
964 werner 408
    ui->actionReload->setEnabled(mRemoteControl.canDestroy() && !mRemoteControl.isRunning());
225 werner 409
    ui->actionStop->setEnabled(mRemoteControl.isRunning());
410
    ui->actionPause->setEnabled(mRemoteControl.isRunning());
776 werner 411
    ui->actionPause->setText(mRemoteControl.isPaused()?"Continue":"Pause");
265 werner 412
    dumpMessages();
129 Werner 413
}
105 Werner 414
 
415
 
3 Werner 416
 
417
 
105 Werner 418
void MainWindow::readwriteCycle()
419
{
420
 
128 Werner 421
    if (!mRemoteControl.canRun())
105 Werner 422
        return;
128 Werner 423
 
403 werner 424
    Model *model = mRemoteControl.model();
425
    model->onlyApplyLightPattern();
105 Werner 426
}
427
 
72 Werner 428
 
429
 
430
 
67 Werner 431
QString MainWindow::dumpTreelist()
432
{
128 Werner 433
    if (!mRemoteControl.isRunning())
105 Werner 434
        return "";
128 Werner 435
 
436
    Model *model = mRemoteControl.model();
144 Werner 437
 
438
    AllTreeIterator at(model);
439
    DebugList treelist;
440
    QString line;
67 Werner 441
    QStringList result;
144 Werner 442
    result << "id;species;dbh;height;x;y;RU#;LRI;mWoody;mRoot;mFoliage;LA";
443
    while (Tree *tree = at.next()) {
444
        treelist.clear();
445
        tree->dumpList(treelist);
446
        line = "";
447
        foreach(QVariant value, treelist)
448
            line+=value.toString() + ";";
449
        result << line;
67 Werner 450
    }
451
    QString resStr = result.join("\n");
452
    return resStr;
453
}
66 Werner 454
 
643 werner 455
void MainWindow::updatePaintGridList()
456
{
457
    ui->paintGridBox->clear();
458
    ui->paintGridBox->addItem("<none>", "");
1047 werner 459
    QMap<QString, PaintObject>::const_iterator i = mPaintList.begin();
643 werner 460
    while (i!=mPaintList.constEnd()) {
461
        ui->paintGridBox->addItem(i.key(),i.key());
462
        ++i;
463
    }
464
}
67 Werner 465
 
647 werner 466
void MainWindow::addLayers(const LayeredGridBase *layer, const QString &name)
467
{
1014 werner 468
    const QVector<LayeredGridBase::LayerElement> &names = const_cast<LayeredGridBase*>(layer)->names();
647 werner 469
    int layer_id = 0;
1062 werner 470
    QString current_layer = mPaintNext.name;
877 werner 471
    foreach (const LayeredGridBase::LayerElement &layername, names) {
472
        QString comb_name = QString("%1 - %2").arg(name, layername.name);
647 werner 473
        PaintObject po;
474
        po.what = PaintObject::PaintLayers;
877 werner 475
        po.view_type = layername.view_type;
647 werner 476
        po.layered = layer;
477
        po.layer_id = layer_id++;
899 werner 478
        po.name = layername.name;
647 werner 479
        po.auto_range = true;
480
        mPaintList[comb_name] = po;
1062 werner 481
        if (current_layer == po.name)
482
            mPaintNext.what = PaintObject::PaintHeightGrid;
647 werner 483
    }
484
    updatePaintGridList();
485
}
486
 
893 werner 487
void MainWindow::removeLayers(const LayeredGridBase *layer)
488
{
1047 werner 489
    QMap<QString, PaintObject>::iterator it=mPaintList.begin();
893 werner 490
    while(it!=mPaintList.end())
491
        if (it->layered == layer)
492
            it = mPaintList.erase(it);
493
        else
494
            ++it;
495
    if (mPaintNext.layered == layer)
496
        mPaintNext.what = PaintObject::PaintHeightGrid;
497
}
647 werner 498
 
893 werner 499
 
643 werner 500
void MainWindow::paintGrid(MapGrid *map_grid, const QString &name,
501
               const GridViewType view_type,
502
               double min_val, double max_val)
503
{
504
    if (map_grid==0 && !name.isEmpty()) {
505
        // remove the grid from the list
506
        mPaintList.remove(name);
507
        updatePaintGridList();
508
        return;
509
    }
510
    mPaintNext.what=PaintObject::PaintMapGrid;
511
    mPaintNext.min_value=min_val; mPaintNext.max_value=max_val;
512
    mPaintNext.map_grid = map_grid; mPaintNext.view_type = view_type;
513
    if (!name.isEmpty()) {
514
        updatePaintGridList();
515
        mPaintList[name] = mPaintNext;
516
    }
732 werner 517
    ui->visOtherGrid->setChecked(true);
643 werner 518
    repaint();
519
}
520
 
521
void MainWindow::paintGrid(const FloatGrid *grid, const QString &name,
522
                           const GridViewType view_type,
523
                           double min_val, double max_val)
524
{
525
    if (grid==0 && !name.isEmpty()) {
526
        // remove the grid from the list
527
        mPaintList.remove(name);
528
        updatePaintGridList();
529
        return;
530
    }
531
    mPaintNext.what=PaintObject::PaintFloatGrid;
532
    mPaintNext.min_value=min_val;
533
    mPaintNext.max_value=max_val;
534
    mPaintNext.float_grid = grid;
535
    mPaintNext.view_type = view_type;
881 werner 536
    mPaintNext.name = name;
643 werner 537
    if (!name.isEmpty()) {
538
        mPaintList[name] = mPaintNext;
539
        updatePaintGridList();
540
    }
732 werner 541
    ui->visOtherGrid->setChecked(true);
643 werner 542
    repaint();
543
}
544
 
20 Werner 545
void MainWindow::paintFON(QPainter &painter, QRect rect)
3 Werner 546
{
105 Werner 547
    DebugTimer drawtimer("painting");
274 werner 548
    drawtimer.setSilent();
121 Werner 549
 
128 Werner 550
    if (!mRemoteControl.canRun())
105 Werner 551
        return;
128 Werner 552
    Model *model = mRemoteControl.model();
107 Werner 553
 
128 Werner 554
    FloatGrid *grid = model->grid();
151 iland 555
    HeightGrid *domGrid = model->heightGrid();
3 Werner 556
    // do the actual painting
127 Werner 557
    if (!grid)
3 Werner 558
        return;
48 Werner 559
    bool auto_scale_color = ui->visAutoScale->isChecked();
560
    bool show_fon = ui->visFon->isChecked();
561
    bool show_dom = ui->visDomGrid->isChecked();
291 werner 562
    bool show_trees = ui->visImpact->isChecked();
493 werner 563
    bool species_color = ui->visSpeciesColor->isChecked();
291 werner 564
    bool show_ru = ui->visResourceUnits->isChecked();
453 werner 565
    bool show_regeneration = ui->visRegeneration->isChecked();
1179 werner 566
    bool show_seedmaps = ui->visSeeds->isChecked();
732 werner 567
    bool other_grid = ui->visOtherGrid->isChecked();
48 Werner 568
 
732 werner 569
    if (other_grid) {
733 werner 570
        // return; // TODO TEST
732 werner 571
        if (ui->paintGridBox->currentIndex()>-1) {
572
            QString name = ui->paintGridBox->itemData(ui->paintGridBox->currentIndex()).toString();
573
            if (!name.isEmpty())
574
                mPaintNext = mPaintList[name];
575
        }
643 werner 576
 
732 werner 577
        if (mPaintNext.what != PaintObject::PaintNothing) {
881 werner 578
            if (mPaintNext.what == PaintObject::PaintMapGrid) {
579
                mRulerColors->setCaption(mPaintNext.name);
732 werner 580
                paintMapGrid(painter, mPaintNext.map_grid, 0, mPaintNext.view_type, mPaintNext.min_value, mPaintNext.max_value);
881 werner 581
            }
596 werner 582
 
881 werner 583
            if (mPaintNext.what == PaintObject::PaintFloatGrid) {
584
                mRulerColors->setCaption(mPaintNext.name);
732 werner 585
                paintMapGrid(painter, 0, mPaintNext.float_grid, mPaintNext.view_type, mPaintNext.min_value, mPaintNext.max_value);
881 werner 586
            }
642 werner 587
 
732 werner 588
            if (mPaintNext.what == PaintObject::PaintLayers)
589
                paintGrid(painter, mPaintNext);
647 werner 590
 
732 werner 591
            return;
592
        }
596 werner 593
    }
594
 
647 werner 595
 
596
    // clear background
597
    painter.fillRect(ui->PaintWidget->rect(), Qt::white);
598
    // draw rectangle around the grid
599
    QRectF r = grid->metricRect();
600
    QRect rs = vp.toScreen(r);
1064 werner 601
    painter.setPen(Qt::darkGray);
647 werner 602
    painter.drawRect(rs);
822 werner 603
    //qDebug() << rs;
647 werner 604
 
605
    // what to paint??
606
 
48 Werner 607
    float maxval=1.f; // default maximum
1041 werner 608
    float minval=0.f;
48 Werner 609
    if (!auto_scale_color)
127 Werner 610
        maxval =grid->max();
3 Werner 611
    if (maxval==0.)
612
        return;
514 werner 613
    QString species;
614
    if (ui->speciesFilterBox->currentIndex()>-1)
615
        species = ui->speciesFilterBox->itemData(ui->speciesFilterBox->currentIndex()).toString();
616
 
3 Werner 617
    int ix,iy;
618
    QColor fill_color;
619
    float value;
70 Werner 620
 
291 werner 621
    if (show_fon ) {
622
 
105 Werner 623
        // start from each pixel and query value in grid for the pixel
880 werner 624
        mRulerColors->setCaption("Light Influence Field", "value of the LIF at 2m resolution.");
1064 werner 625
        mRulerColors->setPalette(GridViewRainbowReverse,0., maxval); // ruler
1041 werner 626
        if (!mRulerColors->autoScale()) {
1157 werner 627
            maxval = static_cast<float>( mRulerColors->maxValue());
628
            minval = static_cast<float>( mRulerColors->minValue() );
1041 werner 629
        }
105 Werner 630
        int x,y;
631
        int sizex = rect.width();
632
        int sizey = rect.height();
633
        QPointF world;
634
        QRgb col;
635
        QImage &img = ui->PaintWidget->drawImage();
636
        for (x=0;x<sizex;x++)
637
            for (y=0;y<sizey;y++) {
643 werner 638
                world = vp.toWorld(QPoint(x,y));
639
                if (grid->coordValid(world)) {
640
                    value = grid->valueAt(world);
1064 werner 641
                    col = Colors::colorFromValue(value, minval, maxval,true).rgb();
643 werner 642
                    img.setPixel(x,y,col);
643
                }
291 werner 644
            }
70 Werner 645
 
291 werner 646
    }
41 Werner 647
 
1179 werner 648
    if (show_seedmaps) {
649
        if (species.isEmpty()) {
650
            qDebug() << "Please select a species!";
651
            return;
652
        }
653
        int x,y;
654
        mRulerColors->setCaption("Seed availability", QString("seed availability of species %1").arg(species));
655
        mRulerColors->setPalette(GridViewRainbow,0., 1.); // ruler
656
        int sizex = rect.width();
657
        int sizey = rect.height();
658
        QPointF world;
659
        QRgb col;
660
        QImage &img = ui->PaintWidget->drawImage();
661
        const Grid<float> &grid = GlobalSettings::instance()->model()->speciesSet()->species(species)->seedDispersal()->seedMap();
662
        QRgb gray_bg = QColor(100,100,100).rgb();
663
 
664
        for (x=0;x<sizex;x++)
665
            for (y=0;y<sizey;y++) {
666
                world = vp.toWorld(QPoint(x,y));
667
                if (grid.coordValid(world)) {
668
                    value = grid.constValueAt(world);
669
                    col = value>0.f ? Colors::colorFromValue(value, 0., 1., false).rgb() : gray_bg;
670
                    img.setPixel(x,y,col);
671
                }
672
            }
673
 
674
    }
675
 
453 werner 676
    if (show_regeneration ) {
677
 
678
        if (mRegenerationGrid.isEmpty())
679
            mRegenerationGrid.setup(*model->grid()); // copy
1117 werner 680
        if (!GlobalSettings::instance()->model()->saplings())
681
            return;
453 werner 682
        static int last_year=0;
514 werner 683
        static QString last_species="";
1178 werner 684
        static bool last_regen_mode=false;
685
        if (last_year!=GlobalSettings::instance()->currentYear() || species!=last_species || ui->visRegenNew->isChecked()!=last_regen_mode) {
453 werner 686
            last_year=GlobalSettings::instance()->currentYear();
514 werner 687
            last_species=species;
1178 werner 688
            bool draw_established = ui->visRegenNew->isChecked();
689
            last_regen_mode = draw_established;
453 werner 690
            // fill grid...
691
            DebugTimer t("create regeneration map...");
692
            mRegenerationGrid.wipe(0.f);
1117 werner 693
            if (species.isEmpty()) {
694
                // hmax of all species
1159 werner 695
                for (float *rg=mRegenerationGrid.begin();rg!=mRegenerationGrid.end(); ++rg) {
696
                    SaplingCell *sc=GlobalSettings::instance()->model()->saplings()->cell(mRegenerationGrid.indexOf(rg));
1178 werner 697
                    if (sc) {
698
                        if (draw_established)
699
                            *rg = sc->has_new_saplings() ? 1.f : 0.f;
700
                        else
701
                            *rg = sc->max_height();
702
                    }
703
 
453 werner 704
                }
1117 werner 705
            } else {
706
                // filter a specific species
707
                int sidx = GlobalSettings::instance()->model()->speciesSet()->species(species)->index();
1159 werner 708
                for (float *rg=mRegenerationGrid.begin(); rg!=mRegenerationGrid.end(); ++rg) {
709
                    SaplingCell *sc=GlobalSettings::instance()->model()->saplings()->cell(mRegenerationGrid.indexOf(rg));
710
                    if (sc) {
711
                        SaplingTree *st=sc->sapling(sidx);
1178 werner 712
                        if (st) {
713
                            if (draw_established)
714
                                *rg = st->is_occupied() && st->age<2 ? 1.f : 0.f;
715
                            else
716
                                *rg = st ? st->height : 0.f;
717
                        }
1159 werner 718
                    }
1117 werner 719
                }
453 werner 720
            }
721
        }
722
        // start from each pixel and query value in grid for the pixel
723
        int x,y;
880 werner 724
        mRulerColors->setCaption("Regeneration Layer", "max. tree height of regeneration layer (blue=0m, red=4m)");
725
        mRulerColors->setPalette(GridViewRainbow,0., 4.); // ruler
453 werner 726
        int sizex = rect.width();
727
        int sizey = rect.height();
728
        QPointF world;
729
        QRgb col;
730
        QImage &img = ui->PaintWidget->drawImage();
1064 werner 731
 
453 werner 732
        for (x=0;x<sizex;x++)
733
            for (y=0;y<sizey;y++) {
643 werner 734
                world = vp.toWorld(QPoint(x,y));
735
                if (mRegenerationGrid.coordValid(world)) {
736
                    value = mRegenerationGrid.valueAt(world);
877 werner 737
                    col = Colors::colorFromValue(value, 0., 4., false).rgb(); // 0..4m
643 werner 738
                    img.setPixel(x,y,col);
739
                }
453 werner 740
            }
741
    }
742
 
291 werner 743
    if (show_dom) {
744
        // paint the lower-res-grid;
1053 werner 745
        float max_val = 50.f;
746
        float min_val = 0.f;
539 werner 747
        if (auto_scale_color) {
748
            max_val = 0.;
749
            for (HeightGridValue *v = domGrid->begin(); v!=domGrid->end(); ++v)
750
                max_val = qMax(max_val, v->height);
751
        }
880 werner 752
        mRulerColors->setCaption("Dominant height (m)", "dominant tree height on 10m pixel.");
753
        mRulerColors->setPalette(GridViewRainbow,0., max_val); // ruler
1041 werner 754
        if (!mRulerColors->autoScale()) {
1157 werner 755
            min_val = static_cast<float>( mRulerColors->minValue() );
756
            max_val = static_cast<float>( mRulerColors->maxValue() );
1041 werner 757
        }
291 werner 758
        for (iy=0;iy<domGrid->sizeY();iy++) {
759
            for (ix=0;ix<domGrid->sizeX();ix++) {
760
                QPoint p(ix,iy);
714 werner 761
                const HeightGridValue &hgv = domGrid->valueAtIndex(p);
762
                if (hgv.isValid()) {
538 werner 763
                    value = domGrid->valueAtIndex(p).height;
764
                    QRect r = vp.toScreen(domGrid->cellRect(p));
877 werner 765
                    fill_color = Colors::colorFromValue(value, 0., max_val); // 0..50m
538 werner 766
                    painter.fillRect(r, fill_color);
767
                }
714 werner 768
                // areas "outside" are drawn as gray.
718 werner 769
                if (hgv.isForestOutside()) {
714 werner 770
                    QRect r = vp.toScreen(domGrid->cellRect(p));
720 werner 771
                    if (hgv.isRadiating())
1040 werner 772
                        painter.fillRect(r, Qt::gray);
720 werner 773
                    else
1041 werner 774
                        painter.fillRect(r, QColor(240,240,240));
720 werner 775
 
714 werner 776
                }
291 werner 777
            }
778
        }
40 Werner 779
 
291 werner 780
    } // if (show_dom)
105 Werner 781
 
291 werner 782
    if (show_ru){
783
        QString ru_expr = ui->lTreeExpr->text();
784
        if (ru_expr.isEmpty())
785
            ru_expr = "id";
786
        RUWrapper ru_wrapper;
105 Werner 787
 
291 werner 788
        Expression ru_value(ru_expr, &ru_wrapper);
789
        ru_value.setCatchExceptions(); // silent catching...
1040 werner 790
 
1041 werner 791
        species_color = ui->visRUSpeciesColor->isChecked();
1040 werner 792
        const Species *drawspecies=0;
793
        GridViewType view_type = GridViewRainbow;
794
        if (species_color) {
795
            drawspecies = model->speciesSet()->species(species);
796
            view_type = GridViewGreens;
797
        }
798
 
558 werner 799
        double min_value = 0.;
800
        double max_value = 1.; // defaults
801
        double value;
1041 werner 802
        if (!mRulerColors->autoScale()) {
803
            max_value = mRulerColors->maxValue();
804
            min_value = mRulerColors->minValue();
805
 
806
        } else if (auto_scale_color) {
558 werner 807
            min_value = 9999999999999999999.;
808
            max_value = -999999999999999999.;
809
            foreach (const ResourceUnit *ru, model->ruList()) {
1180 werner 810
                if (species_color && drawspecies) {
1040 werner 811
                    value = ru->constResourceUnitSpecies(drawspecies)->constStatistics().basalArea();
812
                } else {
813
                    ru_wrapper.setResourceUnit(ru);
814
                    value = ru_value.execute();
815
                }
558 werner 816
                min_value = qMin(min_value, value);
817
                max_value = qMax(max_value, value);
818
            }
819
            qDebug() << "scale colors: min" << min_value << "max:" << max_value;
820
        }
40 Werner 821
 
1040 werner 822
        if (species_color) {
1180 werner 823
            if (drawspecies) {
824
                drawspecies = model->speciesSet()->species(species);
825
                mRulerColors->setCaption("Species share", QString("Species: '%1'").arg(species));
826
                mRulerColors->setPalette(GridViewGreens, static_cast<float>(min_value), static_cast<float>(max_value)); // ruler
827
            } else {
828
                mRulerColors->setCaption("Dominant species on resource unit", "The color indicates the species with the biggest share of basal area. \nDashed fill, if the basal area of the max-species is <50%.");
829
                QList<const Species*> specieslist=mRemoteControl.availableSpecies();
830
                QStringList colors; QStringList speciesnames;
831
                for (int i=0; i<specieslist.count();++i) {
832
                    colors.append(specieslist[i]->displayColor().name());
833
                    speciesnames.append(specieslist[i]->name());
834
                }
835
                mRulerColors->setFactorColors(colors);
836
                mRulerColors->setFactorLabels(speciesnames);
837
                mRulerColors->setPalette(GridViewCustom, 0., 1.);
838
            }
1040 werner 839
        } else {
840
            mRulerColors->setCaption("Resource Units", QString("Result of expression: '%1'").arg(ru_expr));
1157 werner 841
            mRulerColors->setPalette(GridViewRainbow, static_cast<float>(min_value), static_cast<float>(max_value)); // ruler
1040 werner 842
        }
843
 
291 werner 844
        // paint resource units
1180 werner 845
        painter.setPen(Qt::black);
291 werner 846
        foreach (const ResourceUnit *ru, model->ruList()) {
1180 werner 847
            bool stroke = false;
848
            if (species_color) {
849
                if (drawspecies) {
850
                    value = ru->constResourceUnitSpecies(drawspecies)->constStatistics().basalArea();
851
                    fill_color = Colors::colorFromValue(static_cast<float>(value), view_type, static_cast<float>(min_value), static_cast<float>(max_value));
852
                } else {
853
                    const Species *max_sp=0; double max_ba = 0.; double total_ba=0.;
854
                    foreach(const ResourceUnitSpecies *rus, ru->ruSpecies()) {
855
                        total_ba += rus->constStatistics().basalArea();
856
                        if (rus->constStatistics().basalArea()>max_ba) {
857
                            max_ba = rus->constStatistics().basalArea();
858
                            max_sp=rus->species();
859
                        }
860
                    }
861
                    if (max_sp) {
862
                        fill_color = max_sp->displayColor();
863
                        if (max_ba < total_ba*0.5) {
864
                            stroke = true;
865
                        }
866
                    } else
867
                        fill_color = Qt::white;
868
                }
1040 werner 869
            } else {
870
                ru_wrapper.setResourceUnit(ru);
871
                value = ru_value.execute();
1180 werner 872
                fill_color = Colors::colorFromValue(static_cast<float>(value), view_type, static_cast<float>(min_value), static_cast<float>(max_value));
1040 werner 873
            }
291 werner 874
            QRect r = vp.toScreen(ru->boundingBox());
1040 werner 875
            //fill_color = Colors::colorFromValue(value, min_value, max_value);
1180 werner 876
            //fill_color = Colors::colorFromValue(static_cast<float>(value), view_type, static_cast<float>(min_value), static_cast<float>(max_value));
877
            if (stroke)
878
                painter.fillRect(r, QBrush(fill_color, Qt::Dense3Pattern));
879
            else
880
                painter.fillRect(r, fill_color);
291 werner 881
        }
882
        if (!ru_value.lastError().isEmpty())
883
            qDebug() << "Expression error while painting: " << ru_value.lastError();
884
    }
48 Werner 885
 
291 werner 886
    if (show_trees) {
148 iland 887
        QString single_tree_expr = ui->lTreeExpr->text();
888
        if (single_tree_expr.isEmpty())
889
            single_tree_expr = "1-lri";
890
        TreeWrapper tw;
891
 
892
        Expression tree_value(single_tree_expr, &tw);    // get maximum value
893
        tree_value.setCatchExceptions(); // silent catching...
894
 
818 werner 895
        QString filter_expr = ui->expressionFilter->text();
896
        bool do_filter = ui->cbDrawFiltered->isChecked();
897
        if (filter_expr.isEmpty())
898
            filter_expr = "1"; // a constant, always true
899
 
900
        Expression tree_filter(filter_expr, &tw);
901
        tree_filter.setCatchExceptions();
902
 
903
        bool draw_transparent = ui->drawTransparent->isChecked();
128 Werner 904
        AllTreeIterator treelist(model);
107 Werner 905
        Tree *tree;
392 werner 906
        painter.setPen(Qt::gray);
1041 werner 907
        double max_val=1., min_val=0.;
908
        if (!mRulerColors->autoScale()) {
909
            max_val = mRulerColors->maxValue(); min_val = mRulerColors->minValue();
910
        }
911
 
145 Werner 912
        while ((tree = treelist.next())) {
114 Werner 913
            if ( !vp.isVisible(treelist.currentRU()->boundingBox()) ) {
914
                continue;
915
            }
514 werner 916
            // filter species...
917
            if (!species.isEmpty())
918
                if (tree->species()->id() != species)
919
                    continue;
920
 
716 werner 921
            // filter out dead trees
922
            if (tree->isDead())
923
                continue;
924
 
818 werner 925
            // filter (user defined)
926
            if (do_filter) {
927
                tw.setTree(tree);
928
                if (tree_filter.execute()==0.)
929
                    continue;
930
            }
931
 
107 Werner 932
            QPointF pos = tree->position();
56 Werner 933
            QPoint p = vp.toScreen(pos);
493 werner 934
            if (species_color) {
935
                // use species specific color....
936
                fill_color = tree->species()->displayColor();
937
            } else {
938
                // calculate expression
939
                tw.setTree(tree);
1157 werner 940
                value = static_cast<float>(tree_value.execute());
941
                fill_color = Colors::colorFromValue(value, static_cast<float>(min_val), static_cast<float>(max_val), false);
493 werner 942
            }
818 werner 943
            if (draw_transparent)
824 werner 944
                fill_color.setAlpha(80); // 50%
48 Werner 945
            painter.setBrush(fill_color);
407 werner 946
            int diameter = qMax(1,vp.meterToPixel( tree->crownRadius()));
56 Werner 947
            painter.drawEllipse(p, diameter, diameter);
107 Werner 948
        }
291 werner 949
        if (!tree_value.lastError().isEmpty())
950
            qDebug() << "Expression error while painting: " << tree_value.lastError();
880 werner 951
        // ruler
952
        if (species_color) {
953
            mRulerColors->setCaption("Single trees", "species specific colors.");
1066 werner 954
            QList<const Species*> specieslist=mRemoteControl.availableSpecies();
880 werner 955
            QStringList colors; QStringList speciesnames;
1066 werner 956
            for (int i=0; i<specieslist.count();++i) {
957
                colors.append(specieslist[i]->displayColor().name());
958
                speciesnames.append(specieslist[i]->name());
880 werner 959
            }
960
            mRulerColors->setFactorColors(colors);
961
            mRulerColors->setFactorLabels(speciesnames);
962
            mRulerColors->setPalette(GridViewCustom, 0., 1.);
963
        } else {
964
            mRulerColors->setCaption("Single trees", QString("result of expression: '%1'").arg(single_tree_expr));
965
            mRulerColors->setPalette(GridViewRainbow, 0., 1.);
48 Werner 966
 
880 werner 967
        }
968
 
291 werner 969
    } // if (show_trees)
970
 
971
    // highlight selected tree
1157 werner 972
    Tree *t = reinterpret_cast<Tree*>( ui->treeChange->property("tree").toLongLong() );
40 Werner 973
    if (t) {
974
        QPointF pos = t->position();
975
        painter.setPen(Qt::black);
56 Werner 976
        QPoint p = vp.toScreen(pos);
977
        painter.drawRect( p.x()-1, p.y()-1, 3,3);
40 Werner 978
    }
70 Werner 979
}
55 Werner 980
 
647 werner 981
void MainWindow::paintGrid(QPainter &painter, PaintObject &object)
982
{
983
    painter.fillRect(ui->PaintWidget->rect(), object.background_color);
741 werner 984
    bool clip_with_stand_grid = ui->visClipStandGrid->isChecked();
1009 werner 985
    bool shading = ui->visShading->isChecked();
986
    if (!mRemoteControl.model() || !mRemoteControl.model()->dem())
987
         shading=false;
647 werner 988
 
1009 werner 989
 
688 werner 990
    int sx=0, sy=0;
647 werner 991
    QRect total_rect;
992
    object.cur_min_value = object.min_value;
993
    object.cur_max_value = object.max_value;
994
    switch (object.what) {
995
    case PaintObject::PaintMapGrid:
996
        sx = object.map_grid->grid().sizeX();
997
        sy = object.map_grid->grid().sizeY();
998
        total_rect = vp.toScreen(object.map_grid->grid().metricRect());
880 werner 999
        mRulerColors->setCaption("Map grid");
647 werner 1000
        break;
1001
    case PaintObject::PaintFloatGrid:
1002
        sx = object.float_grid->sizeX();
1003
        sy = object.float_grid->sizeY();
1004
        total_rect = vp.toScreen(object.float_grid->metricRect());
880 werner 1005
        mRulerColors->setCaption("Floating point grid");
647 werner 1006
        break;
1007
    case PaintObject::PaintLayers:
1008
        sx = object.layered->sizeX();
1009
        sy = object.layered->sizeY();
1010
        total_rect = vp.toScreen(object.layered->metricRect());
1011
        if (object.auto_range) {
1012
            object.layered->range( object.cur_min_value, object.cur_max_value, object.layer_id );
1013
        }
1014 werner 1014
        mRulerColors->setCaption(const_cast<LayeredGridBase*>(object.layered)->names()[object.layer_id].name,
1015
                const_cast<LayeredGridBase*>(object.layered)->names()[object.layer_id].description);
647 werner 1016
        break;
1017
    case PaintObject::PaintNothing:
880 werner 1018
        mRulerColors->setCaption("-");
647 werner 1019
        return;
1032 werner 1020
    default: return;
647 werner 1021
    }
1041 werner 1022
    if (!mRulerColors->autoScale()) {
1023
        object.cur_max_value = mRulerColors->maxValue();
1024
        object.cur_min_value = mRulerColors->minValue();
1025
    }
647 werner 1026
 
1027
 
1028
 
1029
    painter.setPen(Qt::black);
1030
    painter.drawRect(total_rect);
1031
 
1032
 
1033
    int ix,iy;
688 werner 1034
    double value=0.;
647 werner 1035
    QRect r;
1036
    QColor fill_color;
880 werner 1037
    double max_value = -1.;
741 werner 1038
    QPointF pmetric;
647 werner 1039
    for (iy=0;iy<sy;iy++) {
1040
        for (ix=0;ix<sx;ix++) {
1041
            QPoint p(ix,iy);
1042
            switch(object.what) {
1043
            case PaintObject::PaintMapGrid:
1044
                value = object.map_grid->grid().constValueAtIndex(p);
741 werner 1045
                pmetric = object.map_grid->grid().cellRect(p).center();
647 werner 1046
                r = vp.toScreen(object.map_grid->grid().cellRect(p));
741 werner 1047
 
647 werner 1048
                break;
1049
            case PaintObject::PaintFloatGrid:
1050
                value = object.float_grid->constValueAtIndex(p);
741 werner 1051
                pmetric = object.float_grid->cellRect(p).center();
647 werner 1052
                r = vp.toScreen(object.float_grid->cellRect(p));
1053
                break;
1054
            case PaintObject::PaintLayers:
1055
                value = object.layered->value(ix, iy, object.layer_id);
741 werner 1056
                pmetric = object.layered->cellRect(p).center();
880 werner 1057
                max_value = qMax(max_value, value);
647 werner 1058
                r = vp.toScreen(object.layered->cellRect(p));
1059
                break;
1060
            default: ;
1061
            }
741 werner 1062
            if (clip_with_stand_grid && !GlobalSettings::instance()->model()->heightGrid()->valueAt(pmetric).isValid()) {
1063
                fill_color = Qt::white;
1064
            } else {
877 werner 1065
                fill_color = Colors::colorFromValue(value, object.view_type, object.cur_min_value, object.cur_max_value);
1009 werner 1066
                if (shading)
1067
                    fill_color = Colors::shadeColor(fill_color, pmetric, mRemoteControl.model()->dem());
741 werner 1068
            }
647 werner 1069
            painter.fillRect(r, fill_color);
1070
        }
1071
    }
880 werner 1072
    // update ruler
1073
    if (object.view_type>=10) {
1074
        QStringList labels;
1075
        for (int i=0;i<max_value;++i)
1076
            labels.append(object.layered->labelvalue(i,object.layer_id));
1077
        mRulerColors->setFactorLabels(labels);
1078
    }
1079
    mRulerColors->setPalette(object.view_type, object.cur_min_value, object.cur_max_value); // ruler
647 werner 1080
 
1081
}
1082
 
596 werner 1083
// paint the values of the MapGrid
643 werner 1084
void MainWindow::paintMapGrid(QPainter &painter,
1085
                              MapGrid *map_grid, const FloatGrid *float_grid,
1086
                              const GridViewType view_type,
1087
                              double min_val, double max_val)
596 werner 1088
{
1089
    // clear background
1090
    painter.fillRect(ui->PaintWidget->rect(), Qt::white);
642 werner 1091
    const Grid<int> *int_grid = 0;
20 Werner 1092
 
642 werner 1093
    int sx, sy;
1094
    QRect total_rect;
596 werner 1095
 
642 werner 1096
    if (map_grid) {
1097
        int_grid = &map_grid->grid();
1098
        sx = int_grid->sizeX();
1099
        sy = int_grid->sizeY();
1100
        total_rect = vp.toScreen(int_grid->metricRect());
1101
    } else {
1102
        if (!float_grid)
1103
            return;
1104
        sx = float_grid->sizeX();
1105
        sy = float_grid->sizeY();
1106
        total_rect = vp.toScreen(float_grid->metricRect());
1107
    }
1108
 
596 werner 1109
    // draw rectangle around the grid
1110
    painter.setPen(Qt::black);
642 werner 1111
    painter.drawRect(total_rect);
596 werner 1112
    // paint the lower-res-grid;
1113
    int ix,iy;
642 werner 1114
    double value;
1115
    QRect r;
596 werner 1116
    QColor fill_color;
881 werner 1117
 
880 werner 1118
    if (view_type<10)
1119
        mRulerColors->setPalette(view_type,min_val, max_val); // ruler
1120
    else
1121
        mRulerColors->setPalette(view_type, 0, max_val); // ruler
1122
 
643 werner 1123
    bool reverse = view_type == GridViewRainbowReverse || view_type == GridViewGrayReverse;
1124
    bool black_white = view_type == GridViewGray || view_type == GridViewGrayReverse;
642 werner 1125
    for (iy=0;iy<sy;iy++) {
1126
        for (ix=0;ix<sx;ix++) {
596 werner 1127
            QPoint p(ix,iy);
642 werner 1128
            if (int_grid){
1129
                value = int_grid->constValueAtIndex(p);
1130
                r = vp.toScreen(int_grid->cellRect(p));
1131
            } else {
1132
                value = float_grid->constValueAtIndex(p);
1133
                r = vp.toScreen(float_grid->cellRect(p));
1134
            }
877 werner 1135
            fill_color = view_type<10? Colors::colorFromValue(value, min_val, max_val, reverse,black_white) : Colors::colorFromPalette(value, view_type);
596 werner 1136
            painter.fillRect(r, fill_color);
1137
        }
1138
    }
1139
 
1140
}
1141
 
20 Werner 1142
void MainWindow::repaintArea(QPainter &painter)
1143
{
129 Werner 1144
     paintFON(painter, ui->PaintWidget->rect());
49 Werner 1145
    // fix viewpoint
1146
    vp.setScreenRect(ui->PaintWidget->rect());
880 werner 1147
    mRulerColors->setScale(vp.pixelToMeter(1));
20 Werner 1148
}
1149
 
129 Werner 1150
 
48 Werner 1151
void MainWindow::on_visFon_toggled() { ui->PaintWidget->update(); }
1152
void MainWindow::on_visDomGrid_toggled() { on_visFon_toggled(); }
1153
void MainWindow::on_visImpact_toggled() { on_visFon_toggled(); }
40 Werner 1154
bool wantDrag=false;
6 Werner 1155
void MainWindow::mouseClick(const QPoint& pos)
1156
{
916 werner 1157
    if (!mRemoteControl.canRun())
1158
        return;
1159
 
58 Werner 1160
    QPointF coord=vp.toWorld(pos);
275 werner 1161
    //qDebug() << "to world:" << coord;
40 Werner 1162
    wantDrag = false;
1163
    ui->PaintWidget->setCursor(Qt::CrossCursor);
293 werner 1164
    Model *model = mRemoteControl.model();
1165
    ResourceUnit *ru = model->ru(coord);
40 Werner 1166
    // find adjactent tree
128 Werner 1167
 
896 werner 1168
    // test ressource units...
293 werner 1169
    if (ui->visResourceUnits->isChecked()) {
1170
        if (!ru) return;
1171
        showResourceUnitDetails(ru);
1172
        return;
1173
    }
1174
 
896 werner 1175
    // test for ABE grid
1176
    if (ui->visOtherGrid->isChecked()) {
1177
        if (showABEDetails(coord))
1178
            return;
1179
    }
275 werner 1180
    //qDebug() << "coord:" << coord << "RU:"<< ru << "ru-rect:" << ru->boundingBox();
1157 werner 1181
    if (!ru)
1182
        return;
1183
 
293 werner 1184
    ui->treeChange->setProperty("tree",0);
114 Werner 1185
    QVector<Tree> &mTrees =  ru->trees();
105 Werner 1186
    QVector<Tree>::iterator tit;
155 werner 1187
    Tree *closestTree=0;
1188
    double min_distance = 100000000, current_dist;
15 Werner 1189
    for (tit=mTrees.begin(); tit!=mTrees.end(); ++tit) {
155 werner 1190
        current_dist = distance(tit->position(),coord);
1191
        if (current_dist<min_distance) {
1192
            closestTree = &(*tit);
1193
            min_distance = current_dist;
1194
        }
1195
    }
1196
    if (min_distance<5 && closestTree) {
1197
            Tree *p = closestTree;
275 werner 1198
            //qDebug() << "found!" << tit->id() << "at" << tit->position()<<"value"<<p->lightResourceIndex();
1199
            //qDebug() <<p->dump();
149 werner 1200
            showTreeDetails(p);
1201
 
1035 werner 1202
            ui->treeChange->setProperty("tree", qVariantFromValue((void*)p));
40 Werner 1203
            ui->treeDbh->setValue(p->dbh());
1204
            ui->treeHeight->setValue(p->height());
49 Werner 1205
            ui->treePosX->setValue(p->position().x());
1206
            ui->treePosY->setValue(p->position().y());
187 iland 1207
            ui->treeImpact->setText(QString("#:%1 - %2").arg(p->id()).arg(p->lightResourceIndex(),5));
40 Werner 1208
            wantDrag=true;
1209
            ui->PaintWidget->setCursor(Qt::SizeAllCursor);
1210
            ui->PaintWidget->update();
155 werner 1211
    }
1212
 
6 Werner 1213
}
3 Werner 1214
 
293 werner 1215
void MainWindow::showResourceUnitDetails(const ResourceUnit *ru)
1216
{
1217
    ui->dataTree->clear();
1218
    RUWrapper ruw;
1219
    ruw.setResourceUnit(ru);
1220
    const QStringList &names = ruw.getVariablesList();
1221
    QList<QTreeWidgetItem *> items;
1222
    foreach(QString name, names) {
1223
        items.append(new QTreeWidgetItem(QStringList()<<name<<QString::number(ruw.valueByName(name)) ));
1224
    }
1078 werner 1225
    // add special values (strings)
1226
    if (ru->climate())
1227
        items.append(new QTreeWidgetItem(QStringList()<<"climate"<<ru->climate()->name() ));
1228
 
528 werner 1229
    QList<QPair<QString, QVariant> > dbgdata = GlobalSettings::instance()->debugValues(-ru->index()); // hack: use negative values for resource units
1230
 
1231
    QList<QPair<QString, QVariant> >::const_iterator i = dbgdata.constBegin();
1232
    while (i != dbgdata.constEnd()) {
1233
     //cout << i.key() << ": " << i.value() << endl;
1234
        items.append(new QTreeWidgetItem(QStringList()
1235
                                         << (*i).first
1236
                                         << (*i).second.toString()) );
1237
        ++i;
1238
     }
293 werner 1239
    ui->dataTree->addTopLevelItems(items);
1240
}
1241
 
896 werner 1242
bool MainWindow::showABEDetails(const QPointF &coord)
1243
{
897 werner 1244
    if (!mRemoteControl.canRun()) return false;
962 werner 1245
    if (mPaintNext.layered) {
1246
        if (mPaintNext.layered->onClick(coord))
1247
            return true;
1248
    }
909 werner 1249
    if (!mPaintNext.layered || !mRemoteControl.model()->ABEngine()) return false;
899 werner 1250
    QString grid_name = mPaintNext.name;
909 werner 1251
    QStringList list = mRemoteControl.model()->ABEngine()->evaluateClick(coord, grid_name);
716 werner 1252
 
896 werner 1253
    ui->dataTree->clear();
1254
    QList<QTreeWidgetItem *> items;
1255
    QStack<QTreeWidgetItem*> stack;
1256
    stack.push(0);
1257
    foreach (QString s, list) {
1258
        QStringList elem = s.split(":");
1259
        if (s=="-")
1260
            stack.push(items.back());
1261
        else if (s=="/-")
1262
            stack.pop();
1263
        else  {
1264
            items.append( new QTreeWidgetItem(stack.last(), elem) );
1265
        }
1266
    }
1267
    ui->dataTree->addTopLevelItems(items);
1268
    return true; // handled
1269
 
1270
 
1271
 
1272
}
1273
 
1274
 
149 werner 1275
void MainWindow::showTreeDetails(Tree *tree)
1276
{
1277
    ui->dataTree->clear();
1278
    TreeWrapper tw;
1279
    tw.setTree(tree);
1280
    const QStringList &names = tw.getVariablesList();
1281
    QList<QTreeWidgetItem *> items;
1282
    foreach(QString name, names) {
818 werner 1283
        if (name=="species")
1284
            items.append(new QTreeWidgetItem(QStringList() << name << mRemoteControl.model()->speciesSet()->species(tw.valueByName(name))->id() ));
1285
        else
1286
            items.append(new QTreeWidgetItem(QStringList() << name << QString::number(tw.valueByName(name)) ));
149 werner 1287
    }
160 werner 1288
    QList<QPair<QString, QVariant> > dbgdata = GlobalSettings::instance()->debugValues(tree->id());
153 werner 1289
 
160 werner 1290
    QList<QPair<QString, QVariant> >::const_iterator i = dbgdata.constBegin();
1291
    while (i != dbgdata.constEnd()) {
1292
     //cout << i.key() << ": " << i.value() << endl;
1293
        items.append(new QTreeWidgetItem(QStringList()
1294
                                         << (*i).first
1295
                                         << (*i).second.toString()) );
1296
        ++i;
1297
     }
149 werner 1298
    ui->dataTree->addTopLevelItems(items);
1299
}
1300
 
49 Werner 1301
void MainWindow::mouseMove(const QPoint& pos)
1302
{
127 Werner 1303
 
1071 werner 1304
    if (!mRemoteControl.canRun() )
49 Werner 1305
        return;
128 Werner 1306
    FloatGrid *grid = mRemoteControl.model()->grid();
49 Werner 1307
    QPointF p = vp.toWorld(pos);
648 werner 1308
    bool has_value = true;
1309
    double value;
127 Werner 1310
    if (grid->coordValid(p)) {
291 werner 1311
        QString location=QString("%1 / %2").arg(p.x()).arg(p.y());
732 werner 1312
        if (ui->visOtherGrid->isChecked()) {
1313
            switch (mPaintNext.what) {
1314
            case PaintObject::PaintFloatGrid:
758 werner 1315
                value = mPaintNext.float_grid->isEmpty()?0: mPaintNext.float_grid->constValueAt(p);
732 werner 1316
                break;
1317
            case PaintObject::PaintMapGrid:
1318
                value = mPaintNext.map_grid->grid().constValueAt(p);
1319
                break;
1320
            case PaintObject::PaintLayers:
1321
                value = mPaintNext.layered->value(p, mPaintNext.layer_id);
877 werner 1322
                if (mPaintNext.view_type>=10) {// classes
1323
                   location += QString("\n %1").arg(mPaintNext.layered->labelvalue(value, mPaintNext.layer_id));
1324
                   ui->fonValue->setText(location);
1325
                   return;
1326
                }
1327
 
732 werner 1328
                break;
1329
            default: has_value = false;
1330
            }
1331
            if (has_value) {
1332
                location += QString("\n %1").arg(value);
1333
                ui->fonValue->setText(location);
1334
                return;
1335
            }
648 werner 1336
        }
291 werner 1337
 
642 werner 1338
        if (ui->visFon->isChecked() || ui->visImpact->isChecked()) {
1339
            if (mPaintNext.what == PaintObject::PaintFloatGrid && mPaintNext.float_grid)
1340
                location += QString("\n %1").arg(mPaintNext.float_grid->constValueAt(p));
1341
            else
1342
                location += QString("\n %1").arg((*grid).valueAt(p));
1343
        }
58 Werner 1344
        if( ui->visDomGrid->isChecked())
291 werner 1345
            location += QString("\n %1").arg((*mRemoteControl.model()->heightGrid()).valueAt(p).height);
822 werner 1346
        if( ui->visRegeneration->isChecked() && !mRegenerationGrid.isEmpty())
453 werner 1347
            location += QString("\n %1").arg(mRegenerationGrid.valueAt(p));
1179 werner 1348
        if (ui->visSeeds->isChecked() && ui->speciesFilterBox->currentIndex()>-1) {
1349
            Species *s=GlobalSettings::instance()->model()->speciesSet()->species(ui->speciesFilterBox->itemData(ui->speciesFilterBox->currentIndex()).toString());
1350
            if (s && s->seedDispersal())
1351
              location += QString("\n %1").arg(s->seedDispersal()->seedMap().constValueAt(p));
1352
        }
291 werner 1353
 
1354
        ui->fonValue->setText(location);
51 Werner 1355
    }
49 Werner 1356
}
3 Werner 1357
 
113 Werner 1358
void MainWindow::mouseWheel(const QPoint& pos, int steps)
40 Werner 1359
{
274 werner 1360
    //qDebug() << "mouse-wheel" << steps;
113 Werner 1361
    vp.zoomTo(pos, qMax(1-(2*steps/10.),0.2));
1362
    ui->PaintWidget->update();
1363
}
1364
 
1365
void MainWindow::mouseDrag(const QPoint& from, const QPoint &to, Qt::MouseButton button)
1366
{
1367
    qDebug() << "drag" << button;
40 Werner 1368
    ui->PaintWidget->setCursor(Qt::CrossCursor);
517 werner 1369
    // move view area if not dedicately moving around a tree
1370
    if (!wantDrag) {
113 Werner 1371
        vp.moveTo(from, to);
1372
        ui->PaintWidget->update();
1373
        return;
1374
    }
517 werner 1375
    wantDrag = false;
40 Werner 1376
    qDebug() << "drag from" << from << "to" << to;
1157 werner 1377
    Tree *t = reinterpret_cast<Tree*>( ui->treeChange->property("tree").toLongLong() );
40 Werner 1378
    if (!t)
1379
        return;
58 Werner 1380
    QPointF pos = vp.toWorld(to);
40 Werner 1381
    // calculate new position...
1382
    t->setPosition(pos);
127 Werner 1383
    readwriteCycle();
403 werner 1384
    ui->PaintWidget->update();
40 Werner 1385
}
3 Werner 1386
 
1387
 
1388
 
19 Werner 1389
void MainWindow::on_actionEdit_XML_settings_triggered()
1390
{
1391
    ui->editStack->setCurrentIndex(0);
20 Werner 1392
    ui->PaintWidget->update();
19 Werner 1393
}
1394
 
776 werner 1395
QMutex mutex_yearSimulated;
222 werner 1396
void MainWindow::yearSimulated(int year)
1397
{
776 werner 1398
    QMutexLocker mutex_locker(&mutex_yearSimulated);
1399
    checkModelState();
1400
    ui->modelRunProgress->setValue(year);
1401
    labelMessage(QString("Running.... year %1 of %2.").arg(year).arg(mRemoteControl.totalYears()));
948 werner 1402
    ui->treeChange->setProperty("tree",0);
776 werner 1403
    ui->PaintWidget->update();
1404
    QApplication::processEvents();
222 werner 1405
}
19 Werner 1406
 
222 werner 1407
void MainWindow::modelFinished(QString errorMessage)
1408
{
921 werner 1409
    if (!errorMessage.isEmpty()) {
1410
        Helper::msg(errorMessage);
1411
        labelMessage("Error!");
1412
        qDebug() << "Error:" << errorMessage;
1413
    } else {
1414
        qDebug() << "Finished!";
1415
        labelMessage("Finished!!");
1416
    }
493 werner 1417
 
225 werner 1418
    checkModelState();
661 werner 1419
    if (windowTitle().contains("batch")) {
1420
        // we are in automatic batch mode.
1421
        // we should therefore close down the application.
921 werner 1422
        if (!errorMessage.isEmpty())
1423
            batchLog(QString("error: %1").arg(errorMessage));
661 werner 1424
        batchLog(QString("%1 Finished!!! shutting down...").arg(QDateTime::currentDateTime().toString(Qt::ISODate)));
1425
 
1426
        qDebug() << "****************************";
767 werner 1427
        qDebug() << "Finished automated model run: " << errorMessage;
661 werner 1428
        qDebug() << "****************************";
1429
 
1430
        close(); // shut down the application....
1431
 
1432
    }
222 werner 1433
}
19 Werner 1434
 
344 werner 1435
/// creates the iLand model
104 Werner 1436
void MainWindow::setupModel()
1437
{
1058 werner 1438
    //recent file menu
1439
    recentFileMenu();
1440
 
129 Werner 1441
    // load project xml file to global xml settings structure
189 iland 1442
    mRemoteControl.setFileName(ui->initFileName->text());
1443
    //GlobalSettings::instance()->loadProjectFile(ui->initFileName->text());
493 werner 1444
    labelMessage("Creating model...");
359 werner 1445
 
1446
    // setup logging
360 werner 1447
    setupFileLogging(true);
359 werner 1448
 
129 Werner 1449
    // create the model
1450
    mRemoteControl.create();
575 werner 1451
    if (!mRemoteControl.canRun())
1452
        return;
1453
 
129 Werner 1454
    Model *model = mRemoteControl.model();
189 iland 1455
    if (model && model->isSetup()) {
105 Werner 1456
        // set viewport of paintwidget
129 Werner 1457
        vp = Viewport(model->grid()->metricRect(), ui->PaintWidget->rect());
135 Werner 1458
        ui->PaintWidget->update();
129 Werner 1459
    }
776 werner 1460
    ui->treeChange->setProperty("tree",0);
802 werner 1461
 
776 werner 1462
    // setup dynamic output
1463
    QString dout = GlobalSettings::instance()->settings().value("output.dynamic.columns");
802 werner 1464
    mRemoteControl.setupDynamicOutput(dout);
1465
    mRemoteControl.setDynamicOutputEnabled(GlobalSettings::instance()->settings().valueBool("output.dynamic.enabled",false));
1466
 
776 werner 1467
    ui->modelRunProgress->setValue(0);
1468
    QSettings().setValue("project/lastxmlfile", ui->initFileName->text());
1469
    // magic debug output number
1470
    GlobalSettings::instance()->setDebugOutput((int) GlobalSettings::instance()->settings().valueDouble("system.settings.debugOutput"));
514 werner 1471
 
776 werner 1472
    // populate the tree species filter list
1473
    ui->speciesFilterBox->clear();
1474
    ui->speciesFilterBox->addItem("<all species>", "");
1066 werner 1475
    QList<const Species*> list = mRemoteControl.availableSpecies();
1476
    for (int i=0;i<list.size();++i)
1477
        ui->speciesFilterBox->addItem(list[i]->name(), list[i]->id());
514 werner 1478
 
776 werner 1479
    // retrieve the active management script file
1480
    if (mRemoteControl.model()->management())
1064 werner 1481
        ui->scriptActiveScriptFile->setText(QString("%1").arg(mRemoteControl.model()->management()->scriptFile()));
1482
    if (!mRemoteControl.loadedJavascriptFile().isEmpty())
1483
        ui->scriptActiveScriptFile->setText(QString("%1").arg(mRemoteControl.loadedJavascriptFile()));
776 werner 1484
    labelMessage("Model created. Ready to run.");
1485
    checkModelState();
1043 valentin 1486
 
104 Werner 1487
}
1488
 
28 Werner 1489
 
39 Werner 1490
 
58 Werner 1491
void MainWindow::on_pbSetAsDebug_clicked()
1492
{
1157 werner 1493
    Tree *t = reinterpret_cast<Tree *>( ui->treeChange->property("tree").toLongLong() );
1494
    if (!t)
58 Werner 1495
        return;
1496
    t->enableDebugging();
1497
 
1498
}
65 Werner 1499
 
1500
void MainWindow::on_openFile_clicked()
1501
{
1053 werner 1502
    QString fileName = Helper::fileDialog("select XML-project file", ui->initFileName->text(), "*.xml",this);
65 Werner 1503
    if (fileName.isEmpty())
1504
        return;
1505
    ui->initFileName->setText(fileName);
1506
    QString xmlFile = Helper::loadTextFile(ui->initFileName->text());
1507
    ui->iniEdit->setPlainText(xmlFile);
776 werner 1508
    checkModelState();
65 Werner 1509
}
67 Werner 1510
 
1511
void MainWindow::on_actionTreelist_triggered()
1512
{
1513
    QApplication::clipboard()->setText(dumpTreelist());
1514
    qDebug() << "treelist copied to clipboard.";
1515
}
1516
 
1517
void MainWindow::on_actionFON_grid_triggered()
1518
{
356 werner 1519
    //if (!mRemoteControl.isRunning()) return;
128 Werner 1520
    QString gr = gridToString(*mRemoteControl.model()->grid());
67 Werner 1521
    QApplication::clipboard()->setText(gr);
1522
    qDebug() << "grid copied to clipboard.";
1523
}
69 Werner 1524
 
106 Werner 1525
 
129 Werner 1526
void MainWindow::on_actionModelCreate_triggered()
1527
{
1528
    // create model
1529
    setupModel();
1530
    checkModelState();
1531
}
1532
 
1533
void MainWindow::on_actionModelDestroy_triggered()
1534
{
1065 werner 1535
    mPaintNext.what = PaintObject::PaintNothing;
129 Werner 1536
    mRemoteControl.destroy();
1157 werner 1537
    mRegenerationGrid.clear();
129 Werner 1538
    checkModelState();
1539
}
1540
 
1541
void MainWindow::on_actionModelRun_triggered()
1542
{
1543
   if (!mRemoteControl.canRun())
1544
        return;
497 werner 1545
   QString msg = QString("How many years to run?\nCurrent year: %1.").arg(mRemoteControl.currentYear());
322 werner 1546
   bool ok;
138 Werner 1547
   int count = QInputDialog::getInt(this, "input value",
798 werner 1548
                                        msg, 10, 0, 10000, 1, &ok);
322 werner 1549
   if (!ok)
1550
       return;
497 werner 1551
   count = count + mRemoteControl.currentYear();
948 werner 1552
   ui->treeChange->setProperty("tree",0);
219 werner 1553
   ui->modelRunProgress->setMaximum(count-1);
222 werner 1554
   mRemoteControl.run(count);
1180 werner 1555
   GlobalSettings::instance()->executeJSFunction("onAfterRun");
222 werner 1556
 
138 Werner 1557
}
1558
 
1559
void MainWindow::on_actionRun_one_year_triggered()
1560
{
1561
   if (!mRemoteControl.canRun())
1562
        return;
948 werner 1563
   ui->treeChange->setProperty("tree",0);
129 Werner 1564
   mRemoteControl.runYear();
229 werner 1565
   GlobalSettings::instance()->outputManager()->save(); // save output tables when stepping single year by year
498 werner 1566
   labelMessage(QString("Simulated a single year. year %1.").arg(mRemoteControl.currentYear()));
1567
 
776 werner 1568
   ui->PaintWidget->update();
129 Werner 1569
   checkModelState();
1570
}
1571
 
138 Werner 1572
void MainWindow::on_actionReload_triggered()
1573
{
1574
    if (!mRemoteControl.canDestroy())
1575
        return;
1065 werner 1576
    mPaintNext.what = PaintObject::PaintNothing;
138 Werner 1577
    mRemoteControl.destroy();
1157 werner 1578
    mRegenerationGrid.clear();
138 Werner 1579
    setupModel();
1580
}
129 Werner 1581
 
225 werner 1582
void MainWindow::on_actionPause_triggered()
1583
{
1584
    mRemoteControl.pause();
493 werner 1585
    if (!mRemoteControl.isRunning())
1586
        labelMessage("Model execution paused...");
776 werner 1587
 
1588
    checkModelState();
1589
 
1590
    if (!mRemoteControl.isPaused())
1591
        mRemoteControl.continueRun();
225 werner 1592
}
1593
 
1594
void MainWindow::on_actionStop_triggered()
1595
{
1596
    mRemoteControl.cancel();
493 werner 1597
    labelMessage("Model stopped.");
225 werner 1598
}
1599
 
129 Werner 1600
void MainWindow::on_actionTree_Partition_triggered()
1601
{
130 Werner 1602
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dTreePartition, ";");
129 Werner 1603
    QApplication::clipboard()->setText(result.join("\n"));
1604
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1605
}
1606
 
1168 werner 1607
void MainWindow::on_action_debugSapling_triggered()
1608
{
1609
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dSaplingGrowth, ";");
1610
    QApplication::clipboard()->setText(result.join("\n"));
1611
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1612
 
1613
}
1614
 
129 Werner 1615
void MainWindow::on_actionTree_Growth_triggered()
1616
{
130 Werner 1617
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dTreeGrowth, ";");
129 Werner 1618
    QApplication::clipboard()->setText(result.join("\n"));
1619
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1620
}
1621
 
133 Werner 1622
void MainWindow::on_actionTree_NPP_triggered()
1623
{
1624
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dTreeNPP, ";");
1625
    QApplication::clipboard()->setText(result.join("\n"));
1626
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1627
}
1628
 
239 werner 1629
void MainWindow::on_actionWater_Output_triggered()
1630
{
1631
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dWaterCycle, ";");
1632
    QApplication::clipboard()->setText(result.join("\n"));
1633
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1634
}
329 werner 1635
void MainWindow::on_actionDaily_responses_Output_triggered()
1636
{
1637
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dDailyResponses, ";");
1638
    QApplication::clipboard()->setText(result.join("\n"));
1639
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
344 werner 1640
}
138 Werner 1641
 
442 werner 1642
void MainWindow::on_action_debugEstablishment_triggered()
1643
{
1644
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dEstablishment, ";");
1645
    QApplication::clipboard()->setText(result.join("\n"));
1646
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
1647
}
1648
 
477 werner 1649
void MainWindow::on_actionSnag_Dynamics_triggered()
1650
{
526 werner 1651
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dCarbonCycle, ";");
477 werner 1652
    QApplication::clipboard()->setText(result.join("\n"));
1653
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
442 werner 1654
 
477 werner 1655
}
1656
 
615 werner 1657
void MainWindow::on_actionPerformance_triggered()
1658
{
1659
    QStringList result = GlobalSettings::instance()->debugDataTable(GlobalSettings::dPerformance, ";");
1660
    QApplication::clipboard()->setText(result.join("\n"));
1661
    qDebug() << "copied" <<  result.count() << "lines of debug data to clipboard.";
573 werner 1662
 
615 werner 1663
}
1664
 
590 werner 1665
QImage MainWindow::screenshot()
1666
{
1667
    return ui->PaintWidget->drawImage();
1668
}
1669
 
634 werner 1670
/// set the viewport of the main viewing window
1671
/// @p center_point is the point to zoom to (world coordinates), and @p scael_px_per_m is the
1672
/// pixel/m scaling.
1673
void MainWindow::setViewport(QPointF center_point, double scale_px_per_m)
1674
{
1180 werner 1675
    if (scale_px_per_m>0.)
1676
        vp.setViewPoint(center_point, scale_px_per_m);
1677
    else
1678
        vp.zoomToAll();
634 werner 1679
 
644 werner 1680
//    double current_px = vp.pixelToMeter(1); // number of meters covered by one pixel
1681
//    if (current_px==0)
1682
//        return;
1683
 
1684
//    vp.setCenterPoint(center_point);
1685
//    QPoint screen = vp.toScreen(center_point); // screen coordinates of the target point
1686
//    double target_scale = scale_px_per_m / current_px;
1687
 
1688
//    vp.zoomTo(screen, target_scale);
634 werner 1689
    ui->PaintWidget->update();
1690
    QCoreApplication::processEvents();
1691
}
1692
 
1061 werner 1693
void MainWindow::setUIshortcuts(QVariantMap shortcuts)
1694
{
1695
    if (shortcuts.isEmpty()) {
1696
        ui->lJSShortcuts->setText("(no shortcuts defined)");
1697
        return;
1698
    }
1699
    QString msg = "<html><head/><body><p>Javascript shortcuts<br>";
1700
    QVariantMap::const_iterator i;
1701
    for (i = shortcuts.constBegin(); i != shortcuts.constEnd(); ++i) {
1702
        QString line = QString("<a href =\"%1\"><span style=\" text-decoration: underline; color:#0000ff;\">%1</span></a>: %2<br>").arg(i.key(), i.value().toString());
1703
        msg += line;
1704
    }
1705
    msg += "</body></html>";
1706
    //qDebug() << msg;
1707
 
1708
    ui->lJSShortcuts->setText(msg);
1709
    ui->lJSShortcuts->setTextInteractionFlags(Qt::TextBrowserInteraction);
1710
}
1711
 
716 werner 1712
void MainWindow::closeEvent(QCloseEvent *event)
1713
{
1714
    writeSettings();
1715
    event->accept();
1716
}
1717
 
573 werner 1718
void MainWindow::on_actionImageToClipboard_triggered()
1719
{
1061 werner 1720
    //QClipboard *clipboard = QApplication::clipboard();
1054 werner 1721
    QImage my_img = screenshot();
1722
    my_img.convertToFormat(QImage::Format_RGB32);
1723
    //clipboard->setImage( my_img, QClipboard::Clipboard );
1724
    QString pth = GlobalSettings::instance()->path("screenshot.png", "temp");
1725
    screenshot().save(pth);
1726
    qDebug() << "copied image to clipboard. save also to: " << pth;
1727
    my_img.load(pth);
1728
    QApplication::clipboard()->setImage(my_img);
1729
 
573 werner 1730
}
1731
 
344 werner 1732
 
129 Werner 1733
void MainWindow::on_actionSelect_Data_Types_triggered()
1734
{
382 werner 1735
    int value = GlobalSettings::instance()->currentDebugOutput();
129 Werner 1736
    int newvalue = QInputDialog::getInt(this, "QInputDialog::getText()",
1737
                                        "Enter code for desired outputs: add\n" \
133 Werner 1738
                                        "1 ... Tree NPP\n" \
129 Werner 1739
                                        "2 ... Tree partition\n" \
133 Werner 1740
                                        "4 ... Tree growth (dbh,h)\n" \
1196 werner 1741
                                        "8 ... Standlevel GPP\n" \
239 werner 1742
                                        "16...Water Cycle\n" \
442 werner 1743
                                        "32...Daily responses\n" \
476 werner 1744
                                        "64...Establishment\n" \
1168 werner 1745
                                        "128...Sapling growth\n" \
1746
                                        "256...Carbon cycle\n" \
1747
                                        "512...Performance\n"
129 Werner 1748
                                        "(e.g.: 5 = NPP + tree growth) or 0 for no debug outputs.", value);
1749
     GlobalSettings::instance()->setDebugOutput(newvalue);
1750
}
133 Werner 1751
 
1752
 
138 Werner 1753
 
1754
 
142 Werner 1755
// Expression test
1756
void MainWindow::on_pbCalculateExpression_clicked()
1757
{
1758
    QString expr_text=ui->expressionText->text();
1759
    QString expr_filter=ui->expressionFilter->text();
143 Werner 1760
    if (expr_text == "test") {
808 werner 1761
        on_actionTest_triggered();
143 Werner 1762
        return;
1763
    }
142 Werner 1764
    if (expr_filter.isEmpty())
1765
        expr_filter = "1"; // a constant true expression
1766
    TreeWrapper wrapper;
1767
    Expression expr(expr_text, &wrapper);
1768
    Expression filter(expr_filter, &wrapper);
1769
    AllTreeIterator at(GlobalSettings::instance()->model());
143 Werner 1770
    int totalcount=0;
1771
    QVector<double> datavector;
142 Werner 1772
    try {
143 Werner 1773
 
142 Werner 1774
        while (Tree *tree=at.next()) {
1775
            wrapper.setTree(tree);
1776
            if (filter.execute()) {
143 Werner 1777
                datavector << expr.execute();
142 Werner 1778
            }
1779
            totalcount++;
1780
        }
1781
    } catch (IException &e) {
575 werner 1782
        Helper::msg(e.message());
142 Werner 1783
    }
143 Werner 1784
    StatData stats(datavector);
1785
    qDebug() << "Expression:" << expr_text << "filtered" << datavector.count() << "of" << totalcount;
1786
    qDebug() << "sum:" << stats.sum() << "min" << stats.min() << "max" << stats.max() << "average" << stats.mean();
1787
    qDebug() << "P25" << stats.percentile25() << "median" << stats.median() << "P75" << stats.percentile75() << "P90" << stats.percentile(90);
1788
 
1789
    //qDebug() << "Expression:" << expr_text << "results: count of total: " << count << "/" << totalcount
1790
    //        << "sum:" << sum  << "average:" << (count>0?sum/double(count):0.) << "minval:" << minval << "maxval:" << maxval;
142 Werner 1791
    // add to history
1792
    if (!ui->expressionHistory->currentItem() || ui->expressionHistory->currentItem()->text() != expr_text) {
1793
        ui->expressionHistory->insertItem(0, expr_text);
1794
        ui->expressionHistory->setCurrentRow(0);
1795
    }
1796
}
148 iland 1797
 
1798
void MainWindow::on_pbExecExpression_clicked()
1799
{
1800
    // just repaint...
1801
    ui->PaintWidget->update();
1802
}
161 werner 1803
 
1804
void MainWindow::on_actionDynamic_Output_triggered()
1805
{
1806
    QApplication::clipboard()->setText(mRemoteControl.dynamicOutput());
1807
    qDebug() << "copied dynamic output to clipboard";
1808
}
194 werner 1809
 
1810
void MainWindow::on_actionShow_Debug_Messages_triggered(bool checked)
1811
{
1812
    // enable/disble debug messages
1813
    showDebugMessages=checked;
1814
}
216 werner 1815
 
1816
void MainWindow::on_reloadJavaScript_clicked()
1817
{
221 werner 1818
    if (!GlobalSettings::instance()->model())
414 werner 1819
        MSGRETURN("no model available.");
1064 werner 1820
 
1821
    ScriptGlobal::loadScript(ui->scriptActiveScriptFile->text());
767 werner 1822
    ScriptGlobal::scriptOutput = ui->scriptResult;
414 werner 1823
}
216 werner 1824
 
414 werner 1825
void MainWindow::on_selectJavaScript_clicked()
1826
{
1827
    if (!GlobalSettings::instance()->model())
1828
        return;
1829
    QString fileName = Helper::fileDialog("select a Javascript file:");
1830
    if (fileName.isEmpty())
1831
        return;
767 werner 1832
    ScriptGlobal::loadScript(fileName);
1833
 
794 werner 1834
    ui->scriptActiveScriptFile->setText(QString("%1").arg(fileName));
767 werner 1835
    qDebug() << "loaded Javascript file" << fileName;
1836
    ScriptGlobal::scriptOutput = ui->scriptResult;
414 werner 1837
 
216 werner 1838
}
1839
 
1840
void MainWindow::on_scriptCommand_returnPressed()
1841
{
717 werner 1842
    QString command = ui->scriptCommand->text();
1843
    if (ui->scriptCommandHistory->currentText() != command) {
1844
        ui->scriptCommandHistory->insertItem(0, command);
1845
        ui->scriptCommandHistory->setCurrentIndex(0);
1846
    }
716 werner 1847
 
717 werner 1848
    qDebug() << "executing" << command;
294 werner 1849
    try {
767 werner 1850
 
1851
        QString result = ScriptGlobal::executeScript(command);
392 werner 1852
        if (!result.isEmpty()) {
294 werner 1853
            ui->scriptResult->append(result);
392 werner 1854
            qDebug() << result;
1855
        }
294 werner 1856
    } catch(const IException &e) {
575 werner 1857
        Helper::msg(e.message());
294 werner 1858
    }
216 werner 1859
}
225 werner 1860
 
1861
 
239 werner 1862
 
1863
 
254 werner 1864
 
1865
void MainWindow::on_actionOutput_table_description_triggered()
1866
{
1867
    QString txt = GlobalSettings::instance()->outputManager()->wikiFormat();
1868
    QApplication::clipboard()->setText(txt);
1869
    qDebug() << "Description copied to clipboard!";
1870
}
274 werner 1871
 
1872
void MainWindow::on_actionTimers_triggered()
1873
{
360 werner 1874
    LogToWindow l;
274 werner 1875
    DebugTimer::printAllTimers();
1876
}
323 werner 1877
 
1878
void MainWindow::on_actionOnline_ressources_triggered()
1879
{
1880
    QDesktopServices::openUrl(QUrl("http://iland.boku.ac.at/"));
1881
}
1882
 
1883
void MainWindow::on_actionAbout_triggered()
1884
{
1885
    AboutDialog dialog;
1886
    dialog.exec();
1887
}
329 werner 1888
 
1889
 
365 werner 1890
/* Logging and filtering of logging */
1891
void MainWindow::on_pbLogToClipboard_clicked()
1892
{
1893
    // copy content of log window to clipboard
1894
    QApplication::clipboard()->setText(ui->logOutput->toPlainText());
1895
 
1896
}
1897
 
1898
void MainWindow::on_pbLogClearText_clicked()
1899
{
1900
    ui->logOutput->clear();
1901
    ui->logOutput->setProperty("fullText","");
1902
    ui->pbLogFilterClear->setEnabled(false);
1903
}
1904
 
1905
void MainWindow::on_pbFilterExecute_clicked()
1906
{
1907
    QStringList lines;
1908
    QString search_for = ui->logFilterExpression->text();
1909
    if (search_for.isEmpty())
1910
        return;
1911
    QString full_content;
1912
    if (ui->logOutput->property("fullText").toString().isEmpty()) {
1913
        full_content = ui->logOutput->toPlainText();
1914
        ui->logOutput->setProperty("fullText",full_content);
1915
    } else
1916
        full_content = ui->logOutput->property("fullText").toString();
1917
    QStringList debugLines = full_content.split("\n");
1918
    int i=0;
1919
    foreach(const QString &line, debugLines) {
1920
        i++; // line counter
1921
        if (line.contains(search_for))
1922
            lines.push_back(QString("%1: %2").arg(i).arg(line) );
1923
    }
1924
    if (lines.count()>0) {
1925
        ui->logOutput->setPlainText(lines.join("\n"));
1926
    } else {
1927
        ui->logOutput->setPlainText("Search term not found!");
1928
    }
1929
    ui->pbLogFilterClear->setEnabled(true);
1930
}
1931
 
1932
void MainWindow::on_pbLogFilterClear_clicked()
1933
{
1934
    QString text = ui->logOutput->property("fullText").toString();
1935
    if (text.isEmpty())
1936
        return;
392 werner 1937
    //QString sel = ui->logOutput->textCursor().selectedText();
1938
    //int line = sel.toInt();
1939
    int line = atoi(ui->logOutput->textCursor().block().text().toLocal8Bit());
365 werner 1940
    ui->logOutput->setPlainText(text);
1941
    ui->logOutput->setProperty("fullText","");
392 werner 1942
    //int bl = ui->logOutput->document()->findBlockByNumber(line).position();
1943
    ui->logOutput->setTextCursor(QTextCursor(ui->logOutput->document()->findBlockByNumber(line)));
1944
    ui->logOutput->ensureCursorVisible();
365 werner 1945
    ui->pbLogFilterClear->setEnabled(false);
1946
 
1947
}
386 werner 1948
 
1949
void MainWindow::on_actionClearDebugOutput_triggered()
1950
{
1951
    GlobalSettings::instance()->clearDebugLists();
1952
}
414 werner 1953
 
503 werner 1954
 
1955
void MainWindow::on_actionDebug_triggered()
1956
{
1957
    //
1958
    QObject *o = QObject::sender();
1959
    int level = o->property("logLevel").toInt();
1960
    ui->actionDebug->setChecked( level == 0);
1961
    ui->actionInfo->setChecked( level == 1);
1962
    ui->actionWarning->setChecked( level == 2);
1963
    ui->actionError->setChecked( level == 3);
1964
 
1965
    setLogLevel(level);
1966
}
1967
 
573 werner 1968
 
634 werner 1969
 
717 werner 1970
void MainWindow::on_scriptCommandHistory_currentIndexChanged(int index)
716 werner 1971
{
717 werner 1972
    if (index>=0)
1973
        ui->scriptCommand->setText(ui->scriptCommandHistory->itemText(index));
716 werner 1974
}
647 werner 1975
 
716 werner 1976
void MainWindow::writeSettings()
1977
{
1978
    QSettings settings;
1979
    settings.beginGroup("MainWindow");
1980
    settings.setValue("geometry", saveGeometry());
1981
    settings.setValue("windowState", saveState());
1982
    settings.endGroup();
1983
    // javascript commands
1984
    settings.beginWriteArray("javascriptCommands");
1985
    int size = qMin(ui->scriptCommandHistory->count(), 15); // max 15 entries in the history
1986
    for (int i=0;i<size; ++i) {
1987
        settings.setArrayIndex(i);
1988
        settings.setValue("item", ui->scriptCommandHistory->itemText(i));
1989
    }
1990
    settings.endArray();
1991
    settings.beginGroup("project");
1992
    settings.setValue("lastxmlfile", ui->initFileName->text());
1993
    settings.endGroup();
1043 valentin 1994
    //recent files menu qsettings registry save
1995
    settings.beginGroup("recent_files");
1058 werner 1996
    for(int i = 0;i < mRecentFileList.size();i++){
1997
        settings.setValue(QString("file-%1").arg(i),mRecentFileList[i]);
1043 valentin 1998
    }
1999
    settings.endGroup();
716 werner 2000
}
2001
void MainWindow::readSettings()
2002
{
2003
    QSettings::setDefaultFormat(QSettings::IniFormat);
2004
    QCoreApplication::setOrganizationName("iLand");
2005
    QCoreApplication::setOrganizationDomain("iland.boku.ac.at");
2006
    QCoreApplication::setApplicationName("iLand");
2007
    QSettings settings;
2008
    qDebug() << "reading settings from" << settings.fileName();
2009
 
2010
    // window state and
2011
    restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
2012
    restoreState(settings.value("MainWindow/windowState").toByteArray());
2013
 
2014
    // read javascript commands
2015
    int size = settings.beginReadArray("javascriptCommands");
2016
    for (int i=0;i<size; ++i) {
2017
        settings.setArrayIndex(i);
2018
        ui->scriptCommandHistory->addItem(settings.value("item").toString());
2019
    }
2020
    settings.endArray();
1043 valentin 2021
    //recent files menu qsettings registry load
2022
    settings.beginGroup("recent_files");
2023
    for(int i = 0;i < settings.childKeys().size();i++){
2024
       //resize(settings.value("size", QSize(400, 400)).toSize());
1058 werner 2025
        mRecentFileList.append(settings.value(QString("file-%1").arg(i)).toString());
1043 valentin 2026
    }
2027
    for(int i = 0;i < ui->menuRecent_Files->actions().size();i++){
1058 werner 2028
        if(i < mRecentFileList.size()){
2029
            ui->menuRecent_Files->actions()[i]->setText(mRecentFileList[i]);
1043 valentin 2030
            connect(ui->menuRecent_Files->actions()[i],SIGNAL(triggered()),this,SLOT(menuRecent_Files()));
2031
            ui->menuRecent_Files->actions()[i]->setVisible(true);
2032
        }else{
2033
            ui->menuRecent_Files->actions()[i]->setVisible(false);
2034
        }
2035
     }
2036
    settings.endGroup();
716 werner 2037
}
2038
 
732 werner 2039
 
2040
void MainWindow::on_paintGridBox_currentIndexChanged(int index)
2041
{
780 werner 2042
    Q_UNUSED(index);
732 werner 2043
    ui->visOtherGrid->setChecked(true);
2044
}
808 werner 2045
 
2046
void MainWindow::on_actionTest_triggered()
2047
{
2048
    Tests t(this);
2049
    int which = QInputDialog::getInt(this, "Which test",
2050
                                    "which test?\n0: expression speed\n1: tree clear\n" \
2051
                                    "2:kill trees\n3: climate\n4: multiple light automation\n" \
2052
                                    "5: species response\n" \
2053
                                    "6: watercycle\n" \
2054
                                    "7: CSV File\n" \
2055
                                    "8: Xml setters\n" \
2056
                                    "9: random functions\n" \
2057
                                    "10: seed dispersal.\n" \
2058
                                    "11: multiple thread expression\n" \
2059
                                    "12: linearized expressions\n" \
2060
                                    "13: establishment\n" \
2061
                                    "14: GridRunner\n" \
2062
                                     "15: Soil (ICBM/2N)\n" \
2063
                                     "16: load Map \n" \
2064
                                     "17: test DEM \n" \
2065
                                     "18: test fire module \n" \
2066
                                     "19: test wind module\n" \
2067
                                     "20: test rumple index\n" \
876 werner 2068
                                     "21: test FOME setup\n" \
1002 werner 2069
                                     "22: test FOME step\n" \
1067 werner 2070
                                     "23: test debug establishment\n" \
2071
                                     "24: test grid special index hack",-1);
808 werner 2072
    switch (which) {
2073
    case 0: t.speedOfExpression();break;
2074
    case 1: t.clearTrees(); break;
2075
    case 2: t.killTrees(); break;
2076
    case 3: t.climate(); break;
2077
    case 4: t.multipleLightRuns(GlobalSettings::instance()->path("automation.xml", "home"));
2078
    case 5: t.climateResponse(); break;
2079
    case 6: t.testWater(); break;
2080
    case 7: t.testCSVFile(); break;
2081
    case 8: t.testXml(); break;
2082
    case 9: t.testRandom(); break;
2083
    case 10: t.testSeedDispersal(); break;
2084
    case 11: t.testMultithreadExecute(); break;
2085
    case 12: t.testLinearExpressions(); break;
2086
    case 13: t.testEstablishment(); break;
2087
    case 14: t.testGridRunner(); break;
2088
    case 15: t.testSoil(); break;
2089
    case 16: t.testMap(); break;
2090
    case 17: t.testDEM(); break;
2091
    case 18: t.testFire(); break;
2092
    case 19: t.testWind(); break;
2093
    case 20: t.testRumple(); break;
2094
    case 21: t.testFOMEsetup(); break;
876 werner 2095
    case 22: t.testFOMEstep(); break;
1002 werner 2096
    case 23: t.testDbgEstablishment(); break;
1067 werner 2097
    case 24: t.testGridIndexHack(); break;
808 werner 2098
    }
2099
 
2100
}
879 werner 2101
 
2102
void MainWindow::on_pbReloadQml_clicked()
2103
{
2104
//engine()->clearComponentCache();
2105
    //setSource(source());
2106
    if (!mRuler)
2107
        return;
2108
    mRuler->engine()->clearComponentCache();
2109
    mRuler->setSource(mRuler->source());
2110
}
942 werner 2111
 
2112
void MainWindow::on_actionExit_triggered()
2113
{
2114
    if (Helper::question("Do you really want to quit?"))
2115
        close();
2116
}
2117
 
2118
void MainWindow::on_actionOpen_triggered()
2119
{
2120
    QString fileName = Helper::fileDialog("select XML-project file", ui->initFileName->text(), "*.xml");
2121
    if (fileName.isEmpty())
2122
        return;
2123
    ui->initFileName->setText(fileName);
2124
    QString xmlFile = Helper::loadTextFile(ui->initFileName->text());
2125
    ui->iniEdit->setPlainText(xmlFile);
2126
    checkModelState();
2127
 
2128
}
1043 valentin 2129
 
2130
void MainWindow::menuRecent_Files()
2131
{
2132
        QAction* action = dynamic_cast<QAction*>(sender());
1047 werner 2133
        if (action)
2134
            ui->initFileName->setText(action->text());
1043 valentin 2135
}
2136
 
2137
void MainWindow::recentFileMenu(){
1058 werner 2138
    if(mRecentFileList.size() > 9){
2139
        mRecentFileList.removeAt(9);
1043 valentin 2140
    }
1058 werner 2141
    if(mRecentFileList.contains(ui->initFileName->text())){
2142
        mRecentFileList.removeAt(mRecentFileList.indexOf(ui->initFileName->text()));
1043 valentin 2143
     }
1058 werner 2144
    mRecentFileList.prepend(ui->initFileName->text());
1043 valentin 2145
 
2146
    for(int i = 0;i < ui->menuRecent_Files->actions().size();i++){
1058 werner 2147
        if(i < mRecentFileList.size()){
2148
            ui->menuRecent_Files->actions()[i]->setText(mRecentFileList[i]);
1043 valentin 2149
            connect(ui->menuRecent_Files->actions()[i],SIGNAL(triggered()),this,SLOT(menuRecent_Files()));
2150
            ui->menuRecent_Files->actions()[i]->setVisible(true);
2151
        }else{
2152
            ui->menuRecent_Files->actions()[i]->setVisible(false);
2153
        }
2154
     }
2155
}
1046 werner 2156
 
2157
void MainWindow::on_saveFile_clicked()
2158
{
2159
    ui->iniEdit->setVisible(!ui->iniEdit->isVisible());
2160
}
1061 werner 2161
 
2162
void MainWindow::on_lJSShortcuts_linkActivated(const QString &link)
2163
{
2164
    qDebug() << "executing: " << link;
2165
    try {
2166
 
2167
        qDebug() << ScriptGlobal::executeScript(link);
2168
 
2169
    } catch(const IException &e) {
2170
        Helper::msg(e.message());
2171
    }
2172
 
2173
}
1168 werner 2174
 
2175
 
1179 werner 2176
 
2177
 
2178