Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
678 | 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 | |||
20 | #include "consoleshell.h" |
||
21 | |||
22 | #include <QtCore> |
||
1157 | werner | 23 | #include <QtDebug> |
989 | werner | 24 | //#include <QKeyEvent> |
678 | werner | 25 | |
26 | #include "global.h" |
||
27 | #include "model.h" |
||
28 | #include "modelcontroller.h" |
||
1182 | werner | 29 | #include "version.h" |
678 | werner | 30 | |
31 | QTextStream *ConsoleShell::mLogStream = 0; |
||
1087 | werner | 32 | bool ConsoleShell::mFlushLog = false; |
678 | werner | 33 | |
679 | werner | 34 | // a try to really get keyboard strokes in console mode... |
35 | // did not work. |
||
36 | class KeyboardTaker : public QThread |
||
37 | { |
||
38 | public: |
||
39 | void run(); |
||
40 | bool stop; |
||
41 | }; |
||
42 | |||
43 | void KeyboardTaker::run() |
||
44 | { |
||
45 | stop = false; |
||
46 | QTextStream qin(stdin, QFile::ReadOnly); |
||
47 | while (!stop) { |
||
48 | QString input = qin.read(1); |
||
49 | if (!input.isNull()) { |
||
50 | // .. process input |
||
51 | qWarning() << "input:" << input; |
||
52 | } |
||
53 | } |
||
54 | } |
||
55 | |||
678 | werner | 56 | ConsoleShell::ConsoleShell() |
57 | { |
||
58 | } |
||
59 | |||
679 | werner | 60 | /* |
61 | */ |
||
62 | |||
678 | werner | 63 | void ConsoleShell::run() |
64 | { |
||
679 | werner | 65 | |
66 | QString xml_name = QCoreApplication::arguments().at(1); |
||
67 | // get the number of years to run... |
||
68 | bool ok; |
||
69 | int years = QCoreApplication::arguments().at(2).toInt(&ok); |
||
70 | if (years<0 || !ok) { |
||
71 | qDebug() << QCoreApplication::arguments().at(2) << "is an invalid number of years to run!"; |
||
994 | werner | 72 | QCoreApplication::quit(); |
679 | werner | 73 | return; |
74 | } |
||
75 | |||
837 | werner | 76 | if (!QFile::exists(xml_name)) { |
77 | qDebug() << "invalid XML project file: " << xml_name; |
||
994 | werner | 78 | QCoreApplication::quit(); |
837 | werner | 79 | return; |
80 | } |
||
678 | werner | 81 | try { |
82 | |||
83 | ModelController iland_model; |
||
1081 | werner | 84 | GlobalSettings::instance()->setModelController( &iland_model ); |
678 | werner | 85 | QObject::connect(&iland_model, SIGNAL(year(int)),SLOT(runYear(int))); |
86 | iland_model.setFileName(xml_name); |
||
837 | werner | 87 | if (iland_model.hasError()) { |
88 | qWarning() << "!!!! ERROR !!!!"; |
||
89 | qWarning() << iland_model.lastError(); |
||
90 | qWarning() << "!!!! ERROR !!!!"; |
||
994 | werner | 91 | QCoreApplication::quit(); |
837 | werner | 92 | return; |
93 | } |
||
678 | werner | 94 | |
837 | werner | 95 | mParams.clear(); |
96 | if (QCoreApplication::arguments().count()>3) { |
||
97 | qWarning() << "set command line values:"; |
||
98 | for (int i=3;i<QCoreApplication::arguments().count();++i) { |
||
99 | QString line = QCoreApplication::arguments().at(i); |
||
1157 | werner | 100 | line = line.remove(QChar('"')); // drop quotes |
837 | werner | 101 | mParams.append(line); |
1157 | werner | 102 | //qDebug() << qPrintable(line); |
837 | werner | 103 | QString key = line.left(line.indexOf('=')); |
104 | QString value = line.mid(line.indexOf('=')+1); |
||
105 | const_cast<XmlHelper&>(GlobalSettings::instance()->settings()).setNodeValue(key, value); |
||
1157 | werner | 106 | qWarning() << QString("set '%1' to value '%2'. result: '%3'").arg(key).arg(value).arg(GlobalSettings::instance()->settings().value(key)); |
837 | werner | 107 | } |
108 | } |
||
1075 | werner | 109 | setupLogging(); |
110 | |||
678 | werner | 111 | qDebug() << "**************************************************"; |
112 | qDebug() << "*********** iLand console session ********"; |
||
113 | qDebug() << "**************************************************"; |
||
114 | |||
115 | qWarning() << "*** creating model..."; |
||
116 | qWarning() << "**************************************************"; |
||
117 | |||
118 | iland_model.create(); |
||
837 | werner | 119 | if (iland_model.hasError()) { |
120 | qWarning() << "!!!! ERROR !!!!"; |
||
121 | qWarning() << iland_model.lastError(); |
||
122 | qWarning() << "!!!! ERROR !!!!"; |
||
994 | werner | 123 | QCoreApplication::quit(); |
837 | werner | 124 | return; |
125 | } |
||
126 | runJavascript("onCreate"); |
||
678 | werner | 127 | qWarning() << "**************************************************"; |
679 | werner | 128 | qWarning() << "*** running model for" << years << "years"; |
678 | werner | 129 | qWarning() << "**************************************************"; |
130 | |||
679 | werner | 131 | iland_model.run(years + 1); |
837 | werner | 132 | if (iland_model.hasError()) { |
133 | qWarning() << "!!!! ERROR !!!!"; |
||
134 | qWarning() << iland_model.lastError(); |
||
135 | qWarning() << "!!!! ERROR !!!!"; |
||
994 | werner | 136 | QCoreApplication::quit(); |
837 | werner | 137 | return; |
138 | } |
||
139 | runJavascript("onFinish"); |
||
679 | werner | 140 | |
678 | werner | 141 | qWarning() << "**************************************************"; |
142 | qWarning() << "*** model run finished."; |
||
143 | qWarning() << "**************************************************"; |
||
144 | |||
145 | } catch (const IException &e) { |
||
146 | qWarning() << "*** An exception occured ***"; |
||
147 | qWarning() << e.message(); |
||
148 | } |
||
149 | catch (const std::exception &e) { |
||
837 | werner | 150 | qWarning() << "*** An (std)exception occured ***"; |
678 | werner | 151 | qWarning() << e.what(); |
152 | } |
||
153 | QCoreApplication::quit(); |
||
154 | |||
155 | |||
156 | } |
||
157 | |||
158 | void ConsoleShell::runYear(int year) |
||
159 | { |
||
1157 | werner | 160 | printf("%s: simulating year %d ...\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), year-1); |
678 | werner | 161 | } |
162 | |||
1157 | werner | 163 | static QMutex qdebug_mutex; |
780 | werner | 164 | void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) |
678 | werner | 165 | { |
780 | werner | 166 | Q_UNUSED(context); |
167 | QMutexLocker m(&qdebug_mutex); |
||
678 | werner | 168 | |
169 | switch (type) { |
||
1157 | werner | 170 | case QtDebugMsg: |
678 | werner | 171 | *ConsoleShell::logStream() << msg << endl; |
1087 | werner | 172 | if (ConsoleShell::flush()) |
1157 | werner | 173 | ConsoleShell::logStream()->flush(); |
174 | break; |
||
175 | case QtWarningMsg: |
||
678 | werner | 176 | *ConsoleShell::logStream() << msg << endl; |
1087 | werner | 177 | if (ConsoleShell::flush()) |
1157 | werner | 178 | ConsoleShell::logStream()->flush(); |
179 | printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data()); |
||
180 | break; |
||
181 | // available from qt5.5 |
||
182 | // case QtInfoMsg: |
||
183 | // *ConsoleShell::logStream() << msg << endl; |
||
184 | // if (ConsoleShell::flush()) |
||
185 | // ConsoleShell::logStream()->flush(); |
||
186 | // printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data()); |
||
678 | werner | 187 | |
1157 | werner | 188 | // break; |
189 | case QtCriticalMsg: |
||
678 | werner | 190 | *ConsoleShell::logStream() << msg << endl; |
1087 | werner | 191 | if (ConsoleShell::flush()) |
1157 | werner | 192 | ConsoleShell::logStream()->flush(); |
984 | werner | 193 | printf("Critical: %s\n", msg.toLocal8Bit().data()); |
1157 | werner | 194 | break; |
195 | case QtFatalMsg: |
||
678 | werner | 196 | *ConsoleShell::logStream() << msg << endl; |
1087 | werner | 197 | if (ConsoleShell::flush()) |
1157 | werner | 198 | ConsoleShell::logStream()->flush(); |
984 | werner | 199 | printf("Fatal: %s\n", msg.toLocal8Bit().data()); |
1157 | werner | 200 | } |
678 | werner | 201 | } |
202 | |||
203 | |||
204 | void ConsoleShell::setupLogging() |
||
205 | { |
||
206 | if (mLogStream) { |
||
207 | if (mLogStream->device()) |
||
208 | delete mLogStream->device(); |
||
209 | delete mLogStream; |
||
210 | mLogStream = NULL; |
||
211 | } |
||
212 | |||
213 | QString fname = GlobalSettings::instance()->settings().value("system.logging.logFile", "logfile.txt"); |
||
1087 | werner | 214 | mFlushLog = GlobalSettings::instance()->settings().valueBool("system.logging.flush"); |
678 | werner | 215 | QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); |
216 | fname.replace("$date$", timestamp); |
||
217 | fname = GlobalSettings::instance()->path(fname, "log"); |
||
218 | QFile *file = new QFile(fname); |
||
219 | |||
220 | if (!file->open(QIODevice::WriteOnly)) { |
||
221 | qDebug() << "cannot open logfile" << fname; |
||
222 | } else { |
||
223 | qDebug() << "Log output is redirected to logfile" << fname; |
||
224 | mLogStream = new QTextStream(file); |
||
225 | } |
||
780 | werner | 226 | qInstallMessageHandler(myMessageOutput); |
678 | werner | 227 | |
228 | |||
229 | } |
||
230 | |||
837 | werner | 231 | void ConsoleShell::runJavascript(const QString key) |
232 | { |
||
233 | for (int i=0;i<mParams.count(); ++i) { |
||
234 | QString line=mParams[i]; |
||
235 | QString pkey = line.left(line.indexOf('=')); |
||
236 | if (pkey == key) { |
||
237 | QString command = line.mid(line.indexOf('=')+1); |
||
238 | // execute the function |
||
239 | qWarning() << "executing trigger" << key; |
||
240 | qWarning() << GlobalSettings::instance()->executeJavascript(command); |
||
241 | } |
||
242 | } |
||
243 | |||
244 | |||
245 | } |
||
246 |