tuchulcha  0.10.1
Graphical Workflow Configuration Editor
CharonRun.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 "CharonRun.h"
26 
27 #include "FileManager.h"
29 #include <QSettings>
30 #include <fstream>
32 #include <QMessageBox>
33 #include <QTextStream>
34 #include <QApplication>
35 #include <QDateTime>
36 #include "OptionsDialog.h"
37 
38 #ifdef __GNUG__
39 #include <cxxabi.h>
40 #endif // __GNUG__
41 
42 CharonRun::CharonRun(QObject* pp) :
43  QObject(pp), _man(0)
44 {
45  sout.assign();
46 }
47 
48 CharonRun::~CharonRun() {
49  if (_man) {
50  _freeMan();
51  }
52 }
53 
55  if (_man) {
56  _freeMan();
57  }
58 
59  QSettings settings;
60 #ifdef _MSC_VER
61  // use compile type in MSVC builds
62 #ifdef QT_DEBUG
63  const bool debug = true;
64  const QString privPathTag = "privatePluginPathD";
65 #else // QT_DEBUG
66  const bool debug = false;
67  const QString privPathTag = "privatePluginPath";
68 #endif // QT_DEBUG
69 #else // MSVC
70  // use settings option in unix builds
71  const bool debug = settings.value("suffixedPlugins", false).toBool();
72  const QString privPathTag = debug?"privatePluginPathD":"privatePluginPath";
73 #endif // MSVC
74 
75  QTextStream qout(stdout,QIODevice::WriteOnly);
76  qout << "(II) "
77  << tr("%1 plugins with debug suffix")
78  .arg((debug?tr("prefering"):tr("ignoring"))) << endl;
79 
80  QStringList paths;
81  QStringList libFilter;
82  libFilter << "*.dll" << "*.so" << "*.dylib";
83  QStringList excludeList = settings.value("excludeList").toStringList();
84  QStringList exclExp;
85  paths << settings.value(privPathTag).toStringList();
86  paths << settings.value("globalPluginPath").toStringList();
87  paths.removeDuplicates();
88  paths.removeAll("");
89 
90  qout << "(II) " << tr("Paths:") << endl;
91  std::vector<std::string> pathsS, exclS;
92  QStringListIterator pathsIter(paths);
93  while (pathsIter.hasNext()) {
94  QDir curD(pathsIter.next());
95  QString cur = curD.canonicalPath();
96 
97  if (curD.exists()) {
98  qout << "(II) \t" << cur << endl;
99  pathsS.push_back(cur.toStdString());
100  // globbing for excludes
101  QStringList libs = curD.entryList(libFilter);
102  QStringListIterator libsIter(libs);
103  while (libsIter.hasNext()) {
104  QFileInfo lin(libsIter.next());
105  QString lib = lin.completeBaseName();
106  lib.remove(QRegExp("_d$",Qt::CaseInsensitive));
107 #ifndef _MSC_VER
108  lib.remove(QRegExp("^lib",Qt::CaseInsensitive));
109 #endif
110  QStringListIterator excludeListIter(excludeList);
111  while (excludeListIter.hasNext()) {
112  const QString ex = excludeListIter.next();
113  QRegExp rex(ex,Qt::CaseInsensitive,QRegExp::WildcardUnix);
114  if (rex.exactMatch(lib)) {
115  exclExp << lib;
116  }
117  }
118  }
119  }
120  else {
121  qout << "(WW) \t"
122  << tr("skipping non-existing path: %1").arg(cur) << endl;
123  }
124  }
125  qout << endl;
126  exclExp.removeDuplicates();
127  qout << "(DD) " << tr("found excludes:") << endl;
128  foreach (QString exc, exclExp) {
129  qout << "(DD) \t" << exc << endl;
130  exclS.push_back(exc.toStdString());
131  }
132  qout << "(DD) " << endl;
133 
134  PluginManagerInterface::PluginVersionCheckLevel versionCheck =
135  static_cast<PluginManagerInterface::PluginVersionCheckLevel>(
136  settings.value("versionCheckLevel",2).toInt());
137 
138  // initialize plugin manager with determined settings
139  _man = new PluginManager(pathsS, debug, false, versionCheck);
140  _man->setExcludeList(exclS);
141 }
142 
144  if (_man) {
145  delete _man;
146  _man = 0;
147  }
148 }
149 
151  _taskStart();
152  QTextStream qout(stdout);
153 
154  // delete old wrp files
155  const FileManager& fm = FileManager::instance();
156  QDir metaPath = fm.configDir().absoluteFilePath("metadata");
157  QStringList wrpFiles = metaPath.entryList(
158  QStringList("*.wrp"), QDir::Files);
159  for (int i=0; i < wrpFiles.size(); i++) {
160  Q_ASSERT(QFileInfo(metaPath.absoluteFilePath(wrpFiles[i])).exists());
161  Q_ASSERT(QFileInfo(metaPath.absoluteFilePath(wrpFiles[i])).isFile());
162  Q_ASSERT(wrpFiles[i].contains(QRegExp(".*\\.wrp$")));
163 #ifndef QT_NO_DEBUG
164  bool success =
165 #endif
166  metaPath.remove(wrpFiles[i]);
167  Q_ASSERT(success);
168  }
169  try {
170  _setupMan();
171  }
172  catch(std::exception& err)
173  {
174  qout << "(EE) Could not set up PluginManager: " << err.what() << "\n"
175  << "(EE) Please check that your local and global plugin paths "
176  << "are set correctly in the options menu." << endl ;
177  return;
178  }
179  _man->createMetadata(metaPath.absolutePath().toStdString());
180  _freeMan();
181 
182  // update metadata file
183  wrpFiles = metaPath.entryList(QStringList("*.wrp"), QDir::Files);
184  QFile cFile(fm.classesFile());
185  if (wrpFiles.isEmpty()) {
186  // skip writing metadata file if no metadata available,
187  // remove the file instead to enforce reloading metadata
188  // at next tuchulcha startup
189  qout << "(EE) No Plugins found!\n"
190  << "(EE) Please check that your local and global plugin paths "
191  << "are set correctly in the options menu." << endl ;
192  cFile.remove();
193  return;
194  }
195 
196  if (!cFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
197  QMessageBox::warning(
198  fm.dialogParent, tr("error updating meta data"),
199  tr("could not open classes file for writing"));
200  return;
201  }
202  QTextStream cStream(&cFile);
203  Q_ASSERT(cStream.status() == QTextStream::Ok);
204  cStream << "# Tuchulcha class information file\n";
205  cStream << "# Content is copied from files in metadata directory\n";
206  cStream << "# This is generated during update plugins,\n";
207  cStream << "# do not edit by hand!" << endl;
208 
209  for(int i=0; i<wrpFiles.size(); i++) {
210  QFile cur(metaPath.absoluteFilePath(wrpFiles[i]));
211  cur.open(QIODevice::ReadOnly | QIODevice::Text);
212  QString content = cur.readAll();
213  cur.close();
214  cStream << tr("\n# from file \"%1\":\n").arg(wrpFiles[i]);
215  cStream << content << endl;
216  }
217  cFile.close();
218  _taskFinished();
219 }
220 
221 void CharonRun::runWorkflow(QString fName) {
222  _taskStart();
223  QTextStream qout(stdout);
224  _setupMan();
225 
226  //QString pathBak = QDir::currentPath();
227  fName = QFileInfo(fName).absoluteFilePath();
228  QDir::setCurrent(QFileInfo(fName).path());
229  QString errorMsg;
230  try {
231  qout << tr("Loading parameter file \"%1\"").arg(fName) << endl;
232  _man->loadParameterFile(fName.toStdString());
233  qout << endl;
234  qout << tr("== Executing Workflow ==") << endl;
235  const QDateTime& startTime = QDateTime::currentDateTime();
236  qout << tr("start time: %1").arg(startTime.toString(Qt::ISODate))
237  << endl;
238  _man->runWorkflow();
239  const QDateTime& endTime = QDateTime::currentDateTime();
240  QTime runTime = QTime().addSecs(startTime.secsTo(endTime));
241 
242  qout << tr("Execution finished.") << "\n";
243  qout << tr("end time : %1").arg(endTime.toString(Qt::ISODate)) << endl;
244  qout << tr("runtime : %1").arg(
245  runTime.toString("hh:mm:ss.zzz")) << endl;
246  }
247  catch (const std::string& msg) {
248  errorMsg =
249  tr("Caught exception of type \"std::string\".")
250  +"\n\n"+tr("Message:")+"\n"+msg.c_str();
251  }
252  catch (const std::exception& excpt) {
253  const char* name = typeid(excpt).name();
254 #ifdef __GNUG__
255  name = abi::__cxa_demangle(name, 0, 0, 0);
256 #endif // __GNUG__
257  errorMsg =
258  tr("Caught exception of type \"%1\".").arg(name)
259  +"\n\n"+tr("Message:")+"\n"+excpt.what();
260  }
261  catch (const char* &msg) {
262  errorMsg =
263  tr("Caught exception of type \"char*\".")
264  + "\n\n"+tr("Message:")+"\n" + msg;
265  }
266  catch (...) {
267  errorMsg = tr("Caught exception of unknown type.");
268  }
269  if (!errorMsg.isEmpty()) {
270  QTextStream qerr(stderr);
271  qerr << "\n****************************************************\n\n"
272  << tr("Error during execution:") << "\n\n"
273  << errorMsg << "\n\n"
274  << "****************************************************"
275  << endl;
276  }
277  //don't reset the working Dir, some plugins may still be running
278  //(e.g. FileReaderWatcher or ArgosDisplayReloader)
279  //QDir::setCurrent(pathBak);
280 
281  _taskFinished();
282 }
283 
285  emit busy();
286 }
287 
289  emit ready();
290 }
291 
293  QApplication::exit();
294 }
295 
296 void CharonRun::updateDynamics(QString fName) {
297  _taskStart();
298 
299  QString baseN = QFileInfo(fName).baseName();
300 
301  // delete old wrp files
302  const FileManager& fm = FileManager::instance();
303  QDir dynamPath = fm.configDir().absoluteFilePath("dynamics");
304  if (dynamPath.exists()) {
305  QStringList wrpFiles = dynamPath.entryList(
306  QStringList("*.wrp"), QDir::Files);
307  wrpFiles = wrpFiles.filter(QRegExp("^" + baseN + "_"));
308  for (int i=0; i < wrpFiles.size(); i++) {
309  Q_ASSERT(QFileInfo(dynamPath.absoluteFilePath(wrpFiles[i])).exists());
310  Q_ASSERT(QFileInfo(dynamPath.absoluteFilePath(wrpFiles[i])).isFile());
311  Q_ASSERT(wrpFiles[i].indexOf(".wrp") > 0);
312  dynamPath.remove(wrpFiles[i]);
313  Q_ASSERT(!QFileInfo(wrpFiles[i]).exists());
314  }
315  } else {
316  Q_ASSERT(fm.configDir().mkdir("dynamics"));
317  }
318 
319  _setupMan();
320  _man->createDynamicMetadata(fName.toStdString(),
321  dynamPath.absoluteFilePath(baseN).toStdString());
322  _freeMan();
323 
324  _taskFinished();
325 }
326 
328  if (!OptionsDialog::check()) {
329  // nothing to do
330  QTextStream qout(stdout,QIODevice::WriteOnly);
331  qout << "(DD) " << tr("path settings seem to be ok, keeping them")
332  << endl;
333  return;
334  }
335  _taskStart();
336 
337 #ifdef UNIX
338  // standard install path on linux systems
339  QString globalPath = "/usr/lib/charon-plugins";
340 #else
341  // Assume global plugin dir to be the same directory
342  // where the tuchulcha.exe is located
343  QString globalPath = QCoreApplication::applicationDirPath();
344 #endif
345 
346  QSettings settings;
347  settings.setValue("globalPluginPath", globalPath);
348  settings.setValue("privatePluginPath",QString());
349  settings.setValue("privatePluginPathD",QString());
350 
351  _taskFinished();
352 }
Declaration of class FileManager.
void setupSettings()
setup settings
Definition: CharonRun.cpp:327
void busy()
signal to avoid new command prompt
PluginManager * _man
plugin manager
Definition: CharonRun.h:68
void updatePlugins()
update plugin information
Definition: CharonRun.cpp:150
static const FileManager & instance()
get a reference to the file Manager instance
Definition: FileManager.cpp:70
static QWidget * dialogParent
parent widget for operation result dialogs
Definition: FileManager.h:46
charon_core_DLL_PUBLIC SplitStream sout
QDir configDir() const
get config directory
Definition: FileManager.cpp:77
bool charon_core_DLL_PUBLIC exists(const std::string &file)
CharonRun(QObject *parent=0)
constructor
Definition: CharonRun.cpp:42
void createMetadata(const std::string &targetPath="")
Common config file information and handling.
Definition: FileManager.h:37
QString classesFile() const
get the path of the classes file
Definition: FileManager.cpp:87
Declaration of class OptionsDialog.
void exitWhenFinished()
unlock exiting, quit application if all tasks are completed
Definition: CharonRun.cpp:292
void setExcludeList(const std::vector< std::string > &list)
void updateDynamics(QString fName)
update dynamic plugins of given workflow file
Definition: CharonRun.cpp:296
void _setupMan()
setup plugin manager
Definition: CharonRun.cpp:54
Declaration of class CharonRun.
void ready()
show that running tasks are complete
void _taskFinished()
decrease task counter
Definition: CharonRun.cpp:288
void runWorkflow()
void runWorkflow(QString fName)
run given workflow file
Definition: CharonRun.cpp:221
void _taskStart()
increase task counter
Definition: CharonRun.cpp:284
void _freeMan()
release plugin manager
Definition: CharonRun.cpp:143
void createDynamicMetadata(const ParameterFile &paramFile, const std::string &filePrefix)
static bool check()
Configures plugin paths.
void loadParameterFile(const ParameterFile &pf)