Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkBaseApplication.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkBaseApplication.h"
18 #include "mitkLogMacros.h"
19 
20 #include "QmitkSafeApplication.h"
21 #include "QmitkSingleApplication.h"
22 #include "mitkProvisioningInfo.h"
23 
24 #include <ctkPluginConstants.h>
25 #include <ctkPluginFramework.h>
26 #include <ctkPluginFrameworkLauncher.h>
27 #include <ctkPluginFramework_global.h>
28 
29 #include <usModuleSettings.h>
30 
31 #include <Poco/Util/HelpFormatter.h>
32 
33 #include <QSplashScreen>
34 #include <QRunnable>
35 #include <QFileInfo>
36 #include <QCoreApplication>
37 #include <QDebug>
38 #include <QDesktopServices>
39 #include <QDir>
40 #include <QStringList>
41 #include <QTime>
42 
43 #include <iostream>
44 
45 namespace mitk
46 {
47  QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance";
48  QString BaseApplication::ARG_CLEAN = "BlueBerry.clean";
49  QString BaseApplication::ARG_APPLICATION = "BlueBerry.application";
50  QString BaseApplication::ARG_PRODUCT = "BlueBerry.product";
51  QString BaseApplication::ARG_HOME = "BlueBerry.home";
52  QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir";
53  QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir";
54  QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs";
55  QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins";
56  QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary";
57  QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning";
58  QString BaseApplication::ARG_DEBUG = "BlueBerry.debug";
59  QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog";
60  QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin";
61  QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication";
62 
63  QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen";
64 
65  QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache";
66  QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading";
67  QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage";
68 
69  QString BaseApplication::ARG_XARGS = "xargs";
70 
76 
77  QString BaseApplication::PROP_PRODUCT = "blueberry.product";
78  QString BaseApplication::PROP_APPLICATION = "blueberry.application";
79  QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin";
80  QString BaseApplication::PROP_TESTAPPLICATION = "BlueBerry.testapplication";
81 
82  class SplashCloserCallback : public QRunnable
83  {
84  public:
85  SplashCloserCallback(QSplashScreen* splashscreen)
86  {
87  this->m_Splashscreen = splashscreen;
88  }
89 
90  void run()
91  {
92  this->m_Splashscreen->close();
93  }
94 
95  private:
96  QSplashScreen* m_Splashscreen;
97  };
98 
99  struct BaseApplication::Impl
100  {
101  ctkProperties m_FWProps;
102 
103  QScopedPointer<QCoreApplication> m_QApp;
104 
105  int m_Argc;
106  char **m_Argv;
107 
108  QString m_AppName;
109  QString m_OrgaName;
110  QString m_OrgaDomain;
111 
112  bool m_SingleMode;
113  bool m_SafeMode;
114 
115  QSplashScreen* m_Splashscreen;
116  SplashCloserCallback* m_SplashscreenClosingCallback;
117 
118  QStringList m_PreloadLibs;
119  QString m_ProvFile;
120 
121  Impl(int argc, char **argv)
122  : m_Argc(argc), m_Argv(argv), m_SingleMode(false), m_SafeMode(true),
123  m_Splashscreen(0), m_SplashscreenClosingCallback(nullptr)
124  {
125 #ifdef Q_OS_MAC
126  /*
127  * This is a workaround for bug 19080:
128  * On Mac OS X the prosess serial number is passed as an commandline argument (-psn_<NUMBER>)
129  * if the application is started via the.app bundle.
130  * This option is unknown, which causes a Poco exception.
131  * Since this is done by the system we have to manually remove the argument here.
132  */
133 
134  int newArgc = m_Argc - 1;
135  char **newArgs = new char *[newArgc];
136  bool argFound(false);
137  for (int i = 0; i < m_Argc; ++i)
138  {
139  if (QString::fromLatin1(m_Argv[i]).contains("-psn"))
140  {
141  argFound = true;
142  }
143  else
144  {
145  newArgs[i] = m_Argv[i];
146  }
147  }
148  if (argFound)
149  {
150  m_Argc = newArgc;
151  m_Argv = newArgs;
152  }
153 #endif
154  }
155 
156  QVariant getProperty(const QString &property) const
157  {
158  auto iter = m_FWProps.find(property);
159  return iter == m_FWProps.end() ? QVariant() : iter.value();
160  }
161 
162  void handleBooleanOption(const std::string &name, const std::string & /*value*/)
163  {
164  QString fwKey = QString::fromStdString(name);
165 
166  // translate some keys to proper framework properties
167  if (fwKey == ARG_CONSOLELOG)
168  {
169  fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG;
170  }
171 
172  // For all other options we use the command line option name as the
173  // framework property key.
174  m_FWProps[fwKey] = true;
175  }
176 
177  void handlePreloadLibraryOption(const std::string & /*name*/, const std::string &value)
178  {
179  m_PreloadLibs.push_back(QString::fromStdString(value));
180  }
181 
182  void handleClean(const std::string & /*name*/, const std::string & /*value*/)
183  {
184  m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
185  }
186 
187  void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration)
188  {
189  // add all configuration key / value pairs as framework properties
190  Poco::Util::LayeredConfiguration::Keys keys;
191  Poco::Util::LayeredConfiguration::Keys keyStack;
192  configuration.keys(keyStack);
193  std::vector<std::string> keyChain;
194  while (!keyStack.empty())
195  {
196  std::string currSubKey = keyStack.back();
197  if (!keyChain.empty() && keyChain.back() == currSubKey)
198  {
199  keyChain.pop_back();
200  keyStack.pop_back();
201  continue;
202  }
203  Poco::Util::LayeredConfiguration::Keys subKeys;
204  configuration.keys(currSubKey, subKeys);
205  if (subKeys.empty())
206  {
207  keyStack.pop_back();
208  std::string finalKey;
209  for (auto k = keyChain.begin(); k != keyChain.end(); ++k)
210  {
211  finalKey += *k + ".";
212  }
213  finalKey += currSubKey;
214  keys.push_back(finalKey);
215  }
216  else
217  {
218  keyChain.push_back(currSubKey);
219  for (auto s : subKeys)
220  {
221  keyStack.push_back(s);
222  }
223  }
224  }
225 
226  for (auto key : keys)
227  {
228  QString qKey = QString::fromStdString(key);
229  if (configuration.hasProperty(key))
230  {
231  // ini and command line options overwrite already inserted keys
232  m_FWProps[qKey] = QString::fromStdString(configuration.getString(key));
233  }
234  }
235  }
236 
237  void parseProvisioningFile(const QString &filePath)
238  {
239  // Skip parsing if the file path is empty
240  if (filePath.isEmpty())
241  return;
242 
243  bool consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool();
244 
245  // read initial plugins from a provisioning file
246  QStringList pluginsToStart;
247 
248  QFileInfo provFile(filePath);
249 
250  if (provFile.exists())
251  {
252  MITK_INFO(consoleLog) << "Using provisioning file: " << qPrintable(provFile.absoluteFilePath());
253  ProvisioningInfo provInfo(provFile.absoluteFilePath());
254  // it can still happen, that the encoding is not compatible with the fromUtf8 function ( i.e. when manipulating
255  // the LANG variable
256  // in such case, the QStringList in provInfo is empty which we can easily check for
257  if (provInfo.getPluginDirs().empty())
258  {
259  MITK_ERROR << "Cannot search for provisioning file, the retrieved directory list is empty.\n"
260  << "This can occur if there are some special (non-ascii) characters in the install path.";
261  }
262  else
263  {
264  foreach (QString pluginPath, provInfo.getPluginDirs())
265  {
266  ctkPluginFrameworkLauncher::addSearchPath(pluginPath);
267  }
268 
269  // bool forcePluginOverwrite = this->getProperty(ARG_FORCE_PLUGIN_INSTALL).toBool();
270  QList<QUrl> pluginUrlsToStart = provInfo.getPluginsToStart();
271  for (auto url : pluginUrlsToStart)
272  {
273  pluginsToStart.push_back(url.toString());
274  }
275  // foreach(QUrl pluginUrl, provInfo.getPluginsToInstall())
276  //{
277  // TODO for "uninstall", we need a proper configuration agent, e.g. a dedicated
278  // plug-in for provisioning of the platform
279  /*
280  if (forcePluginOverwrite)
281  {
282  uninstallPugin(pluginUrl, context);
283  }
284  */
285  // try
286  //{
287  // MITK_INFO(consoleLog) << "Installing CTK plug-in from: " << pluginUrl.toString().toStdString();
288  /*
289  QSharedPointer<ctkPlugin> plugin = context->installPlugin(pluginUrl);
290  if (pluginsToStart.contains(pluginUrl))
291  {
292  m_CTKPluginsToStart << plugin->getPluginId();
293  }
294  */
295  /*
296  }
297  catch (const ctkPluginException& e)
298  {
299  QString errorMsg;
300  QDebug dbg(&errorMsg);
301  dbg << e.printStackTrace();
302  BERRY_ERROR << qPrintable(errorMsg);
303  }
304  */
305  //}
306  }
307  }
308  else
309  {
310  MITK_INFO(consoleLog) << "No provisioning file set.";
311  }
312 
313  if (!pluginsToStart.isEmpty())
314  {
315  m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart;
316 
317  // Use transient start with declared activation policy (this helps when
318  // the provisioning file changes and some plug-ins should not be installed
319  // in the application any more).
320  ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY);
321  m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] = static_cast<int>(startOptions);
322  }
323  }
324  };
325 
326  BaseApplication::BaseApplication(int argc, char **argv) : Application(), d(new Impl(argc, argv))
327  {
328  }
329 
331  {
332  if (d->m_Splashscreen != 0)
333  {
334  delete(d->m_Splashscreen);
335  }
336  if (d->m_SplashscreenClosingCallback != 0)
337  {
338  delete(d->m_SplashscreenClosingCallback);
339  }
340  }
341 
342  void BaseApplication::printHelp(const std::string & /*name*/, const std::string & /*value*/)
343  {
344  Poco::Util::HelpFormatter help(this->options());
345  help.setAutoIndent();
346  help.setCommand(this->commandName());
347  help.format(std::cout);
348 
349  exit(EXIT_OK);
350  }
351 
352  void BaseApplication::setApplicationName(const QString &name)
353  {
354  if (qApp)
355  {
356  qApp->setApplicationName(name);
357  }
358  d->m_AppName = name;
359  }
360 
362  {
363  if (qApp)
364  {
365  return qApp->applicationName();
366  }
367  return d->m_AppName;
368  }
369 
370  void BaseApplication::setOrganizationName(const QString &name)
371  {
372  if (qApp)
373  {
374  qApp->setOrganizationName(name);
375  }
376  d->m_OrgaName = name;
377  }
378 
380  {
381  if (qApp)
382  return qApp->organizationName();
383  return d->m_OrgaName;
384  }
385 
386  void BaseApplication::setOrganizationDomain(const QString &domain)
387  {
388  if (qApp)
389  {
390  qApp->setOrganizationDomain(domain);
391  }
392  d->m_OrgaDomain = domain;
393  }
394 
396  {
397  if (qApp)
398  return qApp->organizationDomain();
399  return d->m_OrgaDomain;
400  }
401 
402  void BaseApplication::setSingleMode(bool singleMode)
403  {
404  if (qApp)
405  return;
406  d->m_SingleMode = singleMode;
407  }
408 
409  bool BaseApplication::getSingleMode() const { return d->m_SingleMode; }
410  void BaseApplication::setSafeMode(bool safeMode)
411  {
412  if (qApp && !d->m_QApp)
413  return;
414  d->m_SafeMode = safeMode;
415  if (d->m_QApp)
416  {
417  if (getSingleMode())
418  {
419  static_cast<QmitkSingleApplication *>(d->m_QApp.data())->setSafeMode(safeMode);
420  }
421  else
422  {
423  static_cast<QmitkSafeApplication *>(d->m_QApp.data())->setSafeMode(safeMode);
424  }
425  }
426  }
427 
428  bool BaseApplication::getSafeMode() const { return d->m_SafeMode; }
429  void BaseApplication::setPreloadLibraries(const QStringList &libraryBaseNames)
430  {
431  d->m_PreloadLibs = libraryBaseNames;
432  }
433 
434  QStringList BaseApplication::getPreloadLibraries() const { return d->m_PreloadLibs; }
435  void BaseApplication::setProvisioningFilePath(const QString &filePath) { d->m_ProvFile = filePath; }
437  {
438  QString provFilePath = d->m_ProvFile;
439 
440  // A null QString means look up a default provisioning file
441  if (provFilePath.isNull() && qApp)
442  {
443  QFileInfo appFilePath(QCoreApplication::applicationFilePath());
444  QDir basePath(QCoreApplication::applicationDirPath());
445 
446  QString provFileName = appFilePath.baseName() + ".provisioning";
447 
448  QFileInfo provFile(basePath.absoluteFilePath(provFileName));
449 
450 #ifdef Q_OS_MAC
451  /*
452  * On Mac, if started from the build directory the .provisioning file is located at:
453  * <MITK-build/bin/MitkWorkbench.provisioning>
454  * but the executable path is:
455  * <MITK-build/bin/MitkWorkbench.app/Contents/MacOS/MitkWorkbench>
456  * In this case we have to cdUp threetimes.
457  *
458  * During packaging however the MitkWorkbench.provisioning file is placed at the same
459  * level like the executable, hence nothing has to be done.
460  */
461 
462  if (!provFile.exists())
463  {
464  basePath.cdUp();
465  basePath.cdUp();
466  basePath.cdUp();
467  provFile = basePath.absoluteFilePath(provFileName);
468  }
469 #endif
470 
471  if (provFile.exists())
472  {
473  provFilePath = provFile.absoluteFilePath();
474  }
475 #ifdef CMAKE_INTDIR
476  else
477  {
478  basePath.cdUp();
479  provFile.setFile(basePath.absoluteFilePath(provFileName));
480  if (provFile.exists())
481  {
482  provFilePath = provFile.absoluteFilePath();
483  }
484  }
485 #endif
486  }
487  return provFilePath;
488  }
489 
491  {
492  if (qApp)
493  return;
494 
495  // If previously parameters have been set we have to store them
496  // to hand them through to the application
497  QString appName = this->getApplicationName();
498  QString orgName = this->getOrganizationName();
499  QString orgDomain = this->getOrganizationDomain();
500 
501  // Create a QCoreApplication instance
502  this->getQApplication();
503 
504  // provide parameters to QCoreApplication
505  this->setApplicationName(appName);
506  this->setOrganizationName(orgName);
507  this->setOrganizationDomain(orgDomain);
508  }
509 
510  void BaseApplication::initialize(Poco::Util::Application &self)
511  {
512  // 1. Call the super-class method
513  Poco::Util::Application::initialize(self);
514 
515  // 2. Initialize the Qt framework (by creating a QCoreApplication)
516  this->initializeQt();
517 
518  // 3. Seed the random number generator, once at startup.
519  QTime time = QTime::currentTime();
520  qsrand((uint)time.msec());
521 
522  // 4. Load the "default" configuration, which involves parsing
523  // an optional <executable-name>.ini file and parsing any
524  // command line arguments
525  this->loadConfiguration();
526 
527  // 5. Add configuration data from the command line and the
528  // optional <executable-name>.ini file as CTK plugin
529  // framework properties.
530  d->initializeCTKPluginFrameworkProperties(this->config());
531 
532  // 6. Initialize splash screen if an image path is provided
533  // in the .ini file
534  this->initializeSplashScreen(qApp);
535 
536  // 7. Set the custom CTK Plugin Framework storage directory
537  QString storageDir = this->getCTKFrameworkStorageDir();
538  if (!storageDir.isEmpty())
539  {
540  d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir;
541  }
542 
543  // 8. Set the library search paths and the pre-load library property
544  this->initializeLibraryPaths();
545  QStringList preloadLibs = this->getPreloadLibraries();
546  if (!preloadLibs.isEmpty())
547  {
548  d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs;
549  }
550 
551  // 9. Initialize the CppMicroServices library.
552  // The initializeCppMicroServices() method reuses the
553  // FRAMEWORK_STORAGE property, so we call it after the
554  // getCTKFrameworkStorageDir method.
556 
557  // 10. Parse the (optional) provisioning file and set the
558  // correct framework properties.
559  d->parseProvisioningFile(this->getProvisioningFilePath());
560 
561  // Finally, set the CTK Plugin Framework properties
562  ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps);
563  }
564 
566  {
568  if (pfw)
569  {
570  pfw->stop();
571 
572  // wait 10 seconds for the CTK plugin framework to stop
573  pfw->waitForStop(10000);
574  }
575 
576  Poco::Util::Application::uninitialize();
577  }
578 
579  int BaseApplication::getArgc() const { return d->m_Argc; }
580  char **BaseApplication::getArgv() const { return d->m_Argv; }
582  {
583  QString storageDir;
584  if (this->getSingleMode())
585  {
586  // This function checks if an instance is already running
587  // and either sends a message to it (containing the command
588  // line arguments) or checks if a new instance was forced by
589  // providing the BlueBerry.newInstance command line argument.
590  // In the latter case, a path to a temporary directory for
591  // the new application's storage directory is returned.
592  storageDir = handleNewAppInstance(
593  static_cast<QtSingleApplication *>(d->m_QApp.data()), d->m_Argc, d->m_Argv, ARG_NEWINSTANCE);
594  }
595 
596  if (storageDir.isEmpty())
597  {
598  // This is a new instance and no other instance is already running. We specify
599  // the storage directory here (this is the same code as in berryInternalPlatform.cpp
600  // so that we can re-use the location for the persistent data location of the
601  // the CppMicroServices library.
602 
603  // Append a hash value of the absolute path of the executable to the data location.
604  // This allows to start the same application from different build or install trees.
605  storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" +
606  this->getOrganizationName() + "/" + this->getApplicationName() + '_';
607  storageDir += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/";
608  }
609  return storageDir;
610  }
611 
613  {
614  QString storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString();
615 
616  if (!storageDir.isEmpty())
617  {
618  us::ModuleSettings::SetStoragePath((storageDir + QString("us") + QDir::separator()).toStdString());
619  }
620  }
621 
622  QCoreApplication *BaseApplication::getQApplication() const
623  {
624  QCoreApplication *qCoreApp = qApp;
625 
626 // Needed to fix bug #18521, i.e. not responding GUI on Mac OS X with Qt5
627 #ifdef Q_OS_OSX
628  qCoreApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
629 #endif
630 
631  qCoreApp->setAttribute(Qt::AA_ShareOpenGLContexts);
632 
633  if (!qCoreApp)
634  {
635  if (getSingleMode())
636  {
637  qCoreApp = new QmitkSingleApplication(d->m_Argc, d->m_Argv, getSafeMode());
638  }
639  else
640  {
641  auto safeApp = new QmitkSafeApplication(d->m_Argc, d->m_Argv);
642  safeApp->setSafeMode(d->m_SafeMode);
643  qCoreApp = safeApp;
644  }
645  d->m_QApp.reset(qCoreApp);
646  }
647  return qCoreApp;
648  }
649 
651  {
652  QStringList suffixes;
653  suffixes << "plugins";
654 #ifdef Q_OS_WINDOWS
655  suffixes << "bin/plugins";
656 #ifdef CMAKE_INTDIR
657  suffixes << "bin/" CMAKE_INTDIR "/plugins";
658 #endif
659 #else
660  suffixes << "lib/plugins";
661 #ifdef CMAKE_INTDIR
662  suffixes << "lib/" CMAKE_INTDIR "/plugins";
663 #endif
664 #endif
665 
666 #ifdef Q_OS_MAC
667  suffixes << "../../plugins";
668 #endif
669 
670  // we add a couple of standard library search paths for plug-ins
671  QDir appDir(QCoreApplication::applicationDirPath());
672 
673  // walk one directory up and add bin and lib sub-dirs; this
674  // might be redundant
675  appDir.cdUp();
676 
677  foreach (QString suffix, suffixes)
678  {
679  ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix));
680  }
681  }
682 
683  int BaseApplication::main(const std::vector<std::string> &args)
684  {
685  // Start the plugin framework and all installed plug-ins according with
686  // their auto-start setting.
687  QStringList arguments;
688 
689  for (auto const &arg : args)
690  {
691  arguments.push_back(QString::fromStdString(arg));
692  }
693 
694  if (d->m_Splashscreen != 0)
695  {
696  // a splash screen is displayed,
697  // creating the closing callback
698  d->m_SplashscreenClosingCallback = new SplashCloserCallback(d->m_Splashscreen);
699  }
700 
701  return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt();
702  }
703 
704  void BaseApplication::defineOptions(Poco::Util::OptionSet &options)
705  {
706  Poco::Util::Option helpOption("help", "h", "print this help text");
707  helpOption.callback(Poco::Util::OptionCallback<BaseApplication>(this, &BaseApplication::printHelp));
708  options.addOption(helpOption);
709 
710  Poco::Util::Option newInstanceOption(
711  ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application");
712  newInstanceOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
713  options.addOption(newInstanceOption);
714 
715  Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache");
716  cleanOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleClean));
717  options.addOption(cleanOption);
718 
719  Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched");
720  productOption.argument("<id>").binding(PROP_PRODUCT.toStdString());
721  options.addOption(productOption);
722 
723  Poco::Util::Option appOption(
724  ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed");
725  appOption.argument("<id>").binding(PROP_APPLICATION.toStdString());
726  options.addOption(appOption);
727 
728  Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file");
729  provOption.argument("<prov file>").binding(ARG_PROVISIONING.toStdString());
730  options.addOption(provOption);
731 
732  Poco::Util::Option storageDirOption(
733  ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data");
734  storageDirOption.argument("<dir>").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString());
735  options.addOption(storageDirOption);
736 
737  Poco::Util::Option consoleLogOption(ARG_CONSOLELOG.toStdString(), "", "log messages to the console");
738  consoleLogOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
739  options.addOption(consoleLogOption);
740 
741  Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode");
742  debugOption.argument("<options file>", false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString());
743  options.addOption(debugOption);
744 
745  Poco::Util::Option forcePluginOption(
746  ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name");
747  forcePluginOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
748  options.addOption(forcePluginOption);
749 
750  Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library");
751  preloadLibsOption.argument("<library>")
752  .repeatable(true)
753  .callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handlePreloadLibraryOption));
754  options.addOption(preloadLibsOption);
755 
756  Poco::Util::Option testPluginOption(ARG_TESTPLUGIN.toStdString(), "", "the plug-in to be tested");
757  testPluginOption.argument("<id>").binding(PROP_TESTPLUGIN.toStdString());
758  options.addOption(testPluginOption);
759 
760  Poco::Util::Option testAppOption(ARG_TESTAPPLICATION.toStdString(), "", "the application to be tested");
761  testAppOption.argument("<id>").binding(PROP_TESTAPPLICATION.toStdString());
762  options.addOption(testAppOption);
763 
764  Poco::Util::Option noRegistryCacheOption(
765  ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry");
766  noRegistryCacheOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
767  options.addOption(noRegistryCacheOption);
768 
769  Poco::Util::Option noLazyRegistryCacheLoadingOption(
770  ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry");
771  noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
772  options.addOption(noLazyRegistryCacheLoadingOption);
773 
774  Poco::Util::Option registryMultiLanguageOption(
775  ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry");
776  registryMultiLanguageOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
777  options.addOption(registryMultiLanguageOption);
778 
779  Poco::Util::Option splashScreenOption(ARG_SPLASH_IMAGE.toStdString(), "", "optional picture to use as a splash screen");
780  splashScreenOption.argument("<filename>").binding(ARG_SPLASH_IMAGE.toStdString());
781  options.addOption(splashScreenOption);
782 
783  Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list");
784  xargsOption.argument("<args>").binding(ARG_XARGS.toStdString());
785  options.addOption(xargsOption);
786 
787  Poco::Util::Application::defineOptions(options);
788  }
789 
791  {
792  return ctkPluginFrameworkLauncher::getPluginFramework();
793  }
794 
795  ctkPluginContext *BaseApplication::getFrameworkContext() const
796  {
798  if (framework)
799  return framework->getPluginContext();
800  return nullptr;
801  }
802 
803  void BaseApplication::initializeSplashScreen(QCoreApplication * application) const
804  {
805  QVariant pixmapFileNameProp = d->getProperty(ARG_SPLASH_IMAGE);
806  if (!pixmapFileNameProp.isNull()) {
807  QString pixmapFileName = pixmapFileNameProp.toString();
808  QFileInfo checkFile(pixmapFileName);
809  if (checkFile.exists() && checkFile.isFile()) {
810  QPixmap pixmap(checkFile.absoluteFilePath());
811  d->m_Splashscreen = new QSplashScreen(pixmap, Qt::WindowStaysOnTopHint);
812  d->m_Splashscreen->show();
813  application->processEvents();
814  }
815  }
816  }
817 
818  QHash<QString, QVariant> BaseApplication::getFrameworkProperties() const { return d->m_FWProps; }
819 
821  {
822  this->init(d->m_Argc, d->m_Argv);
823  return Application::run();
824  }
825 
826  void BaseApplication::setProperty(const QString &property, const QVariant &value) { d->m_FWProps[property] = value; }
827  QVariant BaseApplication::getProperty(const QString &property) const { return d->getProperty(property); }
828 }
static QString ARG_PLUGIN_CACHE
ctkPluginContext * getFrameworkContext() const
QString getProvisioningFilePath() const
QVariant getProperty(const QString &property) const
void setPreloadLibraries(const QStringList &libraryBaseNames)
void setOrganizationDomain(const QString &name)
void setSafeMode(bool safeMode)
void initializeSplashScreen(QCoreApplication *application) const
#define MITK_INFO
Definition: mitkLogMacros.h:22
static QString ARG_APPLICATION
#define MITK_ERROR
Definition: mitkLogMacros.h:24
static QString PROP_TESTAPPLICATION
QString getOrganizationName() const
DataCollection - Class to facilitate loading/accessing structured data.
static QString ARG_PLUGIN_DIRS
static QString PROP_TESTPLUGIN
static QString PROP_REGISTRY_MULTI_LANGUAGE
static QString ARG_REGISTRY_MULTI_LANGUAGE
static QString PROP_NO_REGISTRY_CACHE
static QString ARG_STORAGE_DIR
static QString PROP_NEWINSTANCE
static QString ARG_FORCE_PLUGIN_INSTALL
void setProperty(const QString &property, const QVariant &value)
The custom viewer plugin implements simple viewer functionality presented in a customized look and feel It was developed to demonstrate extensibility and customizability of the blueberry application framework As an example for the GUI customization capabilities provided by the BlueBerry application framework
static QString ARG_SPLASH_IMAGE
QString getApplicationName() const
QSharedPointer< ctkPluginFramework > getFramework() const
void initialize(Poco::Util::Application &self) override
QString getOrganizationDomain() const
QStringList getPreloadLibraries() const
void setOrganizationName(const QString &name)
static QString ARG_PROVISIONING
void setSingleMode(bool singleMode)
void defineOptions(Poco::Util::OptionSet &options) override
void setProvisioningFilePath(const QString &filePath)
unsigned int uint
static QString ARG_TESTAPPLICATION
static QString PROP_NO_LAZY_REGISTRY_CACHE_LOADING
BaseApplication(int argc, char **argv)
static QString ARG_NO_REGISTRY_CACHE
void setApplicationName(const QString &name)
virtual QString getCTKFrameworkStorageDir() const
static QString PROP_APPLICATION
virtual void initializeCppMicroServices()
static QString ARG_NEWINSTANCE
QHash< QString, QVariant > getFrameworkProperties() const
virtual void initializeLibraryPaths()
int main(const std::vector< std::string > &args) override
virtual QCoreApplication * getQApplication() const
static void SetStoragePath(const std::string &path)
static QString ARG_NO_LAZY_REGISTRY_CACHE_LOADING
void printHelp(const std::string &name, const std::string &value)
static QString PROP_FORCE_PLUGIN_INSTALL
static QString ARG_PRELOAD_LIBRARY
uint qHash(const berry::Object &o)