diff --git a/Modules/AppUtil/include/mitkBaseApplication.h b/Modules/AppUtil/include/mitkBaseApplication.h index c836ba207f..a3144a56df 100644 --- a/Modules/AppUtil/include/mitkBaseApplication.h +++ b/Modules/AppUtil/include/mitkBaseApplication.h @@ -1,333 +1,323 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef MITKBASEAPPLICATION_H -#define MITKBASEAPPLICATION_H +#ifndef mitkBaseApplication_h +#define mitkBaseApplication_h #include #include -#include -#include #include -#include - -class QCoreApplication; +#include class ctkPluginContext; class ctkPluginFramework; +class QTranslator; namespace mitk { /** - * A utility classes for starting up BlueBerry applications. + * A utility class for starting BlueBerry applications. * - * In the simplest case, a user creates an instance of this - * class and just calls run() which launches a CTK Plugin - * Framework instance and executes the default application - * registered by a plug-in via the org.blueberry.osgi.applications - * extension point. + * In the simplest case, create an instance of this class and call run(). + * This will launch a CTK plugin framework instance and execute the + * default application registered by a plug-in via the + * org.blueberry.osgi.applications extension point. * * This class contains many convenience methods to: * - Put the application in \emph{safe mode} which catches unhandled * exceptions thrown in the Qt event loop and displays an error - * message + * message. * - Put the application in \emph{single mode} which by default * sends the command line arguments to an already running instance * of the same application instead of creating a second instance. * - Add a list of library names which should be pre-loaded at * application start-up, e.g. to speed up the initial launch during * the caching process of the plug-in meta-data. * - Set a custom provisioning file to start a specific set of CTK * plug-ins during application start-up. - * - Set and get CTK Plugin Framework properties + * - Set and get CTK plugin framework properties * - * The behavior can further be customized by deriving from - * BaseApplication and overriding specific methods, such as: - * - initializeLibraryPaths() to add specific library / plugin search - * paths - * - defineOptions(Poco::Util::OptionSet&) to define a custom set - * of command line options + * The behavior can further be customized by deriving from BaseApplication + * and overriding specific methods, such as: + * - initializeLibraryPaths() to add specific library / plugin search paths + * - defineOptions(Poco::Util::OptionSet&) to define a custom set of + * command line options * - getQApplication() to provide a custom QCoreApplication instance * - * A simple but complete usage example: + * A simple but complete example: * * #include * - * int main(int argc, char** argv) + * int main(int argc, char* argv[]) * { * mitk::BaseApplication app(argc, argv); * app.setApplicationName("MyApp"); * app.setOrganizationName("MyOrganization"); * * // Run the workbench * return app.run(); * } * */ class MITKAPPUTIL_EXPORT BaseApplication : public Poco::Util::Application { public: // Command line arguments - static const QString ARG_NEWINSTANCE; - static const QString ARG_CLEAN; static const QString ARG_APPLICATION; - static const QString ARG_PRODUCT; + static const QString ARG_CLEAN; + static const QString ARG_CONSOLELOG; + static const QString ARG_DEBUG; + static const QString ARG_FORCE_PLUGIN_INSTALL; static const QString ARG_HOME; - static const QString ARG_STORAGE_DIR; + static const QString ARG_NEWINSTANCE; + static const QString ARG_NO_LAZY_REGISTRY_CACHE_LOADING; + static const QString ARG_NO_REGISTRY_CACHE; static const QString ARG_PLUGIN_CACHE; static const QString ARG_PLUGIN_DIRS; - static const QString ARG_FORCE_PLUGIN_INSTALL; static const QString ARG_PRELOAD_LIBRARY; + static const QString ARG_PRODUCT; static const QString ARG_PROVISIONING; - static const QString ARG_DEBUG; - - static const QString ARG_CONSOLELOG; - static const QString ARG_TESTPLUGIN; - static const QString ARG_TESTAPPLICATION; - - static const QString ARG_NO_REGISTRY_CACHE; - static const QString ARG_NO_LAZY_REGISTRY_CACHE_LOADING; static const QString ARG_REGISTRY_MULTI_LANGUAGE; - static const QString ARG_SPLASH_IMAGE; - + static const QString ARG_STORAGE_DIR; + static const QString ARG_TESTAPPLICATION; + static const QString ARG_TESTPLUGIN; static const QString ARG_XARGS; - // BlueBerry specific Plugin Framework properties + // BlueBerry specific plugin framework properties - static const QString PROP_NEWINSTANCE; + static const QString PROP_APPLICATION; static const QString PROP_FORCE_PLUGIN_INSTALL; - static const QString PROP_NO_REGISTRY_CACHE; + static const QString PROP_NEWINSTANCE; static const QString PROP_NO_LAZY_REGISTRY_CACHE_LOADING; - static const QString PROP_REGISTRY_MULTI_LANGUAGE; - + static const QString PROP_NO_REGISTRY_CACHE; static const QString PROP_PRODUCT; - static const QString PROP_APPLICATION; - static const QString PROP_TESTPLUGIN; + static const QString PROP_REGISTRY_MULTI_LANGUAGE; static const QString PROP_TESTAPPLICATION; + static const QString PROP_TESTPLUGIN; BaseApplication(int argc, char **argv); ~BaseApplication() override; /** * Initialize the Qt library such that a QCoreApplication - * instance is available and e.g. Qt Widgets can be created. + * instance is available and e.g. Qt widgets can be created. * * This is usually not called directly by the user. */ void initializeQt(); /** * Launches the BlueBerry framework and runs the default application * or the one specified in the PROP_APPLICATION framework property. * * @return The return code of the application after it was shut down. */ int run() override; void printHelp(const std::string &name, const std::string &value); /** * Set the application name. Same as QCoreApplication::setApplicationName. * @param name The application name. */ void setApplicationName(const QString &name); QString getApplicationName() const; /** * Set the organization name. Same as QCoreApplication::setOrganizationName. * @param name The organization name. */ void setOrganizationName(const QString &name); QString getOrganizationName() const; /** * Set the organization domain. Same as QCoreApplication::setOrganizationDomain. * @param name The organization domain. */ void setOrganizationDomain(const QString &name); QString getOrganizationDomain() const; /** * Put the application in single mode, which by default only allows * a single instance of the application to be created. * * Calling this method after run() has been called has no effect. * * @param singleMode */ void setSingleMode(bool singleMode); bool getSingleMode() const; /** * Put the application in safe mode, catching exceptions from the * Qt event loop. * * @param safeMode */ void setSafeMode(bool safeMode); bool getSafeMode() const; /** * Set a list of library names or absoulte file paths * which should be loaded at application start-up. The name * and file path may contain a library version appended at the * end and separated by a '$' charactger. * * For example liborg_mitk_gui_qt_common$1.0. * Platform specific suffixes are appended automatically. * * @param libraryBaseNames A list of library base names. */ void setPreloadLibraries(const QStringList &libraryBaseNames); /** * Get the list of library base names which should be pre-loaded. * * @return A list of pre-loaded libraries. */ QStringList getPreloadLibraries() const; /** * Set the path to the provisioning file. * * By default a provisioning file located in the same directory * as the executable and named .provisioning * is loaded if it exists. To disable parsing of provisioning * files, use an empty string as the argument. Use a * null QString (QString::null) to reset to the * default behaviour. * * @param filePath An absolute file path to the provisioning file. */ void setProvisioningFilePath(const QString &filePath); /** * Get the file path to the provisioning file. * @return The provisioning file path. */ QString getProvisioningFilePath() const; void setProperty(const QString &property, const QVariant &value); QVariant getProperty(const QString &property) const; void installTranslator(QTranslator*); bool isRunning(); void sendMessage(const QByteArray); protected: void initialize(Poco::Util::Application &self) override; void uninitialize() override; int getArgc() const; char **getArgv() const; /** * Get the framework storage directory for the CTK plugin * framework. This method is called in the initialize(Poco::Util::Application&) * method. It must not be called without a QCoreApplications instance. * * @return The CTK Plugin Framework storage directory. */ virtual QString getCTKFrameworkStorageDir() const; /** * Initialize the CppMicroServices library. * * The default implementation set the CppMicroServices storage * path to the current ctkPluginConstants::FRAMEWORK_STORAGE property * value. * * This method is called in the initialize(Poco::Util::Application&) * after the CTK Plugin Framework storage directory property * was set. */ virtual void initializeCppMicroServices(); /** * Get the QCoreApplication object. * * This method is called in the initialize(Poco::Util::Application&) * method and must create a QCoreApplication instance if the * global qApp variable is not initialized yet. * * @return The current QCoreApplication instance. This method * never returns null. */ virtual QCoreApplication *getQApplication() const; /** * Add plugin library search paths to the CTK Plugin Framework. * * This method is called in the nitialize(Poco::Util::Application&) * method after getQApplication() was called. */ virtual void initializeLibraryPaths(); /** * Runs the application for which the platform was started. The platform * must be running. *

* The given argument is passed to the application being run. If it is an invalid QVariant * then the command line arguments used in starting the platform, and not consumed * by the platform code, are passed to the application as a QStringList. *

* @param argument the argument passed to the application. May be invalid * @return the result of running the application * @throws std::exception if anything goes wrong */ int main(const std::vector &args) override; /** * Define command line arguments * @param options */ void defineOptions(Poco::Util::OptionSet &options) override; QSharedPointer getFramework() const; ctkPluginContext *getFrameworkContext() const; /** * Get the initial properties for the CTK plugin framework. * * The returned map contains the initial framework properties for * initializing the CTK plugin framework. The value of specific * properties may change at runtime and differ from the initial * value. * * @return The initial CTK Plugin Framework properties. */ QHash getFrameworkProperties() const; /* * Initialize and display the splash screen if an image filename is given * */ void initializeSplashScreen(QCoreApplication * application) const; private: struct Impl; Impl* d; }; } #endif // MITKBASEAPPLICATION_H diff --git a/Modules/AppUtil/src/mitkBaseApplication.cpp b/Modules/AppUtil/src/mitkBaseApplication.cpp index abe8efb08b..15ad04cbeb 100644 --- a/Modules/AppUtil/src/mitkBaseApplication.cpp +++ b/Modules/AppUtil/src/mitkBaseApplication.cpp @@ -1,871 +1,869 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkBaseApplication.h" -#include "mitkLogMacros.h" -#include "mitkExceptionMacro.h" +#include -#include "QmitkSafeApplication.h" -#include "QmitkSingleApplication.h" -#include "mitkProvisioningInfo.h" +#include +#include +#include + +#include +#include + +#include -#include #include -#include #include +#include #include -#include +#include +#include -#include -#include -#include #include -#include -#include #include -#include +#include +#include +#include +#include #include -#include -#include - -#include -#include - namespace { void outputQtMessage(QtMsgType type, const QMessageLogContext&, const QString& msg) { auto message = msg.toStdString(); switch (type) { case QtDebugMsg: MITK_DEBUG << message; break; case QtInfoMsg: MITK_INFO << message; break; case QtWarningMsg: MITK_WARN << message; break; case QtCriticalMsg: MITK_ERROR << message; break; case QtFatalMsg: MITK_ERROR << message; abort(); default: MITK_INFO << message; break; } } } namespace mitk { - const QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance"; - const QString BaseApplication::ARG_CLEAN = "BlueBerry.clean"; const QString BaseApplication::ARG_APPLICATION = "BlueBerry.application"; - const QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; + const QString BaseApplication::ARG_CLEAN = "BlueBerry.clean"; + const QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog"; + const QString BaseApplication::ARG_DEBUG = "BlueBerry.debug"; + const QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins"; const QString BaseApplication::ARG_HOME = "BlueBerry.home"; - const QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir"; + const QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance"; + const QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading"; + const QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache"; const QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir"; const QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs"; - const QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins"; const QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary"; + const QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; const QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning"; - const QString BaseApplication::ARG_DEBUG = "BlueBerry.debug"; - const QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog"; - const QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin"; - const QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication"; - - const QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen"; - - const QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache"; - const QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading"; const QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage"; - + const QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen"; + const QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir"; + const QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication"; + const QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin"; const QString BaseApplication::ARG_XARGS = "xargs"; - const QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE; + const QString BaseApplication::PROP_APPLICATION = "blueberry.application"; const QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL; - const QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; + const QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE; const QString BaseApplication::PROP_NO_LAZY_REGISTRY_CACHE_LOADING = BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING; - const QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE; - + const QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; const QString BaseApplication::PROP_PRODUCT = "blueberry.product"; - const QString BaseApplication::PROP_APPLICATION = "blueberry.application"; - const QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin"; + const QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE; const QString BaseApplication::PROP_TESTAPPLICATION = "BlueBerry.testapplication"; + const QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin"; class SplashCloserCallback : public QRunnable { public: SplashCloserCallback(QSplashScreen* splashscreen) + : m_Splashscreen(splashscreen) { - this->m_Splashscreen = splashscreen; } void run() override { this->m_Splashscreen->close(); } private: - QSplashScreen* m_Splashscreen; + QSplashScreen *m_Splashscreen; // Owned by BaseApplication::Impl }; struct BaseApplication::Impl { ctkProperties m_FWProps; - QCoreApplication* m_QApp; + QCoreApplication *m_QApp; int m_Argc; char **m_Argv; #ifdef Q_OS_MAC std::vector m_Argv_macOS; #endif QString m_AppName; QString m_OrgaName; QString m_OrgaDomain; bool m_SingleMode; bool m_SafeMode; - QSplashScreen* m_Splashscreen; - SplashCloserCallback* m_SplashscreenClosingCallback; + QSplashScreen *m_Splashscreen; + SplashCloserCallback *m_SplashscreenClosingCallback; QStringList m_PreloadLibs; QString m_ProvFile; Impl(int argc, char **argv) : m_Argc(argc), m_Argv(argv), #ifdef Q_OS_MAC m_Argv_macOS(), #endif m_SingleMode(false), m_SafeMode(true), m_Splashscreen(nullptr), m_SplashscreenClosingCallback(nullptr) { #ifdef Q_OS_MAC /* On macOS the process serial number is passed as an command line argument (-psn_) - if the application is started the first time via the .app bundle. This option causes a - Poco exception. We remove it, if present. */ + in certain circumstances. This option causes a Poco exception. We remove it, if present. */ m_Argv_macOS.reserve(argc); const char psn[] = "-psn"; for (decltype(argc) i = 0; i < argc; ++i) { if (0 == strncmp(argv[i], psn, sizeof(psn))) continue; m_Argv_macOS.push_back(argv[i]); } m_Argc = static_cast(m_Argv_macOS.size()); m_Argv = m_Argv_macOS.data(); #endif } ~Impl() { delete m_SplashscreenClosingCallback; delete m_Splashscreen; delete m_QApp; } QVariant getProperty(const QString &property) const { auto iter = m_FWProps.find(property); - return iter == m_FWProps.end() ? QVariant() : iter.value(); + + return m_FWProps.end() != iter + ? iter.value() + : QVariant(); } - void handleBooleanOption(const std::string &name, const std::string & /*value*/) + void handleBooleanOption(const std::string &name, const std::string &) { - QString fwKey = QString::fromStdString(name); + auto fwKey = QString::fromStdString(name); - // translate some keys to proper framework properties - if (fwKey == ARG_CONSOLELOG) - { + // Translate some keys to proper framework properties + if (ARG_CONSOLELOG == fwKey) fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG; - } // For all other options we use the command line option name as the // framework property key. m_FWProps[fwKey] = true; } - void handlePreloadLibraryOption(const std::string & /*name*/, const std::string &value) + void handlePreloadLibraryOption(const std::string &, const std::string &value) { m_PreloadLibs.push_back(QString::fromStdString(value)); } - void handleClean(const std::string & /*name*/, const std::string & /*value*/) + void handleClean(const std::string &, const std::string &) { m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT; } void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration) { - // add all configuration key / value pairs as framework properties + // Add all configuration key/value pairs as framework properties Poco::Util::LayeredConfiguration::Keys keys; + Poco::Util::LayeredConfiguration::Keys keyStack; configuration.keys(keyStack); + std::vector keyChain; + while (!keyStack.empty()) { - std::string currSubKey = keyStack.back(); + const auto currSubKey = keyStack.back(); + if (!keyChain.empty() && keyChain.back() == currSubKey) { keyChain.pop_back(); keyStack.pop_back(); continue; } + Poco::Util::LayeredConfiguration::Keys subKeys; configuration.keys(currSubKey, subKeys); + if (subKeys.empty()) { - keyStack.pop_back(); std::string finalKey; - for (auto k = keyChain.begin(); k != keyChain.end(); ++k) - { - finalKey += *k + "."; - } + keyStack.pop_back(); + + for (const auto key : keyChain) + finalKey += key + '.'; + finalKey += currSubKey; keys.push_back(finalKey); } else { keyChain.push_back(currSubKey); - for (auto s : subKeys) - { - keyStack.push_back(s); - } + + for (const auto key : subKeys) + keyStack.push_back(key); } } - for (auto key : keys) + for (const auto key : keys) { - QString qKey = QString::fromStdString(key); if (configuration.hasProperty(key)) { - // ini and command line options overwrite already inserted keys + // .ini and command line options overwrite already inserted keys + auto qKey = QString::fromStdString(key); m_FWProps[qKey] = QString::fromStdString(configuration.getString(key)); } } } void parseProvisioningFile(const QString &filePath) { // Skip parsing if the file path is empty if (filePath.isEmpty()) return; - bool consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool(); - - // read initial plugins from a provisioning file - QStringList pluginsToStart; + auto consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool(); + // Read initial plugins from a provisioning file QFileInfo provFile(filePath); + QStringList pluginsToStart; if (provFile.exists()) { MITK_INFO(consoleLog) << "Using provisioning file: " << qPrintable(provFile.absoluteFilePath()); ProvisioningInfo provInfo(provFile.absoluteFilePath()); - // it can still happen, that the encoding is not compatible with the fromUtf8 function ( i.e. when manipulating - // the LANG variable - // in such case, the QStringList in provInfo is empty which we can easily check for + + // It can still happen that the encoding is not compatible with the fromUtf8 function (i.e. when + // manipulating the LANG variable). The QStringList in provInfo is empty then. if (provInfo.getPluginDirs().empty()) { MITK_ERROR << "Cannot search for provisioning file, the retrieved directory list is empty.\n" - << "This can occur if there are some special (non-ascii) characters in the install path."; + << "This can happen if there are some special non-ASCII characters in the install path."; } else { - foreach (QString pluginPath, provInfo.getPluginDirs()) - { + for(const auto pluginPath : provInfo.getPluginDirs()) ctkPluginFrameworkLauncher::addSearchPath(pluginPath); - } - // bool forcePluginOverwrite = this->getProperty(ARG_FORCE_PLUGIN_INSTALL).toBool(); - QList pluginUrlsToStart = provInfo.getPluginsToStart(); - for (auto url : pluginUrlsToStart) - { + auto pluginUrlsToStart = provInfo.getPluginsToStart(); + + for (const auto url : pluginUrlsToStart) pluginsToStart.push_back(url.toString()); - } } } else { - MITK_INFO(consoleLog) << "No provisioning file set."; + MITK_INFO(consoleLog) << "Provisionig file does not exist."; } if (!pluginsToStart.isEmpty()) { m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart; - // Use transient start with declared activation policy (this helps when - // the provisioning file changes and some plug-ins should not be installed - // in the application any more). + // Use transient start with declared activation policy (this helps when the provisioning file + // changes and some plug-ins should not be installed in the application any more). ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY); m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] = static_cast(startOptions); } } }; BaseApplication::BaseApplication(int argc, char **argv) : Application(), d(new Impl(argc, argv)) { } BaseApplication::~BaseApplication() { delete d; } - void BaseApplication::printHelp(const std::string & /*name*/, const std::string & /*value*/) + void BaseApplication::printHelp(const std::string &, const std::string &) { Poco::Util::HelpFormatter help(this->options()); help.setAutoIndent(); help.setCommand(this->commandName()); help.format(std::cout); exit(EXIT_OK); } void BaseApplication::setApplicationName(const QString &name) { if (nullptr != qApp) qApp->setApplicationName(name); d->m_AppName = name; } QString BaseApplication::getApplicationName() const { return nullptr != qApp ? qApp->applicationName() : d->m_AppName; } void BaseApplication::setOrganizationName(const QString &name) { if (nullptr != qApp) qApp->setOrganizationName(name); d->m_OrgaName = name; } QString BaseApplication::getOrganizationName() const { return nullptr != qApp ? qApp->organizationName() : d->m_OrgaName; } void BaseApplication::setOrganizationDomain(const QString &domain) { if (nullptr != qApp) qApp->setOrganizationDomain(domain); d->m_OrgaDomain = domain; } QString BaseApplication::getOrganizationDomain() const { return nullptr != qApp ? qApp->organizationDomain() : d->m_OrgaDomain; } void BaseApplication::setSingleMode(bool singleMode) { if (nullptr != qApp) return; d->m_SingleMode = singleMode; } bool BaseApplication::getSingleMode() const { return d->m_SingleMode; } void BaseApplication::setSafeMode(bool safeMode) { if (nullptr != qApp && nullptr == d->m_QApp) return; d->m_SafeMode = safeMode; nullptr == d->m_QApp && getSingleMode() ? static_cast(d->m_QApp)->setSafeMode(safeMode) : static_cast(d->m_QApp)->setSafeMode(safeMode); } bool BaseApplication::getSafeMode() const { return d->m_SafeMode; } void BaseApplication::setPreloadLibraries(const QStringList &libraryBaseNames) { d->m_PreloadLibs = libraryBaseNames; } QStringList BaseApplication::getPreloadLibraries() const { return d->m_PreloadLibs; } void BaseApplication::setProvisioningFilePath(const QString &filePath) { d->m_ProvFile = filePath; } QString BaseApplication::getProvisioningFilePath() const { - QString provFilePath = d->m_ProvFile; + auto provFilePath = d->m_ProvFile; // A null QString means look up a default provisioning file - if (provFilePath.isNull() && qApp) + if (provFilePath.isNull() && nullptr != qApp) { QFileInfo appFilePath(QCoreApplication::applicationFilePath()); QDir basePath(QCoreApplication::applicationDirPath()); - QString provFileName = appFilePath.baseName() + ".provisioning"; + auto provFileName = appFilePath.baseName() + ".provisioning"; QFileInfo provFile(basePath.absoluteFilePath(provFileName)); #ifdef Q_OS_MAC /* - * On Mac, if started from the build directory the .provisioning file is located at: + * On macOS, if started from the build directory, the .provisioning file is located at: * - * but the executable path is: + * The executable path is: * * In this case we have to cdUp threetimes. * - * During packaging however the MitkWorkbench.provisioning file is placed at the same - * level like the executable, hence nothing has to be done. + * During packaging the MitkWorkbench.provisioning file is placed at the same + * level like the executable. Nothing has to be done. */ if (!provFile.exists()) { basePath.cdUp(); basePath.cdUp(); basePath.cdUp(); provFile = basePath.absoluteFilePath(provFileName); } #endif if (provFile.exists()) { provFilePath = provFile.absoluteFilePath(); } #ifdef CMAKE_INTDIR else { basePath.cdUp(); provFile.setFile(basePath.absoluteFilePath(provFileName)); + if (provFile.exists()) - { provFilePath = provFile.absoluteFilePath(); - } } #endif } + return provFilePath; } void BaseApplication::initializeQt() { if (nullptr != qApp) return; - // If previously parameters have been set we have to store them - // to hand them through to the application + // If parameters have been set before, we have to store them to hand them + // through to the application auto appName = this->getApplicationName(); auto orgName = this->getOrganizationName(); auto orgDomain = this->getOrganizationDomain(); // Create a QCoreApplication instance this->getQApplication(); - // provide parameters to QCoreApplication + // Provide parameters to QCoreApplication this->setApplicationName(appName); this->setOrganizationName(orgName); this->setOrganizationDomain(orgDomain); qInstallMessageHandler(outputQtMessage); } void BaseApplication::initialize(Poco::Util::Application &self) { // 1. Call the super-class method Poco::Util::Application::initialize(self); // 2. Initialize the Qt framework (by creating a QCoreApplication) this->initializeQt(); // 3. Seed the random number generator, once at startup. QTime time = QTime::currentTime(); qsrand((uint)time.msec()); // 4. Load the "default" configuration, which involves parsing // an optional .ini file and parsing any // command line arguments this->loadConfiguration(); // 5. Add configuration data from the command line and the // optional .ini file as CTK plugin // framework properties. d->initializeCTKPluginFrameworkProperties(this->config()); - // 6. Initialize splash screen if an image path is provided - // in the .ini file - this->initializeSplashScreen(qApp); + // 6. Initialize splash screen if an image path is provided + // in the .ini file + this->initializeSplashScreen(qApp); - // 7. Set the custom CTK Plugin Framework storage directory + // 7. Set the custom CTK Plugin Framework storage directory QString storageDir = this->getCTKFrameworkStorageDir(); + if (!storageDir.isEmpty()) - { d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir; - } - // 8. Set the library search paths and the pre-load library property + // 8. Set the library search paths and the pre-load library property this->initializeLibraryPaths(); - QStringList preloadLibs = this->getPreloadLibraries(); + + auto preloadLibs = this->getPreloadLibraries(); + if (!preloadLibs.isEmpty()) - { d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs; - } - // 9. Initialize the CppMicroServices library. + // 9. Initialize the CppMicroServices library. // The initializeCppMicroServices() method reuses the // FRAMEWORK_STORAGE property, so we call it after the // getCTKFrameworkStorageDir method. this->initializeCppMicroServices(); - // 10. Parse the (optional) provisioning file and set the - // correct framework properties. + // 10. Parse the (optional) provisioning file and set the + // correct framework properties. d->parseProvisioningFile(this->getProvisioningFilePath()); - // Finally, set the CTK Plugin Framework properties + // 11. Set the CTK Plugin Framework properties ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps); } void BaseApplication::uninitialize() { - QSharedPointer pfw = this->getFramework(); + auto pfw = this->getFramework(); + if (pfw) { pfw->stop(); - - // wait 10 seconds for the CTK plugin framework to stop + // Wait for up to 10 seconds for the CTK plugin framework to stop pfw->waitForStop(10000); } Poco::Util::Application::uninitialize(); } - int BaseApplication::getArgc() const { return d->m_Argc; } - char **BaseApplication::getArgv() const { return d->m_Argv; } + int BaseApplication::getArgc() const + { + return d->m_Argc; + } + + char **BaseApplication::getArgv() const + { + return d->m_Argv; + } + QString BaseApplication::getCTKFrameworkStorageDir() const { QString storageDir; + if (this->getSingleMode()) { - // This function checks if an instance is already running - // and either sends a message to it (containing the command - // line arguments) or checks if a new instance was forced by - // providing the BlueBerry.newInstance command line argument. - // In the latter case, a path to a temporary directory for - // the new application's storage directory is returned. - storageDir = handleNewAppInstance( - static_cast(d->m_QApp), d->m_Argc, d->m_Argv, ARG_NEWINSTANCE); + // This function checks if an instance is already running and either sends a message to + // it containing the command line arguments or checks if a new instance was forced by + // providing the BlueBerry.newInstance command line argument. In the latter case, a path + // to a temporary directory for the new application's storage directory is returned. + storageDir = handleNewAppInstance(static_cast(d->m_QApp), + d->m_Argc, d->m_Argv, ARG_NEWINSTANCE); } if (storageDir.isEmpty()) { - // This is a new instance and no other instance is already running. We specify - // the storage directory here (this is the same code as in berryInternalPlatform.cpp + // This is a new instance and no other instance is already running. We specify the + // storage directory here (this is the same code as in berryInternalPlatform.cpp) // so that we can re-use the location for the persistent data location of the // the CppMicroServices library. // Append a hash value of the absolute path of the executable to the data location. // This allows to start the same application from different build or install trees. storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" + this->getOrganizationName() + "/" + this->getApplicationName() + '_'; storageDir += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/"; } + return storageDir; } void BaseApplication::initializeCppMicroServices() { - QString storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString(); + auto storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString(); if (!storageDir.isEmpty()) - { - us::ModuleSettings::SetStoragePath((storageDir + QString("us") + QDir::separator()).toStdString()); - } + us::ModuleSettings::SetStoragePath((storageDir + "us" + QDir::separator()).toStdString()); } QCoreApplication *BaseApplication::getQApplication() const { if (nullptr == qApp) { vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(0); auto defaultFormat = QVTKOpenGLWidget::defaultFormat(); defaultFormat.setSamples(0); QSurfaceFormat::setDefaultFormat(defaultFormat); #ifdef Q_OS_OSX QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); #endif QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); d->m_QApp = this->getSingleMode() ? static_cast(new QmitkSingleApplication(d->m_Argc, d->m_Argv, this->getSafeMode())) : static_cast(new QmitkSafeApplication(d->m_Argc, d->m_Argv, this->getSafeMode())); } return qApp; } void BaseApplication::initializeLibraryPaths() { QStringList suffixes; suffixes << "plugins"; + #ifdef Q_OS_WINDOWS suffixes << "bin/plugins"; -#ifdef CMAKE_INTDIR + #ifdef CMAKE_INTDIR suffixes << "bin/" CMAKE_INTDIR "/plugins"; -#endif + #endif #else suffixes << "lib/plugins"; -#ifdef CMAKE_INTDIR + #ifdef CMAKE_INTDIR suffixes << "lib/" CMAKE_INTDIR "/plugins"; -#endif + #endif #endif #ifdef Q_OS_MAC suffixes << "../../plugins"; #endif - // we add a couple of standard library search paths for plug-ins + // We add a couple of standard library search paths for plug-ins QDir appDir(QCoreApplication::applicationDirPath()); - // walk one directory up and add bin and lib sub-dirs; this - // might be redundant + // Walk one directory up and add bin and lib sub-dirs; this might be redundant appDir.cdUp(); - foreach (QString suffix, suffixes) - { + for (const auto suffix : suffixes) ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix)); - } } int BaseApplication::main(const std::vector &args) { - // Start the plugin framework and all installed plug-ins according with - // their auto-start setting. + // Start the plugin framework and all installed plug-ins according to their auto-start setting QStringList arguments; for (auto const &arg : args) - { arguments.push_back(QString::fromStdString(arg)); - } - if (d->m_Splashscreen != nullptr) + if (nullptr != d->m_Splashscreen) { - // a splash screen is displayed, - // creating the closing callback + // A splash screen is displayed. Create the closing callback. d->m_SplashscreenClosingCallback = new SplashCloserCallback(d->m_Splashscreen); } return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt(); } void BaseApplication::defineOptions(Poco::Util::OptionSet &options) { Poco::Util::Option helpOption("help", "h", "print this help text"); helpOption.callback(Poco::Util::OptionCallback(this, &BaseApplication::printHelp)); options.addOption(helpOption); - Poco::Util::Option newInstanceOption( - ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application"); + Poco::Util::Option newInstanceOption(ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application"); newInstanceOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(newInstanceOption); Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache"); cleanOption.callback(Poco::Util::OptionCallback(d, &Impl::handleClean)); options.addOption(cleanOption); Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched"); productOption.argument("").binding(PROP_PRODUCT.toStdString()); options.addOption(productOption); - Poco::Util::Option appOption( - ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed"); + Poco::Util::Option appOption(ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed"); appOption.argument("").binding(PROP_APPLICATION.toStdString()); options.addOption(appOption); Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file"); provOption.argument("").binding(ARG_PROVISIONING.toStdString()); options.addOption(provOption); - Poco::Util::Option storageDirOption( - ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data"); + Poco::Util::Option storageDirOption(ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data"); storageDirOption.argument("").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString()); options.addOption(storageDirOption); Poco::Util::Option consoleLogOption(ARG_CONSOLELOG.toStdString(), "", "log messages to the console"); consoleLogOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(consoleLogOption); Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode"); debugOption.argument("", false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString()); options.addOption(debugOption); - Poco::Util::Option forcePluginOption( - ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name"); + Poco::Util::Option forcePluginOption(ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name"); forcePluginOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(forcePluginOption); Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library"); preloadLibsOption.argument("") .repeatable(true) .callback(Poco::Util::OptionCallback(d, &Impl::handlePreloadLibraryOption)); options.addOption(preloadLibsOption); Poco::Util::Option testPluginOption(ARG_TESTPLUGIN.toStdString(), "", "the plug-in to be tested"); testPluginOption.argument("").binding(PROP_TESTPLUGIN.toStdString()); options.addOption(testPluginOption); Poco::Util::Option testAppOption(ARG_TESTAPPLICATION.toStdString(), "", "the application to be tested"); testAppOption.argument("").binding(PROP_TESTAPPLICATION.toStdString()); options.addOption(testAppOption); - Poco::Util::Option noRegistryCacheOption( - ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry"); + Poco::Util::Option noRegistryCacheOption(ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry"); noRegistryCacheOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(noRegistryCacheOption); - Poco::Util::Option noLazyRegistryCacheLoadingOption( - ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry"); + Poco::Util::Option noLazyRegistryCacheLoadingOption(ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry"); noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(noLazyRegistryCacheLoadingOption); - Poco::Util::Option registryMultiLanguageOption( - ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry"); + Poco::Util::Option registryMultiLanguageOption(ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry"); registryMultiLanguageOption.callback(Poco::Util::OptionCallback(d, &Impl::handleBooleanOption)); options.addOption(registryMultiLanguageOption); Poco::Util::Option splashScreenOption(ARG_SPLASH_IMAGE.toStdString(), "", "optional picture to use as a splash screen"); splashScreenOption.argument("").binding(ARG_SPLASH_IMAGE.toStdString()); options.addOption(splashScreenOption); Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list"); xargsOption.argument("").binding(ARG_XARGS.toStdString()); options.addOption(xargsOption); Poco::Util::Application::defineOptions(options); } QSharedPointer BaseApplication::getFramework() const { return ctkPluginFrameworkLauncher::getPluginFramework(); } ctkPluginContext *BaseApplication::getFrameworkContext() const { - QSharedPointer framework = getFramework(); - if (framework) - return framework->getPluginContext(); - return nullptr; + auto framework = getFramework(); + + return framework + ? framework->getPluginContext() + : nullptr; } void BaseApplication::initializeSplashScreen(QCoreApplication * application) const { - QVariant pixmapFileNameProp = d->getProperty(ARG_SPLASH_IMAGE); - if (!pixmapFileNameProp.isNull()) { - QString pixmapFileName = pixmapFileNameProp.toString(); + auto pixmapFileNameProp = d->getProperty(ARG_SPLASH_IMAGE); + + if (!pixmapFileNameProp.isNull()) + { + auto pixmapFileName = pixmapFileNameProp.toString(); QFileInfo checkFile(pixmapFileName); - if (checkFile.exists() && checkFile.isFile()) { + + if (checkFile.exists() && checkFile.isFile()) + { QPixmap pixmap(checkFile.absoluteFilePath()); + d->m_Splashscreen = new QSplashScreen(pixmap, Qt::WindowStaysOnTopHint); d->m_Splashscreen->show(); + application->processEvents(); } } } - QHash BaseApplication::getFrameworkProperties() const { return d->m_FWProps; } + QHash BaseApplication::getFrameworkProperties() const + { + return d->m_FWProps; + } int BaseApplication::run() { this->init(d->m_Argc, d->m_Argv); return Application::run(); } - void BaseApplication::setProperty(const QString &property, const QVariant &value) { d->m_FWProps[property] = value; } - QVariant BaseApplication::getProperty(const QString &property) const { return d->getProperty(property); } + void BaseApplication::setProperty(const QString &property, const QVariant &value) + { + d->m_FWProps[property] = value; + } + + QVariant BaseApplication::getProperty(const QString &property) const + { + return d->getProperty(property); + } void BaseApplication::installTranslator(QTranslator* translator) { this->getQApplication()->installTranslator(translator); } bool BaseApplication::isRunning() { auto app = dynamic_cast(this->getQApplication()); if (nullptr != app) app->isRunning(); mitkThrow() << "Method not implemented."; } void BaseApplication::sendMessage(const QByteArray msg) { auto app = dynamic_cast(this->getQApplication()); if (nullptr != app) app->sendMessage(msg); mitkThrow() << "Method not implemented."; } - }