1 /*****************************************************************************
2 * *
3 * Elmer, A Finite Element Software for Multiphysical Problems *
4 * *
5 * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program (in file fem/GPL-2); if not, write to the *
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 *****************************************************************************/
23
24 /*****************************************************************************
25 * *
26 * ElmerGUI solverlogwindow *
27 * *
28 *****************************************************************************
29 * *
30 * Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31 * Email: Juha.Ruokolainen@csc.fi *
32 * Web: http://www.csc.fi/elmer *
33 * Address: CSC - IT Center for Science Ltd. *
34 * Keilaranta 14 *
35 * 02101 Espoo, Finland *
36 * *
37 * Original Date: 15 Mar 2008 *
38 * *
39 *****************************************************************************/
40
41 #include "solverlogwindow.h"
42 #include "mainwindow.h"
43 #include <QtGui>
44 #include <iostream>
45
46 #if WITH_QT5
47 #include <QPrintDialog>
48 #include <QPrinter>
49 #include <QtWidgets>
50 #endif
51
52 using namespace std;
53
SolverLogHighlighter(int type,QTextDocument * parent)54 SolverLogHighlighter::SolverLogHighlighter(int type, QTextDocument *parent)
55 : QSyntaxHighlighter(parent) {
56
57 if (type != SOLVERLOG_HIGHLIGHTING_LIGHT &&
58 type != SOLVERLOG_HIGHLIGHTING_DARK)
59 return;
60
61 QColor yellow = QColor(161, 117, 0);
62 QColor orange = QColor(183, 55, 22);
63 QColor red = QColor(200, 30, 27);
64 QColor magenta = QColor(191, 34, 110);
65 QColor violet = QColor(88, 93, 176);
66 QColor blue = QColor(18, 99, 190);
67 QColor cyan = QColor(22, 141, 132);
68 QColor green = QColor(113, 113, 0);
69
70 if (type == SOLVERLOG_HIGHLIGHTING_DARK) {
71 yellow = QColor(201, 157, 20);
72 orange = QColor(223, 95, 42);
73 red = QColor(240, 70, 67);
74 magenta = QColor(231, 74, 150);
75 violet = QColor(128, 133, 216);
76 blue = QColor(58, 159, 250);
77 cyan = QColor(62, 181, 172);
78 green = QColor(133, 173, 0);
79 }
80
81 QColor cBlock = blue;
82 QColor cQuotation = orange;
83
84 QColor cSuffix = red;
85 QColor cKeyword = yellow;
86 QColor cComment = green;
87 QColor cValue = blue;
88
89 HighlightingRule rule;
90
91 keywordFormat.setForeground(cKeyword);
92 rule.pattern = QRegExp("^(.*)\\bWARNING\\b(.*)$", Qt::CaseInsensitive);
93 rule.format = keywordFormat;
94 highlightingRules.append(rule);
95
96 suffixFormat.setForeground(cSuffix);
97 rule.pattern = QRegExp("^(.*)\\bERROR\\b(.*)$", Qt::CaseInsensitive);
98 rule.format = suffixFormat;
99 highlightingRules.append(rule);
100
101 commentFormat.setForeground(cComment);
102 rule.pattern =
103 QRegExp("^(.*) Elmer Solver: ALL DONE (.*)$", Qt::CaseSensitive);
104 rule.format = commentFormat;
105 highlightingRules.append(rule);
106
107 commentFormat.setForeground(cComment);
108 QStringList patterns;
109 patterns << "^(.*) Elmer Solver: ALL DONE (.*)$"
110 << "^(.*)ElmerSolver: The end(.*)$"
111 << "^(.*)SOLVER TOTAL TIME(.*)$"
112 << "^(.*)ELMER SOLVER FINISHED AT:(.*)$";
113 foreach (const QString &pattern, patterns) {
114 rule.pattern = QRegExp(pattern, Qt::CaseInsensitive);
115 rule.format = commentFormat;
116 highlightingRules.append(rule);
117 }
118
119 valueFormat.setForeground(cValue);
120 patterns.clear();
121 patterns << "^(.*)\\b(\\S)*.ep\\b(.*)$";
122 foreach (const QString &pattern, patterns) {
123 rule.pattern = QRegExp(pattern, Qt::CaseInsensitive);
124 rule.format = valueFormat;
125 highlightingRules.append(rule);
126 }
127 }
128
highlightBlock(const QString & text)129 void SolverLogHighlighter::highlightBlock(const QString &text) {
130 foreach (const HighlightingRule &rule, highlightingRules) {
131 QRegExp expression(rule.pattern);
132 int index = expression.indexIn(text);
133 while (index >= 0) {
134 int length = expression.matchedLength();
135 setFormat(index, length, rule.format);
136 index = expression.indexIn(text, index + length);
137 }
138 }
139 }
140
SolverLogWindow(QWidget * parent)141 SolverLogWindow::SolverLogWindow(QWidget *parent) : QMainWindow(parent) {
142 setWindowFlags(Qt::Window);
143
144 textEdit = new QTextEdit;
145 textEdit->setLineWrapMode(QTextEdit::NoWrap);
146
147 setCentralWidget(textEdit);
148
149 lineEdit = new QLineEdit;
150 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(findSlot()));
151
152 createActions();
153 createMenus();
154 createToolBars();
155 createStatusBar();
156
157 firstTime = true;
158 found = false;
159
160 setWindowTitle(tr("Solver Log"));
161 setWindowIcon(QIcon(":/icons/Mesh3D.png"));
162
163 highlighter = NULL;
164
165 QString strFont =
166 ((MainWindow *)parent)
167 ->settings_value(QString("solverlogWindow/font"), QString(""))
168 .toString();
169 QFont font;
170 if (!strFont.isEmpty() && font.fromString(strFont)) {
171 font.setFixedPitch(true);
172 textEdit->setFont(font);
173 lineEdit->setFont(font);
174 }
175
176 int syntaxHighlighting =
177 ((MainWindow *)parent)
178 ->settings_value(QString("solverlogWindow/highlighting"),
179 SOLVERLOG_HIGHLIGHTING_NONE)
180 .toInt();
181 if (syntaxHighlighting == SOLVERLOG_HIGHLIGHTING_NONE) {
182 highlightingNoneSlot();
183 } else if (syntaxHighlighting == SOLVERLOG_HIGHLIGHTING_LIGHT) {
184 highlightingLightSlot();
185 } else if (syntaxHighlighting == SOLVERLOG_HIGHLIGHTING_DARK) {
186 highlightingDarkSlot();
187 }
188 }
189
~SolverLogWindow()190 SolverLogWindow::~SolverLogWindow() {}
191
getTextEdit(void)192 QTextEdit *SolverLogWindow::getTextEdit(void) { return this->textEdit; }
193
setFirstTime(bool b)194 void SolverLogWindow::setFirstTime(bool b) { this->firstTime = b; }
195
setFound(bool b)196 void SolverLogWindow::setFound(bool b) { this->found = b; }
197
minimumSizeHint() const198 QSize SolverLogWindow::minimumSizeHint() const { return QSize(64, 64); }
199
sizeHint() const200 QSize SolverLogWindow::sizeHint() const { return QSize(640, 640); }
201
createActions()202 void SolverLogWindow::createActions() {
203 newAct = new QAction(QIcon(":/icons/document-new.png"), tr("&New"), this);
204 newAct->setShortcut(tr("Ctrl+N"));
205 newAct->setStatusTip(tr("New text document"));
206 connect(newAct, SIGNAL(triggered()), this, SLOT(newSlot()));
207
208 openAct =
209 new QAction(QIcon(":/icons/document-open.png"), tr("&Open..."), this);
210 openAct->setShortcut(tr("Ctrl+O"));
211 openAct->setStatusTip(tr("Open text file"));
212 connect(openAct, SIGNAL(triggered()), this, SLOT(openSlot()));
213
214 saveAct =
215 new QAction(QIcon(":/icons/document-save.png"), tr("&Save as..."), this);
216 saveAct->setShortcut(tr("Ctrl+S"));
217 saveAct->setStatusTip(tr("Save text file"));
218 connect(saveAct, SIGNAL(triggered()), this, SLOT(saveSlot()));
219
220 printAct =
221 new QAction(QIcon(":/icons/document-print.png"), tr("&Print..."), this);
222 printAct->setShortcut(tr("Ctrl+P"));
223 printAct->setStatusTip(tr("Print document"));
224 connect(printAct, SIGNAL(triggered()), this, SLOT(printSlot()));
225
226 exitAct =
227 new QAction(QIcon(":/icons/application-exit.png"), tr("&Quit"), this);
228 exitAct->setShortcut(tr("Ctrl+Q"));
229 exitAct->setStatusTip(tr("Quit editor"));
230 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
231
232 cutAct = new QAction(QIcon(":/icons/edit-cut.png"), tr("Cu&t"), this);
233 cutAct->setShortcut(tr("Ctrl+X"));
234 cutAct->setStatusTip(tr("Cut the current selection to clipboard"));
235 connect(cutAct, SIGNAL(triggered()), this->textEdit, SLOT(cut()));
236
237 copyAct = new QAction(QIcon(":/icons/edit-copy.png"), tr("&Copy"), this);
238 copyAct->setShortcut(tr("Ctrl+C"));
239 copyAct->setStatusTip(tr("Copy the current selection to clipboard"));
240 connect(copyAct, SIGNAL(triggered()), this->textEdit, SLOT(copy()));
241
242 pasteAct = new QAction(QIcon(":/icons/edit-paste.png"), tr("&Paste"), this);
243 pasteAct->setShortcut(tr("Ctrl+V"));
244 pasteAct->setStatusTip(tr("Paste clipboard into the current selection"));
245 connect(pasteAct, SIGNAL(triggered()), this->textEdit, SLOT(paste()));
246
247 findAct = new QAction(QIcon(":/icons/edit-find.png"), tr("&Find"), this);
248 findAct->setShortcut(tr("Ctrl+F"));
249 findAct->setStatusTip(tr("Find text in document"));
250 connect(findAct, SIGNAL(triggered()), this, SLOT(findSlot()));
251
252 fontAct = new QAction(QIcon(""), tr("&Font"), this);
253 findAct->setStatusTip(tr("Select font"));
254 connect(fontAct, SIGNAL(triggered()), this, SLOT(fontSlot()));
255
256 highlightingNoneAct = new QAction(QIcon(""), tr("&None"), this);
257 highlightingNoneAct->setStatusTip(tr("No highlighting"));
258 highlightingNoneAct->setCheckable(true);
259 connect(highlightingNoneAct, SIGNAL(triggered()), this,
260 SLOT(highlightingNoneSlot()));
261
262 highlightingLightAct = new QAction(QIcon(""), tr(" &Light"), this);
263 highlightingLightAct->setStatusTip(tr("Highlight in light theme"));
264 highlightingLightAct->setCheckable(true);
265 connect(highlightingLightAct, SIGNAL(triggered()), this,
266 SLOT(highlightingLightSlot()));
267
268 highlightingDarkAct = new QAction(QIcon(""), tr(" &Dark"), this);
269 highlightingDarkAct->setStatusTip(tr("Highlight in dark theme"));
270 highlightingDarkAct->setCheckable(true);
271 connect(highlightingDarkAct, SIGNAL(triggered()), this,
272 SLOT(highlightingDarkSlot()));
273 }
274
createMenus()275 void SolverLogWindow::createMenus() {
276 fileMenu = menuBar()->addMenu(tr("&File"));
277 fileMenu->addAction(newAct);
278 fileMenu->addAction(openAct);
279 fileMenu->addAction(saveAct);
280 fileMenu->addSeparator();
281 fileMenu->addAction(printAct);
282 fileMenu->addSeparator();
283 fileMenu->addAction(exitAct);
284
285 editMenu = menuBar()->addMenu(tr("&Edit"));
286 editMenu->addAction(cutAct);
287 editMenu->addAction(copyAct);
288 editMenu->addAction(pasteAct);
289 editMenu->addSeparator();
290 editMenu->addAction(findAct);
291
292 preferenceMenu = menuBar()->addMenu(tr("&Preference"));
293 preferenceMenu->addAction(fontAct);
294 highlightingMenu = preferenceMenu->addMenu(tr("&Syntax highlighting"));
295 highlightingMenu->addAction(highlightingNoneAct);
296 highlightingMenu->addAction(highlightingLightAct);
297 highlightingMenu->addAction(highlightingDarkAct);
298 }
299
createToolBars()300 void SolverLogWindow::createToolBars() {
301 fileToolBar = addToolBar(tr("&File"));
302 fileToolBar->addAction(newAct);
303 fileToolBar->addAction(openAct);
304 fileToolBar->addAction(saveAct);
305 fileToolBar->addAction(printAct);
306
307 editToolBar = addToolBar(tr("&Edit"));
308 editToolBar->addAction(cutAct);
309 editToolBar->addAction(copyAct);
310 editToolBar->addAction(pasteAct);
311 editToolBar->addSeparator();
312 editToolBar->addWidget(lineEdit);
313 editToolBar->addAction(findAct);
314 }
315
createStatusBar()316 void SolverLogWindow::createStatusBar() {
317 statusBar()->showMessage(tr("Ready"));
318 }
319
newSlot()320 void SolverLogWindow::newSlot() {
321 textEdit->clear();
322
323 firstTime = true;
324 found = false;
325
326 statusBar()->showMessage(tr("Ready"));
327 }
328
openSlot()329 void SolverLogWindow::openSlot() {
330 QString fileName;
331
332 fileName = QFileDialog::getOpenFileName(this, tr("Open text file"));
333
334 if (fileName.isEmpty())
335 return;
336
337 QFile file;
338 file.setFileName(fileName);
339 if (!file.open(QIODevice::ReadOnly))
340 return;
341
342 QTextStream inputStream(&file);
343
344 statusBar()->showMessage(tr("Opening file..."));
345
346 textEdit->clear();
347
348 QString line = inputStream.readAll();
349
350 file.close();
351
352 textEdit->append(line);
353
354 firstTime = true;
355 found = false;
356
357 statusBar()->showMessage(tr("Ready"));
358 }
359
saveSlot()360 void SolverLogWindow::saveSlot() {
361 QString fileName;
362
363 fileName = QFileDialog::getSaveFileName(this, tr("Save text file"));
364
365 if (fileName.isEmpty())
366 return;
367
368 QFile file;
369 file.setFileName(fileName);
370 if (!file.open(QIODevice::WriteOnly))
371 return;
372
373 QTextStream outputStream(&file);
374
375 statusBar()->showMessage(tr("Saving file..."));
376
377 outputStream << textEdit->toPlainText();
378
379 file.close();
380
381 statusBar()->showMessage(tr("Ready"));
382 }
383
printSlot()384 void SolverLogWindow::printSlot() {
385 QTextDocument *document = textEdit->document();
386 QPrinter printer;
387
388 QPrintDialog *printDialog = new QPrintDialog(&printer, this);
389 if (printDialog->exec() != QDialog::Accepted)
390 return;
391
392 statusBar()->showMessage(tr("Printing..."));
393
394 document->print(&printer);
395
396 statusBar()->showMessage(tr("Ready"));
397 }
398
findSlot()399 void SolverLogWindow::findSlot() {
400 QString searchString = lineEdit->text().trimmed();
401 QTextDocument *document = textEdit->document();
402
403 if (!firstTime && found)
404 document->undo();
405
406 found = false;
407
408 if (searchString == "") {
409 QMessageBox::information(this, tr("Empty string"),
410 "Please enter a string in the "
411 "line edit box in the tool bar");
412 } else {
413
414 QTextCursor highlightCursor(document);
415 QTextCursor cursor(document);
416
417 cursor.beginEditBlock();
418
419 QTextCharFormat plainFormat(highlightCursor.charFormat());
420 QTextCharFormat colorFormat = plainFormat;
421 colorFormat.setForeground(Qt::red);
422 colorFormat.setFontWeight(QFont::Bold);
423
424 while (!highlightCursor.isNull() && !highlightCursor.atEnd()) {
425 highlightCursor = document->find(searchString, highlightCursor);
426
427 if (!highlightCursor.isNull()) {
428 found = true;
429 highlightCursor.mergeCharFormat(colorFormat);
430 }
431 }
432
433 cursor.endEditBlock();
434 firstTime = false;
435
436 if (!found)
437 QMessageBox::information(this, tr("String not found"),
438 "The string was not found in the document");
439 }
440
441 statusBar()->showMessage(tr("Ready"));
442 }
443
fontSlot()444 void SolverLogWindow::fontSlot() {
445 bool ok;
446 QFont font = QFontDialog::getFont(&ok, textEdit->font());
447 if (ok) {
448 font.setFixedPitch(true);
449 textEdit->setFont(font);
450 lineEdit->setFont(font);
451 }
452 ((MainWindow *)parent())
453 ->settings_setValue(QString("solverlogWindow/font"), font.toString());
454 }
highlightingNoneSlot()455 void SolverLogWindow::highlightingNoneSlot() {
456 QString style = "";
457 setStyleSheet(style);
458 delete highlighter;
459 highlighter = NULL;
460 ((MainWindow *)parent())
461 ->settings_setValue(QString("solverlogWindow/highlighting"),
462 SOLVERLOG_HIGHLIGHTING_NONE);
463 highlightingNoneAct->setChecked(true);
464 highlightingLightAct->setChecked(false);
465 highlightingDarkAct->setChecked(false);
466 }
467
highlightingLightSlot()468 void SolverLogWindow::highlightingLightSlot() {
469 QString style = "QTextEdit { color: #384e55; background: #fffdf6}";
470 setStyleSheet(style);
471 delete highlighter;
472 highlighter = new SolverLogHighlighter(SOLVERLOG_HIGHLIGHTING_LIGHT,
473 textEdit->document());
474 ((MainWindow *)parent())
475 ->settings_setValue(QString("solverlogWindow/highlighting"),
476 SOLVERLOG_HIGHLIGHTING_LIGHT);
477 highlightingNoneAct->setChecked(false);
478 highlightingLightAct->setChecked(true);
479 highlightingDarkAct->setChecked(false);
480 }
481
highlightingDarkSlot()482 void SolverLogWindow::highlightingDarkSlot() {
483 QString style = "QTextEdit { color: #c3b1b1; background: #000814}";
484 setStyleSheet(style);
485 delete highlighter;
486 highlighter = new SolverLogHighlighter(SOLVERLOG_HIGHLIGHTING_DARK,
487 textEdit->document());
488 ((MainWindow *)parent())
489 ->settings_setValue(QString("solverlogWindow/highlighting"),
490 SOLVERLOG_HIGHLIGHTING_DARK);
491 highlightingNoneAct->setChecked(false);
492 highlightingLightAct->setChecked(false);
493 highlightingDarkAct->setChecked(true);
494 }