tuchulcha  0.10.1
Graphical Workflow Configuration Editor
LogDecorators.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011 Jens-Malte Gottfried
2 
3  This file is part of Tuchulcha.
4 
5  Tuchulcha is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  Tuchulcha is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with Tuchulcha. If not, see <http://www.gnu.org/licenses/>.
17  */
25 #include "LogDecorators.h"
26 #include "FileManager.h"
27 
28 #include <QApplication>
29 #include <QDir>
30 #include <QSettings>
31 #include <QMessageBox>
32 #include <QStandardItemModel>
33 #include <QTableView>
34 #include <QHeaderView>
35 
36 #include <QDebug>
37 
38 // -------------------------- Decorator ----------------------------------
39 LogDecorators::Decorator::Decorator() :
40  debugOutput(true) {
41 }
42 
43 LogDecorators::Decorator::~Decorator() {
44 }
45 
47 }
48 
50  return QString::null;
51 }
52 
54  return QString::null;
55 }
56 
58  return QString::null;
59 }
60 
61 bool LogDecorators::Decorator::ready(QWidget*) const {
62  return true;
63 }
64 
65 QStringList LogDecorators::Decorator::postStartCommands(QWidget*) const {
66  return QStringList();
67 }
68 
70 }
71 
73  return 0;
74 }
75 
77  return QString();
78 }
79 
80 // --------------------------- update ------------------------------------
82  return tr("Plugin Information Update");
83 }
84 
85 QString LogDecorators::Update::desc() const {
86  return tr("Output of update process:");
87 }
88 
89 QStringList LogDecorators::Update::arguments() const {
90  QSettings settings;
91  QStringList args;
92  args << "--quiet";
93  if (!settings.value("delayExecution",false).toBool()) {
94  args << "--non-interactive" << "update";
95  }
96  return args;
97 }
98 
99 QStringList LogDecorators::Update::postStartCommands(QWidget* pp) const {
100  QSettings settings;
101  QStringList cmds;
102  if (settings.value("delayExecution",false).toBool()) {
103  QMessageBox::information(
104  pp,
105  tr("wait before plugin update"),
106  tr(
107  "Waiting because <em>delayExecution</em> option set. "
108  "You can now attach your debugger to the update process. "
109  "Update will be started, when you close this message box."
110  )
111  );
112  cmds << "update" << "quit";
113  }
114  return cmds;
115 }
116 
118  return QDir::home().absoluteFilePath("update-modules.log");
119 }
120 
123  .absoluteFilePath("updateLog.txt");
124 }
125 
126 LogDecorators::Update::Update() :
127  _curStatus(Invalid), _result(0), _view(new QTableView),
128  _ttFont(QFont("fixed")), _sfFont(QFont("sans"))
129 {
130  QString p = "\\(\\w+\\)\\s+"; // prefix
131  _fileRegex = QRegExp(p+"File: (.*)");
132  _passRegex = QRegExp(p+"Created Instance \"\\w+\" of the plugin \"(.+)\".*");
133  _finishRegex = QRegExp(p+"Successfully unloaded plugin \"(.+)\".*");
134  _noPluginRegex = QRegExp(p+"\"(.+)\" is no charon plugin.*");
135  _failRegex = QRegExp(p+"Could not generate metadata for module \"(.+)\".*");
136  _warnRegex = QRegExp("\\(WW\\)\\s+.*");
137  _ttFont.setStyleHint(QFont::TypeWriter);
138  _sfFont.setStyleHint(QFont::SansSerif);
139  _result = new QStandardItemModel(0,2,this);
140  QStandardItem* head = new QStandardItem(tr("file"));
141  _result->setHorizontalHeaderItem(0,head);
142  head = new QStandardItem(tr("module"));
143  _result->setHorizontalHeaderItem(1,head);
144  head = new QStandardItem(tr("status"));
145  _result->setHorizontalHeaderItem(2,head);
146  _result->setSortRole(Qt::UserRole);
147  _view->setModel(_result);
148  _view->setEditTriggers(QAbstractItemView::NoEditTriggers);
149  _view->horizontalHeader()->setStretchLastSection(true);
150  _view->verticalHeader()->hide();
151  _view->setSortingEnabled(true);
152  _view->setAlternatingRowColors(true);
153  _view->setGridStyle(Qt::NoPen);
154  _view->setSelectionBehavior(QAbstractItemView::SelectRows);
155  _view->setSelectionMode(QAbstractItemView::SingleSelection);
156  connect(_view->selectionModel(),
157  SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
158  SLOT(_searchOutput(QModelIndex)));
159 }
160 
161 
163  if (_curStatus == Invalid) {
164  return;
165  }
166  QList<QStandardItem*> row;
167  QStandardItem* curItem = 0;
168  QFont curFont;
169 
170  curItem = new QStandardItem();
171  curFont = _ttFont;
172  if (_curFile.isEmpty()) {
173  _curFile = tr("[no file available]");
174  curFont.setItalic(true);
175  curItem->setData(_curFile, Qt::DisplayRole);
176  curItem->setData(QColor(Qt::gray), Qt::ForegroundRole);
177  curItem->setData(QString(), Qt::UserRole);
178  }
179  else {
180  curItem->setData(_curFile, Qt::DisplayRole);
181  curItem->setData(_curFile, Qt::UserRole);
182  }
183  curItem->setData(curFont, Qt::FontRole);
184  row << curItem;
185 
186  curItem = new QStandardItem();
187  curItem->setData(_curPlugin, Qt::DisplayRole);
188  curItem->setData(_curPlugin, Qt::UserRole);
189  curItem->setData(_ttFont, Qt::FontRole);
190  row << curItem;
191 
192  curItem = new QStandardItem();
193  curItem->setData(_curStatus, Qt::UserRole);
194  curFont = _sfFont;
195  switch (_curStatus) {
196  case Passed:
197  curItem->setData(tr("passed"), Qt::DisplayRole);
198  curItem->setData(QBrush(QColor("#0A2")),Qt::ForegroundRole);
199  break;
200  case NoPlugin:
201  curItem->setData(tr("no plugin"), Qt::DisplayRole);
202  curItem->setData(QBrush(QColor("#777")),Qt::ForegroundRole);
203  break;
204  case Warnings:
205  curItem->setData(tr("warnings"), Qt::DisplayRole);
206  curItem->setData(QBrush(QColor("#F84")),Qt::ForegroundRole);
207  curFont.setWeight(QFont::DemiBold);
208  break;
209  case Failed:
210  curItem->setData(tr("failed"), Qt::DisplayRole);
211  curItem->setData(QBrush(QColor("#F20")),Qt::ForegroundRole);
212  curFont.setWeight(QFont::DemiBold);
213  break;
214  default:
215  qDebug() << "unhandled status code:" << _curStatus;
216  break;
217  }
218  curItem->setData(curFont, Qt::FontRole);
219  row << curItem;
220 
221  _result->appendRow(row);
222  _view->setRowHeight(_result->rowCount()-1,20);
223  _view->setColumnWidth(0,_view->width()/2);
224  _view->setColumnWidth(1,_view->width()/4);
225 
226  // reset status
227  _curStatus = Invalid;
228  _curFile = QString();
229  _curPlugin = QString();
230 }
231 
233  if (_fileRegex.exactMatch(line)) {
234  _appendSummaryRow();
235  _curFile = _fileRegex.cap(1);
236  _curStatus = Failed;
237  }
238  else if (_noPluginRegex.exactMatch(line)) {
239  _curStatus = NoPlugin;
240  if (!_curPlugin.isEmpty() && _curPlugin != _noPluginRegex.cap(1)) {
241  qDebug() << "Plugin Mismatch (noPlugin):"
242  << _curPlugin << _noPluginRegex.cap(1);
243  }
244  _curPlugin = _noPluginRegex.cap(1);
245  }
246  else if (_failRegex.exactMatch(line)) {
247  if (!_curPlugin.isEmpty() && _curPlugin != _failRegex.cap(1)) {
248  qDebug() << "Plugin Mismatch (fail):"
249  << _curPlugin << _failRegex.cap(1);
250  }
251  _curStatus = Failed;
252  _curPlugin = _failRegex.cap(1);
253  _appendSummaryRow();
254  }
255  else if (_warnRegex.exactMatch(line)) {
256  _curStatus = Warnings;
257  }
258  else if (_passRegex.exactMatch(line)) {
259  if (!_curPlugin.isEmpty() && _curPlugin != _passRegex.cap(1)) {
260  qDebug() << "Plugin Mismatch (pass):"
261  << _curPlugin << _passRegex.cap(1);
262  }
263  _curPlugin = _passRegex.cap(1);
264  if (_curStatus != Warnings) {
265  _curStatus = Passed;
266  }
267  }
268  else if (_finishRegex.exactMatch(line)) {
269  if (!_curPlugin.isEmpty() && _curPlugin != _finishRegex.cap(1)) {
270  qDebug() << "Plugin Mismatch (finish):"
271  << _curPlugin << _finishRegex.cap(1);
272  }
273  if (_curStatus != Passed && _curStatus != Warnings) {
274  qDebug() << "Strange Plugin Status (finish):" << _curStatus;
275  }
276  _curPlugin = _finishRegex.cap(1);
277  _appendSummaryRow();
278  }
279 }
280 
282  _view->sortByColumn(2,Qt::DescendingOrder);
283 }
284 
286  return _view;
287 }
288 
289 void LogDecorators::Update::_searchOutput(const QModelIndex& idx) {
290  emit filter(QString("\"%1\"").arg(
291  _result->data(_result->index(idx.row(),1),Qt::DisplayRole).toString()));
292 }
293 
295  return QString("#update-metadata");
296 }
297 
298 // ------------------------- update dynamics ------------------------------
300  _fileName(fileName) {
301 }
302 
304  return tr("Plugin Information Update of Dynamic Modules");
305 }
306 
308  return tr("Output of update-dynamics process:");
309 }
310 
313  .absoluteFilePath("updateDynLog.txt");
314 }
315 
316 QStringList LogDecorators::UpdateDynamics::postStartCommands(QWidget *pp) const {
317  QSettings settings;
318  QStringList cmds;
319  if (settings.value("delayExecution",false).toBool()) {
320  QMessageBox::information(
321  pp,
322  tr("wait before plugin update"),
323  tr(
324  "Waiting because <em>delayExecution</em> option set. "
325  "You can now attach your debugger to the update process. "
326  "Update will be started, when you close this message box."
327  )
328  );
329  cmds << QString("update-dynamics ")+_fileName << "quit";
330  }
331  return cmds;
332 }
333 
335  QSettings settings;
336  QStringList args;
337  args << "--quiet";
338  if (!settings.value("delayExecution",false).toBool()) {
339  args << "--non-interactive" << "update-dynamics" << _fileName;
340  }
341  return args;
342 }
343 
344 // -------------------------- run workflow -------------------------------
346  _fileName(fileName) {
347 }
348 
349 bool LogDecorators::RunWorkflow::ready(QWidget* pp) const {
350  if(_fileName.isEmpty()) {
351  QMessageBox::warning(
352  pp,
353  tr("missing workflow file"),
354  tr(
355  "The workflow cannot be started because it has not "
356  "been saved to disk (empty filename given). "
357  "Please save it and retry execution."
358  )
359  );
360  return false;
361  }
362  return true;
363 }
364 
366  QSettings settings;
367  QStringList args;
368  args << "--quiet";
369  if (!settings.value("delayExecution",false).toBool()) {
370  args << "run" << _fileName;
371  }
372  return args;
373 }
374 
375 QStringList LogDecorators::RunWorkflow::postStartCommands(QWidget* pp) const {
376  QSettings settings;
377  QStringList cmds;
378  if (settings.value("delayExecution",false).toBool()) {
379  QMessageBox::information(
380  pp,
381  tr("wait before workflow execution"),
382  tr(
383  "Waiting because <em>delayExecution</em> option set. "
384  "You can now attach your debugger to the run process. "
385  "Workflow will be started, when you close this message box."
386  )
387  );
388  cmds << QString("run %1").arg(_fileName);
389  }
390  return cmds;
391 }
392 
394  // emit signal to highlight currently executed object
395  QRegExp curObj("\\(II\\) Executing\\s*\\w*\\s*\"(\\w*)\"\\s*");
396  if (curObj.exactMatch(line)) {
397  emit highlightObject(curObj.cap(1));
398  }
399  // add status message if workflow execution finished
400  if (line.contains(
401  QCoreApplication::translate("CharonRun","Execution finished.")) ||
402  line.contains(
403  QCoreApplication::translate("CharonRun","Error during execution:"))) {
404  emit finish();
405  emit message(finishMessage());
406  }
407 }
408 
410  return QString("<br><span class=\"success\">%1</span><br>%2<br>")
411  .arg(tr("Workflow execution finished."))
412  .arg(tr("Plugins stay loaded until you close this dialog."));
413 }
414 
416  QFileInfo wrpFile(_fileName);
417  return QString("%1/%2.log")
418  .arg(wrpFile.absolutePath()).arg(wrpFile.baseName());
419 }
420 
423  .absoluteFilePath("executeLog.txt");
424 }
425 
427  return QString("#run-workflow");
428 }
virtual QString finishMessage() const
finish message to display when workflow finished
Declaration of class FileManager.
QRegExp _failRegex
fail regex
virtual QString title() const
title string
static const FileManager & instance()
get a reference to the file Manager instance
Definition: FileManager.cpp:70
QRegExp _warnRegex
no plugin info
virtual void processLine(QString line)
decorator hook to allow log line parsing
QRegExp _noPluginRegex
no plugin info
QRegExp _finishRegex
plugin unloaded
virtual QStringList arguments() const
determine command line arguments
QDir configDir() const
get config directory
Definition: FileManager.cpp:77
void _appendSummaryRow()
append log row with current information
virtual QString desc() const
description string
virtual QString desc() const
description string
virtual QString title() const
title string
virtual QStringList postStartCommands(QWidget *pp) const
commands sent to the proccess after start
Declaration of classes in the LogDecorators namespace.
QFont _ttFont
typewriter font
virtual void finishProcessing()
inform about finished processing
RunWorkflow(QString fileName)
constructor
QStandardItemModel * _result
update summary
virtual QStringList postStartCommands(QWidget *parent) const
commands sent to the proccess after start
QFont _sfFont
sans-serif font
virtual bool ready(QWidget *parent) const
check if process may be started
virtual QString logFileName() const
logfile name for output logging
virtual QWidget * statusWidget()
custom status widget
virtual void processLine(QString line)
decorator hook to allow log line parsing
virtual QStringList postStartCommands(QWidget *parent) const
commands sent to the proccess after start
QTableView * _view
summary list
virtual void finishProcessing()
inform about finished processing
virtual QString desc() const
description string
virtual QString filenameHint() const
hint for filename on save dialog
virtual QWidget * statusWidget()
custom status widget
virtual QString logFileName() const
logfile name for output logging
UpdateDynamics(QString fileName)
constructor
virtual QString helpAnchor()
html anchor on help page
virtual QString helpAnchor()
html anchor on help page
virtual QString title() const
title string
virtual QString filenameHint() const
hint for filename on save dialog
QRegExp _fileRegex
file name regexp
virtual bool ready(QWidget *parent) const
check if process may be started
QRegExp _passRegex
plugin passed regexp
virtual QString helpAnchor()
html anchor on help page
virtual QString filenameHint() const
hint for filename on save dialog
virtual QStringList postStartCommands(QWidget *parent) const
commands sent to the proccess after start
void _searchOutput(const QModelIndex &)
show corresponding log line on selection
virtual QStringList arguments() const
determine command line arguments
virtual void processLine(QString line)
decorator hook to allow log line parsing
virtual QStringList arguments() const
determine command line arguments
virtual QString logFileName() const
logfile name for output logging