24 #include <ctkPluginConstants.h>
25 #include <ctkPluginFramework.h>
26 #include <ctkPluginFrameworkLauncher.h>
27 #include <ctkPluginFramework_global.h>
31 #include <Poco/Util/HelpFormatter.h>
33 #include <QSplashScreen>
36 #include <QCoreApplication>
38 #include <QDesktopServices>
40 #include <QStringList>
82 class SplashCloserCallback :
public QRunnable
85 SplashCloserCallback(QSplashScreen* splashscreen)
87 this->m_Splashscreen = splashscreen;
92 this->m_Splashscreen->close();
96 QSplashScreen* m_Splashscreen;
99 struct BaseApplication::Impl
101 ctkProperties m_FWProps;
103 QScopedPointer<QCoreApplication> m_QApp;
110 QString m_OrgaDomain;
115 QSplashScreen* m_Splashscreen;
116 SplashCloserCallback* m_SplashscreenClosingCallback;
118 QStringList m_PreloadLibs;
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)
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)
139 if (QString::fromLatin1(m_Argv[i]).contains(
"-psn"))
145 newArgs[i] = m_Argv[i];
156 QVariant
getProperty(
const QString &property)
const
158 auto iter = m_FWProps.find(property);
159 return iter == m_FWProps.end() ? QVariant() : iter.value();
162 void handleBooleanOption(
const std::string &name,
const std::string & )
164 QString fwKey = QString::fromStdString(name);
169 fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG;
174 m_FWProps[fwKey] =
true;
177 void handlePreloadLibraryOption(
const std::string & ,
const std::string &value)
179 m_PreloadLibs.push_back(QString::fromStdString(value));
182 void handleClean(
const std::string & ,
const std::string & )
184 m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
187 void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration)
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())
196 std::string currSubKey = keyStack.back();
197 if (!keyChain.empty() && keyChain.back() == currSubKey)
203 Poco::Util::LayeredConfiguration::Keys subKeys;
204 configuration.keys(currSubKey, subKeys);
208 std::string finalKey;
209 for (
auto k = keyChain.begin(); k != keyChain.end(); ++k)
211 finalKey += *k +
".";
213 finalKey += currSubKey;
214 keys.push_back(finalKey);
218 keyChain.push_back(currSubKey);
219 for (
auto s : subKeys)
221 keyStack.push_back(s);
226 for (
auto key : keys)
228 QString qKey = QString::fromStdString(key);
229 if (configuration.hasProperty(key))
232 m_FWProps[qKey] = QString::fromStdString(configuration.getString(key));
237 void parseProvisioningFile(
const QString &filePath)
240 if (filePath.isEmpty())
243 bool consoleLog = this->
getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool();
246 QStringList pluginsToStart;
248 QFileInfo provFile(filePath);
250 if (provFile.exists())
252 MITK_INFO(consoleLog) <<
"Using provisioning file: " << qPrintable(provFile.absoluteFilePath());
253 ProvisioningInfo provInfo(provFile.absoluteFilePath());
257 if (provInfo.getPluginDirs().empty())
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.";
264 foreach (QString pluginPath, provInfo.getPluginDirs())
266 ctkPluginFrameworkLauncher::addSearchPath(pluginPath);
270 QList<QUrl> pluginUrlsToStart = provInfo.getPluginsToStart();
271 for (
auto url : pluginUrlsToStart)
273 pluginsToStart.push_back(url.toString());
310 MITK_INFO(consoleLog) <<
"No provisioning file set.";
313 if (!pluginsToStart.isEmpty())
315 m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart;
320 ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY);
321 m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] =
static_cast<int>(startOptions);
332 if (d->m_Splashscreen != 0)
334 delete(d->m_Splashscreen);
336 if (d->m_SplashscreenClosingCallback != 0)
338 delete(d->m_SplashscreenClosingCallback);
344 Poco::Util::HelpFormatter help(this->options());
345 help.setAutoIndent();
346 help.setCommand(this->commandName());
347 help.format(std::cout);
356 qApp->setApplicationName(name);
365 return qApp->applicationName();
374 qApp->setOrganizationName(name);
376 d->m_OrgaName = name;
382 return qApp->organizationName();
383 return d->m_OrgaName;
390 qApp->setOrganizationDomain(domain);
392 d->m_OrgaDomain = domain;
398 return qApp->organizationDomain();
399 return d->m_OrgaDomain;
406 d->m_SingleMode = singleMode;
412 if (qApp && !d->m_QApp)
414 d->m_SafeMode = safeMode;
431 d->m_PreloadLibs = libraryBaseNames;
438 QString provFilePath = d->m_ProvFile;
441 if (provFilePath.isNull() && qApp)
443 QFileInfo appFilePath(QCoreApplication::applicationFilePath());
444 QDir basePath(QCoreApplication::applicationDirPath());
446 QString provFileName = appFilePath.baseName() +
".provisioning";
448 QFileInfo provFile(basePath.absoluteFilePath(provFileName));
462 if (!provFile.exists())
467 provFile = basePath.absoluteFilePath(provFileName);
471 if (provFile.exists())
473 provFilePath = provFile.absoluteFilePath();
479 provFile.setFile(basePath.absoluteFilePath(provFileName));
480 if (provFile.exists())
482 provFilePath = provFile.absoluteFilePath();
513 Poco::Util::Application::initialize(
self);
519 QTime time = QTime::currentTime();
520 qsrand((
uint)time.msec());
525 this->loadConfiguration();
530 d->initializeCTKPluginFrameworkProperties(this->config());
538 if (!storageDir.isEmpty())
540 d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir;
546 if (!preloadLibs.isEmpty())
548 d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs;
562 ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps);
573 pfw->waitForStop(10000);
576 Poco::Util::Application::uninitialize();
592 storageDir = handleNewAppInstance(
593 static_cast<QtSingleApplication *>(d->m_QApp.data()), d->m_Argc, d->m_Argv,
ARG_NEWINSTANCE);
596 if (storageDir.isEmpty())
605 storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/" +
607 storageDir += QString::number(
qHash(QCoreApplication::applicationDirPath())) +
"/";
614 QString storageDir = this->
getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString();
616 if (!storageDir.isEmpty())
624 QCoreApplication *qCoreApp = qApp;
628 qCoreApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
631 qCoreApp->setAttribute(Qt::AA_ShareOpenGLContexts);
642 safeApp->setSafeMode(d->m_SafeMode);
645 d->m_QApp.reset(qCoreApp);
652 QStringList suffixes;
653 suffixes <<
"plugins";
655 suffixes <<
"bin/plugins";
657 suffixes <<
"bin/" CMAKE_INTDIR
"/plugins";
660 suffixes <<
"lib/plugins";
662 suffixes <<
"lib/" CMAKE_INTDIR
"/plugins";
667 suffixes <<
"../../plugins";
671 QDir appDir(QCoreApplication::applicationDirPath());
677 foreach (QString suffix, suffixes)
679 ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix));
687 QStringList arguments;
689 for (
auto const &arg : args)
691 arguments.push_back(QString::fromStdString(arg));
694 if (d->m_Splashscreen != 0)
698 d->m_SplashscreenClosingCallback =
new SplashCloserCallback(d->m_Splashscreen);
701 return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt();
706 Poco::Util::Option helpOption(
"help",
"h",
"print this help text");
708 options.addOption(helpOption);
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);
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);
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);
723 Poco::Util::Option appOption(
724 ARG_APPLICATION.toStdString(),
"",
"the id of the application extension to be executed");
726 options.addOption(appOption);
728 Poco::Util::Option provOption(
ARG_PROVISIONING.toStdString(),
"",
"the location of a provisioning file");
730 options.addOption(provOption);
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);
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);
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);
745 Poco::Util::Option forcePluginOption(
747 forcePluginOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
748 options.addOption(forcePluginOption);
750 Poco::Util::Option preloadLibsOption(
ARG_PRELOAD_LIBRARY.toStdString(),
"",
"preload a library");
751 preloadLibsOption.argument(
"<library>")
753 .callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handlePreloadLibraryOption));
754 options.addOption(preloadLibsOption);
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);
760 Poco::Util::Option testAppOption(
ARG_TESTAPPLICATION.toStdString(),
"",
"the application to be tested");
762 options.addOption(testAppOption);
764 Poco::Util::Option noRegistryCacheOption(
766 noRegistryCacheOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
767 options.addOption(noRegistryCacheOption);
769 Poco::Util::Option noLazyRegistryCacheLoadingOption(
771 noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
772 options.addOption(noLazyRegistryCacheLoadingOption);
774 Poco::Util::Option registryMultiLanguageOption(
776 registryMultiLanguageOption.callback(Poco::Util::OptionCallback<Impl>(d.data(), &Impl::handleBooleanOption));
777 options.addOption(registryMultiLanguageOption);
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);
783 Poco::Util::Option xargsOption(
ARG_XARGS.toStdString(),
"",
"Extended argument list");
784 xargsOption.argument(
"<args>").binding(
ARG_XARGS.toStdString());
785 options.addOption(xargsOption);
787 Poco::Util::Application::defineOptions(options);
792 return ctkPluginFrameworkLauncher::getPluginFramework();
799 return framework->getPluginContext();
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();
822 this->init(d->m_Argc, d->m_Argv);
823 return Application::run();
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
static QString ARG_CONSOLELOG
static QString ARG_APPLICATION
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)
bool getSingleMode() const
void defineOptions(Poco::Util::OptionSet &options) override
void setProvisioningFilePath(const QString &filePath)
static QString PROP_PRODUCT
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
static QString ARG_PRODUCT
void uninitialize() override
virtual QCoreApplication * getQApplication() const
static void SetStoragePath(const std::string &path)
static QString ARG_TESTPLUGIN
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)