22 #include <Poco/Util/HelpFormatter.h> 24 #include <ctkPluginFramework.h> 25 #include <ctkPluginFramework_global.h> 26 #include <ctkPluginFrameworkLauncher.h> 30 #include <vtkOpenGLRenderWindow.h> 31 #include <QVTKOpenGLWidget.h> 33 #include <QCoreApplication> 37 #include <QSplashScreen> 38 #include <QStandardPaths> 43 void outputQtMessage(QtMsgType type,
const QMessageLogContext&,
const QString& msg)
45 auto message = msg.toStdString();
105 class SplashCloserCallback :
public QRunnable
108 SplashCloserCallback(QSplashScreen* splashscreen)
109 : m_Splashscreen(splashscreen)
115 this->m_Splashscreen->close();
119 QSplashScreen *m_Splashscreen;
122 struct BaseApplication::Impl
124 ctkProperties m_FWProps;
126 QCoreApplication *m_QApp;
132 std::vector<char*> m_Argv_macOS;
137 QString m_OrgaDomain;
142 QSplashScreen *m_Splashscreen;
143 SplashCloserCallback *m_SplashscreenClosingCallback;
145 QStringList m_PreloadLibs;
148 Impl(
int argc,
char **argv)
156 m_Splashscreen(nullptr),
157 m_SplashscreenClosingCallback(nullptr)
163 m_Argv_macOS.reserve(argc);
165 const char psn[] =
"-psn";
167 for (decltype(argc) i = 0; i < argc; ++i)
169 if (0 == strncmp(argv[i], psn,
sizeof(psn)))
172 m_Argv_macOS.push_back(argv[i]);
175 m_Argc =
static_cast<decltype(m_Argc)
>(m_Argv_macOS.size());
176 m_Argv = m_Argv_macOS.data();
182 delete m_SplashscreenClosingCallback;
183 delete m_Splashscreen;
187 QVariant getProperty(
const QString &property)
const 189 auto iter = m_FWProps.find(property);
191 return m_FWProps.end() != iter
196 void handleBooleanOption(
const std::string &name,
const std::string &)
198 auto fwKey = QString::fromStdString(name);
201 if (ARG_CONSOLELOG == fwKey)
202 fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG;
206 m_FWProps[fwKey] =
true;
209 void handlePreloadLibraryOption(
const std::string &,
const std::string &value)
211 m_PreloadLibs.push_back(QString::fromStdString(value));
214 void handleClean(
const std::string &,
const std::string &)
216 m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
219 void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration)
222 Poco::Util::LayeredConfiguration::Keys keys;
224 Poco::Util::LayeredConfiguration::Keys keyStack;
225 configuration.keys(keyStack);
227 std::vector<std::string> keyChain;
229 while (!keyStack.empty())
231 const auto currSubKey = keyStack.back();
233 if (!keyChain.empty() && keyChain.back() == currSubKey)
240 Poco::Util::LayeredConfiguration::Keys subKeys;
241 configuration.keys(currSubKey, subKeys);
245 std::string finalKey;
248 for (
const auto key : keyChain)
249 finalKey += key +
'.';
251 finalKey += currSubKey;
252 keys.push_back(finalKey);
256 keyChain.push_back(currSubKey);
258 for (
const auto key : subKeys)
259 keyStack.push_back(key);
263 for (
const auto key : keys)
265 if (configuration.hasProperty(key))
268 auto qKey = QString::fromStdString(key);
269 m_FWProps[qKey] = QString::fromStdString(configuration.getString(key));
274 void parseProvisioningFile(
const QString &filePath)
277 if (filePath.isEmpty())
280 auto consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool();
283 QFileInfo provFile(filePath);
284 QStringList pluginsToStart;
286 if (provFile.exists())
288 MITK_INFO(consoleLog) <<
"Using provisioning file: " << qPrintable(provFile.absoluteFilePath());
289 ProvisioningInfo provInfo(provFile.absoluteFilePath());
293 if (provInfo.getPluginDirs().empty())
295 MITK_ERROR <<
"Cannot search for provisioning file, the retrieved directory list is empty.\n" 296 <<
"This can happen if there are some special non-ASCII characters in the install path.";
300 for(
const auto pluginPath : provInfo.getPluginDirs())
301 ctkPluginFrameworkLauncher::addSearchPath(pluginPath);
303 auto pluginUrlsToStart = provInfo.getPluginsToStart();
305 for (
const auto url : pluginUrlsToStart)
306 pluginsToStart.push_back(url.toString());
311 MITK_INFO(consoleLog) <<
"Provisionig file does not exist.";
314 if (!pluginsToStart.isEmpty())
316 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);
328 d(new Impl(argc, argv))
339 Poco::Util::HelpFormatter help(this->options());
340 help.setAutoIndent();
341 help.setCommand(this->commandName());
342 help.format(std::cout);
350 qApp->setApplicationName(name);
357 return nullptr != qApp
358 ? qApp->applicationName()
365 qApp->setOrganizationName(name);
367 d->m_OrgaName = name;
372 return nullptr != qApp
373 ? qApp->organizationName()
380 qApp->setOrganizationDomain(domain);
382 d->m_OrgaDomain = domain;
387 return nullptr != qApp
388 ? qApp->organizationDomain()
397 d->m_SingleMode = singleMode;
402 return d->m_SingleMode;
407 if (
nullptr != qApp &&
nullptr == d->m_QApp)
410 d->m_SafeMode = safeMode;
419 return d->m_SafeMode;
424 d->m_PreloadLibs = libraryBaseNames;
429 return d->m_PreloadLibs;
434 d->m_ProvFile = filePath;
439 auto provFilePath = d->m_ProvFile;
442 if (provFilePath.isNull() &&
nullptr != qApp)
444 QFileInfo appFilePath(QCoreApplication::applicationFilePath());
445 QDir basePath(QCoreApplication::applicationDirPath());
447 auto provFileName = appFilePath.baseName() +
".provisioning";
449 QFileInfo provFile(basePath.absoluteFilePath(provFileName));
463 if (!provFile.exists())
468 provFile = basePath.absoluteFilePath(provFileName);
472 if (provFile.exists())
474 provFilePath = provFile.absoluteFilePath();
480 provFile.setFile(basePath.absoluteFilePath(provFileName));
482 if (provFile.exists())
483 provFilePath = provFile.absoluteFilePath();
510 qInstallMessageHandler(outputQtMessage);
516 Poco::Util::Application::initialize(
self);
522 QTime time = QTime::currentTime();
523 qsrand((
uint)time.msec());
528 this->loadConfiguration();
533 d->initializeCTKPluginFrameworkProperties(this->config());
542 if (!storageDir.isEmpty())
543 d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir;
546 this->initializeLibraryPaths();
550 if (!preloadLibs.isEmpty())
551 d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs;
557 this->initializeCppMicroServices();
564 ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps);
575 pfw->waitForStop(10000);
578 Poco::Util::Application::uninitialize();
601 storageDir = handleNewAppInstance(static_cast<QtSingleApplication *>(d->m_QApp),
605 if (storageDir.isEmpty())
614 storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/" +
616 storageDir += QString::number(
qHash(QCoreApplication::applicationDirPath())) +
"/";
624 auto storageDir = this->
getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString();
626 if (!storageDir.isEmpty())
634 vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(0);
636 auto defaultFormat = QVTKOpenGLWidget::defaultFormat();
637 defaultFormat.setSamples(0);
638 QSurfaceFormat::setDefaultFormat(defaultFormat);
641 QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
644 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
648 :
static_cast<QCoreApplication*
>(
new QmitkSafeApplication(d->m_Argc, d->m_Argv, this->getSafeMode()));
656 QStringList suffixes;
657 suffixes <<
"plugins";
660 suffixes <<
"bin/plugins";
662 suffixes <<
"bin/" CMAKE_INTDIR
"/plugins";
665 suffixes <<
"lib/plugins";
667 suffixes <<
"lib/" CMAKE_INTDIR
"/plugins";
672 suffixes <<
"../../plugins";
676 QDir appDir(QCoreApplication::applicationDirPath());
681 for (
const auto suffix : suffixes)
682 ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix));
688 QStringList arguments;
690 for (
auto const &arg : args)
691 arguments.push_back(QString::fromStdString(arg));
693 if (
nullptr != d->m_Splashscreen)
696 d->m_SplashscreenClosingCallback =
new SplashCloserCallback(d->m_Splashscreen);
699 return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt();
704 Poco::Util::Option helpOption(
"help",
"h",
"print this help text");
706 options.addOption(helpOption);
708 Poco::Util::Option newInstanceOption(
ARG_NEWINSTANCE.toStdString(),
"",
"forces a new instance of this application");
709 newInstanceOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
710 options.addOption(newInstanceOption);
712 Poco::Util::Option cleanOption(
ARG_CLEAN.toStdString(),
"",
"cleans the plugin cache");
713 cleanOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleClean));
714 options.addOption(cleanOption);
716 Poco::Util::Option productOption(
ARG_PRODUCT.toStdString(),
"",
"the id of the product to be launched");
717 productOption.argument(
"<id>").binding(
PROP_PRODUCT.toStdString());
718 options.addOption(productOption);
720 Poco::Util::Option appOption(
ARG_APPLICATION.toStdString(),
"",
"the id of the application extension to be executed");
722 options.addOption(appOption);
724 Poco::Util::Option provOption(
ARG_PROVISIONING.toStdString(),
"",
"the location of a provisioning file");
726 options.addOption(provOption);
728 Poco::Util::Option storageDirOption(
ARG_STORAGE_DIR.toStdString(),
"",
"the location for storing persistent application data");
729 storageDirOption.argument(
"<dir>").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString());
730 options.addOption(storageDirOption);
732 Poco::Util::Option consoleLogOption(
ARG_CONSOLELOG.toStdString(),
"",
"log messages to the console");
733 consoleLogOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
734 options.addOption(consoleLogOption);
736 Poco::Util::Option debugOption(
ARG_DEBUG.toStdString(),
"",
"enable debug mode");
737 debugOption.argument(
"<options file>",
false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString());
738 options.addOption(debugOption);
740 Poco::Util::Option forcePluginOption(
ARG_FORCE_PLUGIN_INSTALL.toStdString(),
"",
"force installing plug-ins with same symbolic name");
741 forcePluginOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
742 options.addOption(forcePluginOption);
744 Poco::Util::Option preloadLibsOption(
ARG_PRELOAD_LIBRARY.toStdString(),
"",
"preload a library");
745 preloadLibsOption.argument(
"<library>")
747 .callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handlePreloadLibraryOption));
748 options.addOption(preloadLibsOption);
750 Poco::Util::Option noRegistryCacheOption(
ARG_NO_REGISTRY_CACHE.toStdString(),
"",
"do not use a cache for the registry");
751 noRegistryCacheOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
752 options.addOption(noRegistryCacheOption);
755 noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
756 options.addOption(noLazyRegistryCacheLoadingOption);
758 Poco::Util::Option registryMultiLanguageOption(
ARG_REGISTRY_MULTI_LANGUAGE.toStdString(),
"",
"enable multi-language support for the registry");
759 registryMultiLanguageOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
760 options.addOption(registryMultiLanguageOption);
762 Poco::Util::Option splashScreenOption(
ARG_SPLASH_IMAGE.toStdString(),
"",
"optional picture to use as a splash screen");
763 splashScreenOption.argument(
"<filename>").binding(
ARG_SPLASH_IMAGE.toStdString());
764 options.addOption(splashScreenOption);
766 Poco::Util::Option xargsOption(
ARG_XARGS.toStdString(),
"",
"Extended argument list");
767 xargsOption.argument(
"<args>").binding(
ARG_XARGS.toStdString());
768 options.addOption(xargsOption);
770 Poco::Util::Application::defineOptions(options);
775 return ctkPluginFrameworkLauncher::getPluginFramework();
791 if (!pixmapFileNameProp.isNull())
793 auto pixmapFileName = pixmapFileNameProp.toString();
794 QFileInfo checkFile(pixmapFileName);
796 if (checkFile.exists() && checkFile.isFile())
798 QPixmap pixmap(checkFile.absoluteFilePath());
800 d->m_Splashscreen =
new QSplashScreen(pixmap, Qt::WindowStaysOnTopHint);
801 d->m_Splashscreen->show();
803 application->processEvents();
815 this->init(d->m_Argc, d->m_Argv);
816 return Application::run();
821 d->m_FWProps[property] = value;
826 return d->getProperty(property);
836 auto app =
dynamic_cast<QtSingleApplication*
>(this->
getQApplication());
841 mitkThrow() <<
"Method not implemented.";
846 auto app =
dynamic_cast<QtSingleApplication*
>(this->
getQApplication());
849 app->sendMessage(msg);
851 mitkThrow() <<
"Method not implemented.";
virtual QString getCTKFrameworkStorageDir() const
static const QString ARG_DEBUG
void setPreloadLibraries(const QStringList &libraryBaseNames)
void setOrganizationDomain(const QString &name)
void setSafeMode(bool safeMode)
static const QString ARG_CONSOLELOG
void initializeSplashScreen(QCoreApplication *application) const
QString getApplicationName() const
QStringList getPreloadLibraries() const
static const QString ARG_REGISTRY_MULTI_LANGUAGE
static const QString ARG_CLEAN
static const QString ARG_PLUGIN_CACHE
static const QString ARG_XARGS
DataCollection - Class to facilitate loading/accessing structured data.
QSharedPointer< ctkPluginFramework > getFramework() const
QVariant getProperty(const QString &property) const
static const QString PROP_REGISTRY_MULTI_LANGUAGE
static const QString PROP_APPLICATION
static const QString PROP_NO_REGISTRY_CACHE
static const QString ARG_SPLASH_IMAGE
static const QString ARG_NO_REGISTRY_CACHE
static const QString ARG_PRELOAD_LIBRARY
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
ctkPluginContext * getFrameworkContext() const
static const QString ARG_NEWINSTANCE
void initialize(Poco::Util::Application &self) override
static const QString ARG_HOME
void setOrganizationName(const QString &name)
void setSingleMode(bool singleMode)
void defineOptions(Poco::Util::OptionSet &options) override
static const QString ARG_PLUGIN_DIRS
void setProvisioningFilePath(const QString &filePath)
static const QString ARG_FORCE_PLUGIN_INSTALL
void sendMessage(const QByteArray)
static const QString ARG_PRODUCT
static const QString PROP_PRODUCT
static const QString ARG_APPLICATION
static const QString PROP_NEWINSTANCE
BaseApplication(int argc, char **argv)
void installTranslator(QTranslator *)
void setApplicationName(const QString &name)
static const QString PROP_NO_LAZY_REGISTRY_CACHE_LOADING
static const QString ARG_PROVISIONING
static const QString ARG_NO_LAZY_REGISTRY_CACHE_LOADING
virtual void initializeCppMicroServices()
QHash< QString, QVariant > getFrameworkProperties() const
QString getOrganizationName() const
QString getOrganizationDomain() const
virtual void initializeLibraryPaths()
virtual QCoreApplication * getQApplication() const
int main(const std::vector< std::string > &args) override
static const QString ARG_STORAGE_DIR
void uninitialize() override
static void SetStoragePath(const std::string &path)
void printHelp(const std::string &name, const std::string &value)
~BaseApplication() override
QString getProvisioningFilePath() const
bool getSingleMode() const
static const QString PROP_FORCE_PLUGIN_INSTALL
uint qHash(const berry::Object &o)