diff --git a/Modules/AppUtil/include/QmitkSafeApplication.h b/Modules/AppUtil/include/QmitkSafeApplication.h index c6413a0749..fb59a49183 100644 --- a/Modules/AppUtil/include/QmitkSafeApplication.h +++ b/Modules/AppUtil/include/QmitkSafeApplication.h @@ -1,47 +1,47 @@ /*=================================================================== 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 QMITKSAFEAPPLICATION_H #define QMITKSAFEAPPLICATION_H #include #include #include class MITKAPPUTIL_EXPORT QmitkSafeApplication : public QApplication { public: - QmitkSafeApplication(int &argc, char **argv); + QmitkSafeApplication(int &argc, char **argv, bool safeMode = true); /** * Reimplement notify to catch unhandled exceptions and open an error message. * * @param receiver * @param event * @return */ bool notify(QObject *receiver, QEvent *event) override; void setSafeMode(bool safeMode); bool getSafeMode() const; private: bool m_SafeMode; }; #endif // QMITKSAFEAPPLICATION_H diff --git a/Modules/AppUtil/include/mitkBaseApplication.h b/Modules/AppUtil/include/mitkBaseApplication.h index bd48cc5e15..a3144a56df 100644 --- a/Modules/AppUtil/include/mitkBaseApplication.h +++ b/Modules/AppUtil/include/mitkBaseApplication.h @@ -1,334 +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 -#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 QString ARG_NEWINSTANCE; - static QString ARG_CLEAN; - static QString ARG_APPLICATION; - static QString ARG_PRODUCT; - static QString ARG_HOME; - static QString ARG_STORAGE_DIR; - static QString ARG_PLUGIN_CACHE; - static QString ARG_PLUGIN_DIRS; - static QString ARG_FORCE_PLUGIN_INSTALL; - static QString ARG_PRELOAD_LIBRARY; - static QString ARG_PROVISIONING; - static QString ARG_DEBUG; - - static QString ARG_CONSOLELOG; - static QString ARG_TESTPLUGIN; - static QString ARG_TESTAPPLICATION; - - static QString ARG_NO_REGISTRY_CACHE; - static QString ARG_NO_LAZY_REGISTRY_CACHE_LOADING; - static QString ARG_REGISTRY_MULTI_LANGUAGE; - - static QString ARG_SPLASH_IMAGE; - - static QString ARG_XARGS; - - // BlueBerry specific Plugin Framework properties - - static QString PROP_NEWINSTANCE; - static QString PROP_FORCE_PLUGIN_INSTALL; - static QString PROP_NO_REGISTRY_CACHE; - static QString PROP_NO_LAZY_REGISTRY_CACHE_LOADING; - static QString PROP_REGISTRY_MULTI_LANGUAGE; - - static QString PROP_PRODUCT; - static QString PROP_APPLICATION; - static QString PROP_TESTPLUGIN; - static QString PROP_TESTAPPLICATION; + static const QString ARG_APPLICATION; + 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_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_PRELOAD_LIBRARY; + static const QString ARG_PRODUCT; + static const QString ARG_PROVISIONING; + 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 + + static const QString PROP_APPLICATION; + static const QString PROP_FORCE_PLUGIN_INSTALL; + static const QString PROP_NEWINSTANCE; + static const QString PROP_NO_LAZY_REGISTRY_CACHE_LOADING; + static const QString PROP_NO_REGISTRY_CACHE; + static const QString PROP_PRODUCT; + 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; - QScopedPointer d; + Impl* d; }; } #endif // MITKBASEAPPLICATION_H diff --git a/Modules/AppUtil/src/QmitkSafeApplication.cpp b/Modules/AppUtil/src/QmitkSafeApplication.cpp index 52e4fac56a..54367892f1 100644 --- a/Modules/AppUtil/src/QmitkSafeApplication.cpp +++ b/Modules/AppUtil/src/QmitkSafeApplication.cpp @@ -1,46 +1,45 @@ /*=================================================================== 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 "QmitkSafeApplication.h" #include "QmitkSafeNotify.h" #include #include -QmitkSafeApplication::QmitkSafeApplication(int &argc, char **argv) : QApplication(argc, argv) +QmitkSafeApplication::QmitkSafeApplication(int &argc, char **argv, bool safeMode) + : QApplication(argc, argv), + m_SafeMode(safeMode) { } bool QmitkSafeApplication::notify(QObject *receiver, QEvent *event) { - if (!m_SafeMode) - { - return QApplication::notify(receiver, event); - } - - return QmitkSafeNotify(this, receiver, event); + return m_SafeMode + ? QmitkSafeNotify(this, receiver, event) + : QApplication::notify(receiver, event); } void QmitkSafeApplication::setSafeMode(bool safeMode) { m_SafeMode = safeMode; } bool QmitkSafeApplication::getSafeMode() const { return m_SafeMode; } diff --git a/Modules/AppUtil/src/QmitkSingleApplication.cpp b/Modules/AppUtil/src/QmitkSingleApplication.cpp index a70557d7c9..57a1beb591 100644 --- a/Modules/AppUtil/src/QmitkSingleApplication.cpp +++ b/Modules/AppUtil/src/QmitkSingleApplication.cpp @@ -1,44 +1,40 @@ /*=================================================================== 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 "QmitkSingleApplication.h" - #include "QmitkSafeNotify.h" QmitkSingleApplication::QmitkSingleApplication(int &argc, char **argv, bool safeMode) : QtSingleApplication(argc, argv), m_SafeMode(safeMode) { } bool QmitkSingleApplication::notify(QObject *receiver, QEvent *event) { - if (!m_SafeMode) - { - return QtSingleApplication::notify(receiver, event); - } - - return QmitkSafeNotify(this, receiver, event); + return m_SafeMode + ? QmitkSafeNotify(this, receiver, event) + : QtSingleApplication::notify(receiver, event); } void QmitkSingleApplication::setSafeMode(bool safeMode) { m_SafeMode = safeMode; } bool QmitkSingleApplication::getSafeMode() const { return m_SafeMode; } diff --git a/Modules/AppUtil/src/mitkBaseApplication.cpp b/Modules/AppUtil/src/mitkBaseApplication.cpp index d17d780edf..15ad04cbeb 100644 --- a/Modules/AppUtil/src/mitkBaseApplication.cpp +++ b/Modules/AppUtil/src/mitkBaseApplication.cpp @@ -1,899 +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 mitk +namespace { - QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance"; - QString BaseApplication::ARG_CLEAN = "BlueBerry.clean"; - QString BaseApplication::ARG_APPLICATION = "BlueBerry.application"; - QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; - QString BaseApplication::ARG_HOME = "BlueBerry.home"; - QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir"; - QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir"; - QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs"; - QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins"; - QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary"; - QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning"; - QString BaseApplication::ARG_DEBUG = "BlueBerry.debug"; - QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog"; - QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin"; - QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication"; - - QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen"; - - QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache"; - QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading"; - QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage"; - - QString BaseApplication::ARG_XARGS = "xargs"; - - QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE; - QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL; - QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; - QString BaseApplication::PROP_NO_LAZY_REGISTRY_CACHE_LOADING = BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING; - QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE; - - QString BaseApplication::PROP_PRODUCT = "blueberry.product"; - QString BaseApplication::PROP_APPLICATION = "blueberry.application"; - QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin"; - QString BaseApplication::PROP_TESTAPPLICATION = "BlueBerry.testapplication"; - - static void outputQtMessage(QtMsgType type, const QMessageLogContext &, const QString &msg) + 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_APPLICATION = "BlueBerry.application"; + 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_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_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary"; + const QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; + const QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning"; + 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_APPLICATION = "blueberry.application"; + const QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL; + 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_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; + const QString BaseApplication::PROP_PRODUCT = "blueberry.product"; + 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; - QScopedPointer 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), m_SingleMode(false), m_SafeMode(true), - m_Splashscreen(nullptr), m_SplashscreenClosingCallback(nullptr) + : 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 - /* - * This is a workaround for bug 19080: - * On macOS the prosess serial number is passed as an commandline argument (-psn_) - * if the application is started via the.app bundle. - * This option is unknown, which causes a Poco exception. - * Since this is done by the system we have to manually remove the argument here. - */ + /* On macOS the process serial number is passed as an command line argument (-psn_) + in certain circumstances. This option causes a Poco exception. We remove it, if present. */ - int newArgc = m_Argc - 1; - char **newArgs = new char *[newArgc]; - bool argFound(false); - for (int i = 0; i < m_Argc; ++i) - { - if (QString::fromLatin1(m_Argv[i]).contains("-psn")) - { - argFound = true; - } - else - { - newArgs[i] = m_Argv[i]; - } - } - if (argFound) + m_Argv_macOS.reserve(argc); + + const char psn[] = "-psn"; + + for (decltype(argc) i = 0; i < argc; ++i) { - m_Argc = newArgc; - m_Argv = newArgs; + 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()); - } - // foreach(QUrl pluginUrl, provInfo.getPluginsToInstall()) - //{ - // TODO for "uninstall", we need a proper configuration agent, e.g. a dedicated - // plug-in for provisioning of the platform - /* - if (forcePluginOverwrite) - { - uninstallPugin(pluginUrl, context); - } - */ - // try - //{ - // MITK_INFO(consoleLog) << "Installing CTK plug-in from: " << pluginUrl.toString().toStdString(); - /* - QSharedPointer plugin = context->installPlugin(pluginUrl); - if (pluginsToStart.contains(pluginUrl)) - { - m_CTKPluginsToStart << plugin->getPluginId(); - } - */ - /* - } - catch (const ctkPluginException& e) - { - QString errorMsg; - QDebug dbg(&errorMsg); - dbg << e.printStackTrace(); - BERRY_ERROR << qPrintable(errorMsg); - } - */ - //} } } 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(int argc, char **argv) + : Application(), + d(new Impl(argc, argv)) { } BaseApplication::~BaseApplication() { - if (d->m_Splashscreen != nullptr) - { - delete(d->m_Splashscreen); - } - if (d->m_SplashscreenClosingCallback != nullptr) - { - delete(d->m_SplashscreenClosingCallback); - } + 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 (qApp) - { + if (nullptr != qApp) qApp->setApplicationName(name); - } + d->m_AppName = name; } QString BaseApplication::getApplicationName() const { - if (qApp) - { - return qApp->applicationName(); - } - return d->m_AppName; + return nullptr != qApp + ? qApp->applicationName() + : d->m_AppName; } void BaseApplication::setOrganizationName(const QString &name) { - if (qApp) - { + if (nullptr != qApp) qApp->setOrganizationName(name); - } + d->m_OrgaName = name; } QString BaseApplication::getOrganizationName() const { - if (qApp) - return qApp->organizationName(); - return d->m_OrgaName; + return nullptr != qApp + ? qApp->organizationName() + : d->m_OrgaName; } void BaseApplication::setOrganizationDomain(const QString &domain) { - if (qApp) - { + if (nullptr != qApp) qApp->setOrganizationDomain(domain); - } + d->m_OrgaDomain = domain; } QString BaseApplication::getOrganizationDomain() const { - if (qApp) - return qApp->organizationDomain(); - return d->m_OrgaDomain; + return nullptr != qApp + ? qApp->organizationDomain() + : d->m_OrgaDomain; } void BaseApplication::setSingleMode(bool singleMode) { - if (qApp) + if (nullptr != qApp) return; + d->m_SingleMode = singleMode; } - bool BaseApplication::getSingleMode() const { return d->m_SingleMode; } + bool BaseApplication::getSingleMode() const + { + return d->m_SingleMode; + } + void BaseApplication::setSafeMode(bool safeMode) { - if (qApp && !d->m_QApp) + if (nullptr != qApp && nullptr == d->m_QApp) return; + d->m_SafeMode = safeMode; - if (d->m_QApp) - { - if (getSingleMode()) - { - static_cast(d->m_QApp.data())->setSafeMode(safeMode); - } - else - { - static_cast(d->m_QApp.data())->setSafeMode(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; } - 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; } + 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 (qApp) + if (nullptr != qApp) return; - // If previously parameters have been set we have to store them - // to hand them through to the application - QString appName = this->getApplicationName(); - QString orgName = this->getOrganizationName(); - QString orgDomain = this->getOrganizationDomain(); + // 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.data()), 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 { - QCoreApplication *qCoreApp = qApp; - - if (nullptr == qCoreApp) + 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); - if (this->getSingleMode()) - { - qCoreApp = new QmitkSingleApplication(d->m_Argc, d->m_Argv, getSafeMode()); - } - else - { - auto safeApp = new QmitkSafeApplication(d->m_Argc, d->m_Argv); - safeApp->setSafeMode(d->m_SafeMode); - qCoreApp = safeApp; - } - d->m_QApp.reset(qCoreApp); + 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 qCoreApp; + 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"); - newInstanceOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); + 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.data(), &Impl::handleClean)); + 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.data(), &Impl::handleBooleanOption)); + 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"); - forcePluginOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); + 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.data(), &Impl::handlePreloadLibraryOption)); + .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"); - noRegistryCacheOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); + 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"); - noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); + 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"); - registryMultiLanguageOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); + 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."; } - } diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryInternalPlatform.cpp b/Plugins/org.blueberry.core.runtime/src/internal/berryInternalPlatform.cpp index f9d4876d23..a6711d0482 100644 --- a/Plugins/org.blueberry.core.runtime/src/internal/berryInternalPlatform.cpp +++ b/Plugins/org.blueberry.core.runtime/src/internal/berryInternalPlatform.cpp @@ -1,500 +1,503 @@ /*=================================================================== BlueBerry Platform 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 NOMINMAX #define NOMINMAX #endif #include "berryInternalPlatform.h" #include "berryLog.h" #include "berryLogImpl.h" #include "berryPlatform.h" #include "berryPlatformException.h" #include "berryDebugUtil.h" #include "berryPlatformException.h" #include "berryCTKPluginActivator.h" #include "berryPlatformException.h" #include "berryApplicationContainer.h" #include "berryProduct.h" #include "berryIBranding.h" //#include "event/berryPlatformEvents.h" //#include "berryPlatformLogChannel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace berry { QMutex InternalPlatform::m_Mutex; bool InternalPlatform::DEBUG = false; bool InternalPlatform::DEBUG_PLUGIN_PREFERENCES = false; InternalPlatform::InternalPlatform() : m_Initialized(false) , m_ConsoleLog(false) , m_Context(nullptr) { } InternalPlatform::~InternalPlatform() { } InternalPlatform* InternalPlatform::GetInstance() { QMutexLocker lock(&m_Mutex); static InternalPlatform instance; return &instance; } bool InternalPlatform::ConsoleLog() const { return m_ConsoleLog; } QVariant InternalPlatform::GetOption(const QString& option, const QVariant& defaultValue) const { ctkDebugOptions* options = GetDebugOptions(); if (options != nullptr) { return options->getOption(option, defaultValue); } return QVariant(); } IAdapterManager* InternalPlatform::GetAdapterManager() const { AssertInitialized(); return nullptr; } SmartPointer InternalPlatform::GetProduct() const { if (product.IsNotNull()) return product; ApplicationContainer* container = org_blueberry_core_runtime_Activator::GetContainer(); IBranding* branding = container == nullptr ? nullptr : container->GetBranding(); if (branding == nullptr) return IProduct::Pointer(); IProduct::Pointer brandingProduct = branding->GetProduct(); if (!brandingProduct) { brandingProduct = new Product(branding); } product = brandingProduct; return product; } void InternalPlatform::InitializePluginPaths() { QMutexLocker lock(&m_Mutex); // Add search paths for Qt plugins - foreach(QString qtPluginPath, m_Context->getProperty(Platform::PROP_QTPLUGIN_PATH).toStringList()) + for(const auto qtPluginPath : m_Context->getProperty(Platform::PROP_QTPLUGIN_PATH).toStringList()) { + if (qtPluginPath.isEmpty()) + continue; + if (QFile::exists(qtPluginPath)) { QCoreApplication::addLibraryPath(qtPluginPath); } else if (m_ConsoleLog) { BERRY_WARN << "Qt plugin path does not exist: " << qtPluginPath.toStdString(); } } // Add a default search path. It is assumed that installed applications // provide their Qt plugins in that path. static const QString defaultQtPluginPath = QCoreApplication::applicationDirPath() + "/plugins"; if (QFile::exists(defaultQtPluginPath)) { QCoreApplication::addLibraryPath(defaultQtPluginPath); } if (m_ConsoleLog) { std::string pathList; foreach(QString libPath, QCoreApplication::libraryPaths()) { pathList += (pathList.empty() ? "" : ", ") + libPath.toStdString(); } BERRY_INFO << "Qt library search paths: " << pathList; } /* m_ConfigPath.setPath(m_Context->getProperty("application.configDir").toString()); m_InstancePath.setPath(m_Context->getProperty("application.dir").toString()); QString installPath = m_Context->getProperty(Platform::PROP_HOME).toString(); if (installPath.isEmpty()) { m_InstallPath = m_InstancePath; } else { m_InstallPath.setPath(installPath); } QString dataLocation = m_Context->getProperty(Platform::PROP_STORAGE_DIR).toString(); if (!storageDir.isEmpty()) { if (dataLocation.at(dataLocation.size()-1) != '/') { dataLocation += '/'; } m_UserPath.setPath(dataLocation); } else { // 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. dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + this->getOrganizationName() + "/" + this->getApplicationName() + '_'; dataLocation += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/"; m_UserPath.setPath(dataLocation); } BERRY_INFO(m_ConsoleLog) << "Framework storage dir: " << m_UserPath.absolutePath(); QFileInfo userFile(m_UserPath.absolutePath()); if (!QDir().mkpath(userFile.absoluteFilePath()) || !userFile.isWritable()) { QString tmpPath = QDir::temp().absoluteFilePath(QString::fromStdString(this->commandName())); BERRY_WARN << "Storage dir " << userFile.absoluteFilePath() << " is not writable. Falling back to temporary path " << tmpPath; QDir().mkpath(tmpPath); userFile.setFile(tmpPath); } m_BaseStatePath.setPath(m_UserPath.absolutePath() + "/bb-metadata/bb-plugins"); QString logPath(m_UserPath.absoluteFilePath(QString::fromStdString(this->commandName()) + ".log")); m_PlatformLogChannel = new Poco::SimpleFileChannel(logPath.toStdString()); */ } ctkDebugOptions* InternalPlatform::GetDebugOptions() const { return m_DebugTracker.isNull() ? nullptr : m_DebugTracker->getService(); } IApplicationContext* InternalPlatform::GetApplicationContext() const { QList refs; try { refs = m_Context->getServiceReferences("(blueberry.application.type=main.thread)"); } catch (const std::invalid_argument&) { return nullptr; } if (refs.isEmpty()) return nullptr; // assumes the application context is available as a service IApplicationContext* result = m_Context->getService(refs.front()); if (result != nullptr) { m_Context->ungetService(refs.front()); return result; } return nullptr; } void InternalPlatform::Start(ctkPluginContext* context) { this->m_Context = context; m_ConsoleLog = m_Context->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool(); OpenServiceTrackers(); this->InitializePluginPaths(); #ifdef BLUEBERRY_DEBUG_SMARTPOINTER DebugUtil::RestoreState(m_UserPath); #endif InitializeDebugFlags(); this->m_Initialized = true; } void InternalPlatform::Stop(ctkPluginContext* /*context*/) { AssertInitialized(); this->m_Initialized = false; CloseServiceTrackers(); #ifdef BLUEBERRY_DEBUG_SMARTPOINTER DebugUtil::SaveState(m_UserPath); #endif this->m_Context = nullptr; } void InternalPlatform::AssertInitialized() const { if (!m_Initialized) { throw PlatformException("The Platform has not been initialized yet!"); } } void InternalPlatform::OpenServiceTrackers() { ctkPluginContext* context = this->m_Context; instanceLocation.reset(new ctkServiceTracker(context, ctkLDAPSearchFilter(ctkLocation::INSTANCE_FILTER))); instanceLocation->open(); userLocation.reset(new ctkServiceTracker(context, ctkLDAPSearchFilter(ctkLocation::USER_FILTER))); userLocation->open(); configurationLocation.reset(new ctkServiceTracker(context, ctkLDAPSearchFilter(ctkLocation::CONFIGURATION_FILTER))); configurationLocation->open(); installLocation.reset(new ctkServiceTracker(context, ctkLDAPSearchFilter(ctkLocation::INSTALL_FILTER))); installLocation->open(); m_PreferencesTracker.reset(new ctkServiceTracker(context)); m_PreferencesTracker->open(); m_RegistryTracker.reset(new ctkServiceTracker(context)); m_RegistryTracker->open(); m_DebugTracker.reset(new ctkServiceTracker(context)); m_DebugTracker->open(); } void InternalPlatform::CloseServiceTrackers() { if (!m_PreferencesTracker.isNull()) { m_PreferencesTracker->close(); m_PreferencesTracker.reset(); } if (!m_RegistryTracker.isNull()) { m_RegistryTracker->close(); m_RegistryTracker.reset(); } if (!m_DebugTracker.isNull()) { m_DebugTracker->close(); m_DebugTracker.reset(); } if (!configurationLocation.isNull()) { configurationLocation->close(); configurationLocation.reset(); } if (!installLocation.isNull()) { installLocation->close(); installLocation.reset(); } if (!instanceLocation.isNull()) { instanceLocation->close(); instanceLocation.reset(); } if (!userLocation.isNull()) { userLocation->close(); userLocation.reset(); } } void InternalPlatform::InitializeDebugFlags() { DEBUG = this->GetOption(Platform::PI_RUNTIME + "/debug", false).toBool(); if (DEBUG) { DEBUG_PLUGIN_PREFERENCES = GetOption(Platform::PI_RUNTIME + "/preferences/plugin", false).toBool(); } } IExtensionRegistry* InternalPlatform::GetExtensionRegistry() { return m_RegistryTracker.isNull() ? nullptr : m_RegistryTracker->getService(); } IPreferencesService *InternalPlatform::GetPreferencesService() { return m_PreferencesTracker.isNull() ? nullptr : m_PreferencesTracker->getService(); } ctkLocation* InternalPlatform::GetConfigurationLocation() { this->AssertInitialized(); return configurationLocation->getService(); } ctkLocation* InternalPlatform::GetInstallLocation() { this->AssertInitialized(); return installLocation->getService(); } ctkLocation* InternalPlatform::GetInstanceLocation() { this->AssertInitialized(); return instanceLocation->getService(); } QDir InternalPlatform::GetStateLocation(const QSharedPointer& plugin) { ctkLocation* service = GetInstanceLocation(); if (service == nullptr) { throw ctkIllegalStateException("No instance data can be specified."); } QUrl url = GetInstanceLocation()->getDataArea(plugin->getSymbolicName()); if (!url.isValid()) { throw ctkIllegalStateException("The instance data location has not been specified yet."); } QDir location(url.toLocalFile()); if (!location.exists()) { if (!location.mkpath(location.absolutePath())) { throw PlatformException(QString("Could not create plugin state location \"%1\"").arg(location.absolutePath())); } } return location; } //PlatformEvents& InternalPlatform::GetEvents() //{ // return m_Events; //} ctkLocation* InternalPlatform::GetUserLocation() { this->AssertInitialized(); return userLocation->getService(); } ILog *InternalPlatform::GetLog(const QSharedPointer &plugin) const { LogImpl* result = m_Logs.value(plugin->getPluginId()); if (result != nullptr) return result; // ExtendedLogService logService = (ExtendedLogService) extendedLogTracker.getService(); // Logger logger = logService == null ? null : logService.getLogger(bundle, PlatformLogWriter.EQUINOX_LOGGER_NAME); // result = new Log(bundle, logger); // ExtendedLogReaderService logReader = (ExtendedLogReaderService) logReaderTracker.getService(); // logReader.addLogListener(result, result); // logs.put(bundle, result); // return result; result = new LogImpl(plugin); m_Logs.insert(plugin->getPluginId(), result); return result; } bool InternalPlatform::IsRunning() const { QMutexLocker lock(&m_Mutex); try { return m_Initialized && m_Context && m_Context->getPlugin()->getState() == ctkPlugin::ACTIVE; } catch (const ctkIllegalStateException&) { return false; } } QSharedPointer InternalPlatform::GetPlugin(const QString &symbolicName) { QList > plugins = m_Context->getPlugins(); QSharedPointer res(nullptr); foreach(QSharedPointer plugin, plugins) { if ((plugin->getState() & (ctkPlugin::INSTALLED | ctkPlugin::UNINSTALLED)) == 0 && plugin->getSymbolicName() == symbolicName) { if (res.isNull()) { res = plugin; } else if (res->getVersion().compare(plugin->getVersion()) < 0) { res = plugin; } } } return res; } QList > InternalPlatform::GetPlugins(const QString &symbolicName, const QString &version) { QList > plugins = m_Context->getPlugins(); QMap > selected; ctkVersion versionObj(version); foreach(QSharedPointer plugin, plugins) { if ((plugin->getState() & (ctkPlugin::INSTALLED | ctkPlugin::UNINSTALLED)) == 0 && plugin->getSymbolicName() == symbolicName) { if (plugin->getVersion().compare(versionObj) > -1) { selected.insert(plugin->getVersion(), plugin); } } } QList > sortedPlugins = selected.values(); QList > reversePlugins; qCopyBackward(sortedPlugins.begin(), sortedPlugins.end(), reversePlugins.end()); return reversePlugins; } QStringList InternalPlatform::GetApplicationArgs() const { QStringList result; IApplicationContext* appContext = this->GetApplicationContext(); if (appContext) { QHash args = appContext->GetArguments(); result = args[IApplicationContext::APPLICATION_ARGS].toStringList(); } return result; } }