Rev 1182 | Rev 1217 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1182 | Rev 1204 | ||
---|---|---|---|
1 | Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/ilandc/consoleshell.cpp': |
1 | Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/ilandc/consoleshell.cpp': |
2 | /********************************************************************************************
|
2 | /********************************************************************************************
|
3 | ** iLand - an individual based forest landscape and disturbance model
|
3 | ** iLand - an individual based forest landscape and disturbance model
|
4 | ** http://iland.boku.ac.at
|
4 | ** http://iland.boku.ac.at
|
5 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl
|
5 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl
|
6 | **
|
6 | **
|
7 | ** This program is free software: you can redistribute it and/or modify
|
7 | ** This program is free software: you can redistribute it and/or modify
|
8 | ** it under the terms of the GNU General Public License as published by
|
8 | ** it under the terms of the GNU General Public License as published by
|
9 | ** the Free Software Foundation, either version 3 of the License, or
|
9 | ** the Free Software Foundation, either version 3 of the License, or
|
10 | ** (at your option) any later version.
|
10 | ** (at your option) any later version.
|
11 | **
|
11 | **
|
12 | ** This program is distributed in the hope that it will be useful,
|
12 | ** This program is distributed in the hope that it will be useful,
|
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 | ** GNU General Public License for more details.
|
15 | ** GNU General Public License for more details.
|
16 | **
|
16 | **
|
17 | ** You should have received a copy of the GNU General Public License
|
17 | ** You should have received a copy of the GNU General Public License
|
18 | ** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18 | ** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19 | ********************************************************************************************/
|
19 | ********************************************************************************************/
|
20 | 20 | ||
21 | #include "consoleshell.h"
|
21 | #include "consoleshell.h"
|
22 | 22 | ||
23 | #include <QtCore>
|
23 | #include <QtCore>
|
24 | #include <QtDebug>
|
24 | #include <QtDebug>
|
25 | //#include <QKeyEvent>
|
25 | //#include <QKeyEvent>
|
26 | 26 | ||
27 | #include "global.h"
|
27 | #include "global.h"
|
28 | #include "model.h"
|
28 | #include "model.h"
|
29 | #include "modelcontroller.h"
|
29 | #include "modelcontroller.h"
|
30 | #include "version.h"
|
30 | #include "version.h"
|
31 | 31 | ||
32 | QTextStream *ConsoleShell::mLogStream = 0; |
32 | QTextStream *ConsoleShell::mLogStream = 0; |
33 | bool ConsoleShell::mFlushLog = false; |
33 | bool ConsoleShell::mFlushLog = false; |
34 | 34 | ||
35 | // a try to really get keyboard strokes in console mode...
|
35 | // a try to really get keyboard strokes in console mode...
|
36 | // did not work.
|
36 | // did not work.
|
37 | class KeyboardTaker : public QThread |
37 | class KeyboardTaker : public QThread |
38 | {
|
38 | {
|
39 | public: |
39 | public: |
40 | void run(); |
40 | void run(); |
41 | bool stop; |
41 | bool stop; |
42 | }; |
42 | }; |
43 | 43 | ||
44 | void KeyboardTaker::run() |
44 | void KeyboardTaker::run() |
45 | {
|
45 | {
|
46 | stop = false; |
46 | stop = false; |
47 | QTextStream qin(stdin, QFile::ReadOnly); |
47 | QTextStream qin(stdin, QFile::ReadOnly); |
48 | while (!stop) { |
48 | while (!stop) { |
49 | QString input = qin.read(1); |
49 | QString input = qin.read(1); |
50 | if (!input.isNull()) { |
50 | if (!input.isNull()) { |
51 | // .. process input
|
51 | // .. process input
|
52 | qWarning() << "input:" << input; |
52 | qWarning() << "input:" << input; |
53 | }
|
53 | }
|
54 | }
|
54 | }
|
55 | }
|
55 | }
|
56 | 56 | ||
57 | ConsoleShell::ConsoleShell() |
57 | ConsoleShell::ConsoleShell() |
58 | {
|
58 | {
|
59 | }
|
59 | }
|
60 | 60 | ||
61 | /*
|
61 | /*
|
62 | */
|
62 | */
|
63 | 63 | ||
64 | void ConsoleShell::run() |
64 | void ConsoleShell::run() |
65 | {
|
65 | {
|
66 | 66 | ||
67 | QString xml_name = QCoreApplication::arguments().at(1); |
67 | QString xml_name = QCoreApplication::arguments().at(1); |
68 | // get the number of years to run...
|
68 | // get the number of years to run...
|
69 | bool ok; |
69 | bool ok; |
70 | int years = QCoreApplication::arguments().at(2).toInt(&ok); |
70 | int years = QCoreApplication::arguments().at(2).toInt(&ok); |
71 | if (years<0 || !ok) { |
71 | if (years<0 || !ok) { |
72 | qDebug() << QCoreApplication::arguments().at(2) << "is an invalid number of years to run!"; |
72 | qDebug() << QCoreApplication::arguments().at(2) << "is an invalid number of years to run!"; |
73 | QCoreApplication::quit(); |
73 | QCoreApplication::quit(); |
74 | return; |
74 | return; |
75 | }
|
75 | }
|
76 | 76 | ||
77 | if (!QFile::exists(xml_name)) { |
77 | if (!QFile::exists(xml_name)) { |
78 | qDebug() << "invalid XML project file: " << xml_name; |
78 | qDebug() << "invalid XML project file: " << xml_name; |
79 | QCoreApplication::quit(); |
79 | QCoreApplication::quit(); |
80 | return; |
80 | return; |
81 | }
|
81 | }
|
82 | try { |
82 | try { |
83 | 83 | ||
84 | ModelController iland_model;
|
84 | ModelController iland_model;
|
85 | GlobalSettings::instance()->setModelController( &iland_model ); |
85 | GlobalSettings::instance()->setModelController( &iland_model ); |
86 | QObject::connect(&iland_model, SIGNAL(year(int)),SLOT(runYear(int))); |
86 | QObject::connect(&iland_model, SIGNAL(year(int)),SLOT(runYear(int))); |
87 | iland_model.setFileName(xml_name); |
87 | iland_model.setFileName(xml_name); |
88 | if (iland_model.hasError()) { |
88 | if (iland_model.hasError()) { |
89 | qWarning() << "!!!! ERROR !!!!"; |
89 | qWarning() << "!!!! ERROR !!!!"; |
90 | qWarning() << iland_model.lastError(); |
90 | qWarning() << iland_model.lastError(); |
91 | qWarning() << "!!!! ERROR !!!!"; |
91 | qWarning() << "!!!! ERROR !!!!"; |
92 | QCoreApplication::quit(); |
92 | QCoreApplication::quit(); |
93 | return; |
93 | return; |
94 | }
|
94 | }
|
95 | 95 | ||
96 | mParams.clear(); |
96 | mParams.clear(); |
97 | if (QCoreApplication::arguments().count()>3) { |
97 | if (QCoreApplication::arguments().count()>3) { |
98 | qWarning() << "set command line values:"; |
98 | qWarning() << "set command line values:"; |
99 | for (int i=3;i<QCoreApplication::arguments().count();++i) { |
99 | for (int i=3;i<QCoreApplication::arguments().count();++i) { |
100 | QString line = QCoreApplication::arguments().at(i); |
100 | QString line = QCoreApplication::arguments().at(i); |
101 | line = line.remove(QChar('"')); // drop quotes |
101 | line = line.remove(QChar('"')); // drop quotes |
102 | mParams.append(line); |
102 | mParams.append(line); |
103 | //qDebug() << qPrintable(line);
|
103 | //qDebug() << qPrintable(line);
|
104 | QString key = line.left(line.indexOf('=')); |
104 | QString key = line.left(line.indexOf('=')); |
105 | QString value = line.mid(line.indexOf('=')+1); |
105 | QString value = line.mid(line.indexOf('=')+1); |
106 | const_cast<XmlHelper&>(GlobalSettings::instance()->settings()).setNodeValue(key, value); |
106 | const_cast<XmlHelper&>(GlobalSettings::instance()->settings()).setNodeValue(key, value); |
107 | qWarning() << QString("set '%1' to value '%2'. result: '%3'").arg(key).arg(value).arg(GlobalSettings::instance()->settings().value(key)); |
107 | qWarning() << QString("set '%1' to value '%2'. result: '%3'").arg(key).arg(value).arg(GlobalSettings::instance()->settings().value(key)); |
108 | }
|
108 | }
|
109 | }
|
109 | }
|
110 | setupLogging(); |
110 | setupLogging(); |
111 | 111 | ||
112 | qDebug() << "**************************************************"; |
112 | qDebug() << "**************************************************"; |
113 | qDebug() << "*********** iLand console session ********"; |
113 | qDebug() << "*********** iLand console session ********"; |
114 | qDebug() << "**************************************************"; |
- | |
115 | qDebug() << "started at: " << QDateTime::currentDateTime().toString("hh:mm:ss"); |
- | |
116 | qDebug() << "iLand " << currentVersion() << " (" << svnRevision() << ")"; |
- | |
117 | qDebug() << "**************************************************"; |
114 | qDebug() << "**************************************************"; |
118 | 115 | ||
119 | qWarning() << "*** creating model..."; |
116 | qWarning() << "*** creating model..."; |
120 | qWarning() << "**************************************************"; |
117 | qWarning() << "**************************************************"; |
121 | 118 | ||
122 | iland_model.create(); |
119 | iland_model.create(); |
123 | if (iland_model.hasError()) { |
120 | if (iland_model.hasError()) { |
124 | qWarning() << "!!!! ERROR !!!!"; |
121 | qWarning() << "!!!! ERROR !!!!"; |
125 | qWarning() << iland_model.lastError(); |
122 | qWarning() << iland_model.lastError(); |
126 | qWarning() << "!!!! ERROR !!!!"; |
123 | qWarning() << "!!!! ERROR !!!!"; |
127 | QCoreApplication::quit(); |
124 | QCoreApplication::quit(); |
128 | return; |
125 | return; |
129 | }
|
126 | }
|
130 | runJavascript("onCreate"); |
127 | runJavascript("onCreate"); |
131 | qWarning() << "**************************************************"; |
128 | qWarning() << "**************************************************"; |
132 | qWarning() << "*** running model for" << years << "years"; |
129 | qWarning() << "*** running model for" << years << "years"; |
133 | qWarning() << "**************************************************"; |
130 | qWarning() << "**************************************************"; |
134 | 131 | ||
135 | iland_model.run(years + 1); |
132 | iland_model.run(years + 1); |
136 | if (iland_model.hasError()) { |
133 | if (iland_model.hasError()) { |
137 | qWarning() << "!!!! ERROR !!!!"; |
134 | qWarning() << "!!!! ERROR !!!!"; |
138 | qWarning() << iland_model.lastError(); |
135 | qWarning() << iland_model.lastError(); |
139 | qWarning() << "!!!! ERROR !!!!"; |
136 | qWarning() << "!!!! ERROR !!!!"; |
140 | QCoreApplication::quit(); |
137 | QCoreApplication::quit(); |
141 | return; |
138 | return; |
142 | }
|
139 | }
|
143 | runJavascript("onFinish"); |
140 | runJavascript("onFinish"); |
144 | 141 | ||
145 | qWarning() << "**************************************************"; |
142 | qWarning() << "**************************************************"; |
146 | qWarning() << "*** model run finished."; |
143 | qWarning() << "*** model run finished."; |
147 | qWarning() << "**************************************************"; |
144 | qWarning() << "**************************************************"; |
148 | 145 | ||
149 | } catch (const IException &e) { |
146 | } catch (const IException &e) { |
150 | qWarning() << "*** An exception occured ***"; |
147 | qWarning() << "*** An exception occured ***"; |
151 | qWarning() << e.message(); |
148 | qWarning() << e.message(); |
152 | }
|
149 | }
|
153 | catch (const std::exception &e) { |
150 | catch (const std::exception &e) { |
154 | qWarning() << "*** An (std)exception occured ***"; |
151 | qWarning() << "*** An (std)exception occured ***"; |
155 | qWarning() << e.what(); |
152 | qWarning() << e.what(); |
156 | }
|
153 | }
|
157 | QCoreApplication::quit(); |
154 | QCoreApplication::quit(); |
158 | 155 | ||
159 | 156 | ||
160 | }
|
157 | }
|
161 | 158 | ||
162 | void ConsoleShell::runYear(int year) |
159 | void ConsoleShell::runYear(int year) |
163 | {
|
160 | {
|
164 | printf("%s: simulating year %d ...\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), year-1); |
161 | printf("%s: simulating year %d ...\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), year-1); |
165 | }
|
162 | }
|
166 | 163 | ||
167 | static QMutex qdebug_mutex; |
164 | static QMutex qdebug_mutex; |
168 | void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) |
165 | void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) |
169 | {
|
166 | {
|
170 | Q_UNUSED(context); |
167 | Q_UNUSED(context); |
171 | QMutexLocker m(&qdebug_mutex); |
168 | QMutexLocker m(&qdebug_mutex); |
172 | 169 | ||
173 | switch (type) { |
170 | switch (type) { |
174 | case QtDebugMsg: |
171 | case QtDebugMsg: |
175 | *ConsoleShell::logStream() << msg << endl; |
172 | *ConsoleShell::logStream() << msg << endl; |
176 | if (ConsoleShell::flush()) |
173 | if (ConsoleShell::flush()) |
177 | ConsoleShell::logStream()->flush(); |
174 | ConsoleShell::logStream()->flush(); |
178 | break; |
175 | break; |
179 | case QtWarningMsg: |
176 | case QtWarningMsg: |
180 | *ConsoleShell::logStream() << msg << endl; |
177 | *ConsoleShell::logStream() << msg << endl; |
181 | if (ConsoleShell::flush()) |
178 | if (ConsoleShell::flush()) |
182 | ConsoleShell::logStream()->flush(); |
179 | ConsoleShell::logStream()->flush(); |
183 | printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data()); |
180 | printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data()); |
184 | break; |
181 | break; |
185 | // available from qt5.5
|
182 | // available from qt5.5
|
186 | // case QtInfoMsg:
|
183 | // case QtInfoMsg:
|
187 | // *ConsoleShell::logStream() << msg << endl;
|
184 | // *ConsoleShell::logStream() << msg << endl;
|
188 | // if (ConsoleShell::flush())
|
185 | // if (ConsoleShell::flush())
|
189 | // ConsoleShell::logStream()->flush();
|
186 | // ConsoleShell::logStream()->flush();
|
190 | // printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data());
|
187 | // printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data());
|
191 | 188 | ||
192 | // break;
|
189 | // break;
|
193 | case QtCriticalMsg: |
190 | case QtCriticalMsg: |
194 | *ConsoleShell::logStream() << msg << endl; |
191 | *ConsoleShell::logStream() << msg << endl; |
195 | if (ConsoleShell::flush()) |
192 | if (ConsoleShell::flush()) |
196 | ConsoleShell::logStream()->flush(); |
193 | ConsoleShell::logStream()->flush(); |
197 | printf("Critical: %s\n", msg.toLocal8Bit().data()); |
194 | printf("Critical: %s\n", msg.toLocal8Bit().data()); |
198 | break; |
195 | break; |
199 | case QtFatalMsg: |
196 | case QtFatalMsg: |
200 | *ConsoleShell::logStream() << msg << endl; |
197 | *ConsoleShell::logStream() << msg << endl; |
201 | if (ConsoleShell::flush()) |
198 | if (ConsoleShell::flush()) |
202 | ConsoleShell::logStream()->flush(); |
199 | ConsoleShell::logStream()->flush(); |
203 | printf("Fatal: %s\n", msg.toLocal8Bit().data()); |
200 | printf("Fatal: %s\n", msg.toLocal8Bit().data()); |
204 | }
|
201 | }
|
205 | }
|
202 | }
|
206 | 203 | ||
207 | 204 | ||
208 | void ConsoleShell::setupLogging() |
205 | void ConsoleShell::setupLogging() |
209 | {
|
206 | {
|
210 | if (mLogStream) { |
207 | if (mLogStream) { |
211 | if (mLogStream->device()) |
208 | if (mLogStream->device()) |
212 | delete mLogStream->device(); |
209 | delete mLogStream->device(); |
213 | delete mLogStream; |
210 | delete mLogStream; |
214 | mLogStream = NULL; |
211 | mLogStream = NULL; |
215 | }
|
212 | }
|
216 | 213 | ||
217 | QString fname = GlobalSettings::instance()->settings().value("system.logging.logFile", "logfile.txt"); |
214 | QString fname = GlobalSettings::instance()->settings().value("system.logging.logFile", "logfile.txt"); |
218 | mFlushLog = GlobalSettings::instance()->settings().valueBool("system.logging.flush"); |
215 | mFlushLog = GlobalSettings::instance()->settings().valueBool("system.logging.flush"); |
219 | QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); |
216 | QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); |
220 | fname.replace("$date$", timestamp); |
217 | fname.replace("$date$", timestamp); |
221 | fname = GlobalSettings::instance()->path(fname, "log"); |
218 | fname = GlobalSettings::instance()->path(fname, "log"); |
222 | QFile *file = new QFile(fname); |
219 | QFile *file = new QFile(fname); |
223 | 220 | ||
224 | if (!file->open(QIODevice::WriteOnly)) { |
221 | if (!file->open(QIODevice::WriteOnly)) { |
225 | qDebug() << "cannot open logfile" << fname; |
222 | qDebug() << "cannot open logfile" << fname; |
226 | } else { |
223 | } else { |
227 | qDebug() << "Log output is redirected to logfile" << fname; |
224 | qDebug() << "Log output is redirected to logfile" << fname; |
228 | mLogStream = new QTextStream(file); |
225 | mLogStream = new QTextStream(file); |
229 | }
|
226 | }
|
230 | qInstallMessageHandler(myMessageOutput); |
227 | qInstallMessageHandler(myMessageOutput); |
231 | 228 | ||
232 | 229 | ||
233 | }
|
230 | }
|
234 | 231 | ||
235 | void ConsoleShell::runJavascript(const QString key) |
232 | void ConsoleShell::runJavascript(const QString key) |
236 | {
|
233 | {
|
237 | for (int i=0;i<mParams.count(); ++i) { |
234 | for (int i=0;i<mParams.count(); ++i) { |
238 | QString line=mParams[i]; |
235 | QString line=mParams[i]; |
239 | QString pkey = line.left(line.indexOf('=')); |
236 | QString pkey = line.left(line.indexOf('=')); |
240 | if (pkey == key) { |
237 | if (pkey == key) { |
241 | QString command = line.mid(line.indexOf('=')+1); |
238 | QString command = line.mid(line.indexOf('=')+1); |
242 | // execute the function
|
239 | // execute the function
|
243 | qWarning() << "executing trigger" << key; |
240 | qWarning() << "executing trigger" << key; |
244 | qWarning() << GlobalSettings::instance()->executeJavascript(command); |
241 | qWarning() << GlobalSettings::instance()->executeJavascript(command); |
245 | }
|
242 | }
|
246 | }
|
243 | }
|
247 | 244 | ||
248 | 245 | ||
249 | }
|
246 | }
|
250 | 247 | ||
251 | 248 |