1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
|
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#ifndef EXTENSIONS_MANAGER_H
#define EXTENSIONS_MANAGER_H
// -- Core stuff
#include "ComponentExtension.h"
#include "ActionExtension.h"
#include "ViewerExtension.h"
#include "CamiTKAPI.h"
// -- QT stuff
#include <QtPlugin>
#include <QPluginLoader>
#include <QStringList>
#include <QMap>
#include <QDir>
namespace camitk {
/**
* @ingroup group_sdk_libraries_core
*
* @brief
* This class is used to manage all plugins loaded by the application.
*
* The current version is able to load dynamic library for
* - ComponentExtension
* - ActionExtension
*
* This class is a contained for all the loaded extension. It contains only
* static members.
*/
class CAMITK_API ExtensionManager : public QObject {
public:
/** \enum ExtensionType describes the CamiTK Extension Type (Action, Component, Application...).
* CamiTK follows Component-Based programming architecture. The Service Layer defines four types
* of extensions.
*/
enum ExtensionType {
ACTION, ///< Action extensions: manages the processing logic
COMPONENT, ///< Component extensions: manages the data logic
APPLICATION, ///< MainWindow extensions: manages the application logic
VIEWER ///< Viewer extensions: manages the presentation and user interaction logic.
};
/// \enum InstallationRepository corresponds to where the extension is installed
enum InstallationRepository {
GLOBAL, ///< the extension is installed on the system (global install)
LOCAL, ///< the extension is installed in the user defined installation directory (local install)
WORKING_DIRECTORY, ///< the extension is installed in the current working directory (development stage)
USER, ///< the extension is registered in the user configuration file (could be anywhere)
NOT_REGISTERED ///< the extension is not registered in any of the recognized installation repository
};
/// Autoload component, action and viewer extensions (dlls) as well as registered CamiTK extension file
static void autoload();
/** Autoload all the extension of a given type.
* This method try to load all the extensions of the given type that are found (in this specific order) :
* - in the current working directory (considered as an install directory), this should be the build directory (load extensions that are just being compiled, before their installation
* - in the user config directory (CamiTK user install)
* - in the system-wide install (CamiTK global install)
* - and in the list of user-registered extensions (stored in the configuration directory)
*
* Duplicates found within the installation directory are removed (e.g. if you have the extension x.so in the build directory as
* well as the user directory, only the extension in the build directory will be loaded (it takes precedence).
*
* @param type the extension type
*/
static void autoload(ExtensionType type);
/** Load a specific extension from a file.
* This methods loads a ActionExtension, ComponentExtension,... plugin from a .dll/.so/.dylib filename
*
* @param type the extension type
* @param file the plugin filename (.dll/.so/.dylib)
* @return false if it cannot be loaded
*/
static bool loadExtension(ExtensionType type, QString file);
/** Register the given ComponentExtension.
* If the given ComponentExtension is managing file extensions that are already registered, it
* will not be registered, and this method will return false and a info message will be printed
* with more information.
*
* @param ce valid ComponentExtension pointer (loaded from a shared library plugin (.dll/.so/.dylib) or instantiated programmatically)
* @param filename (optional) if the extension was loaded from a shared library (.dll/.so/.dylib), path to this file
* @return true if the extension was registered without error
*/
static bool registerNewComponentExtension(ComponentExtension* ce, QString filename = QString());
/** Returns a three char string that corresponds to the installation directory of a given shared library.
*
* The shared library should be the complete/fullpath filename corresponding to a component, action or viewer extension.
*
* The following enum value is returned:
* - "[G]" for an extension installed in the global installation directory (where CamiTK SDK is installed)
* - "[L]" for an extension installed in the user configuration directory (local install)
* - "[W]" for an extension loaded directly from the current working directory (build installation tree)
* - "[U]" for an extension loaded manually by the user
*
* @return the string coding for the installation
* @param file the extension plugin file
* @param globalInstallDir the global installation directory
* @param userInstallDir the user installation directory
* @param currentWorkingDir the current working directory
*/
static QString getInstallationString(QString file, const QString& globalInstallDir, const QString& userInstallDir, const QString& currentWorkingDir);
/**
* @brief Returns the enum corresponding to the installation repository (directory) of a given shared library.
*
* The shared library should be the name corresponding to the value of getName() of an
* existing ComponentExtension, ActionExtension or ViewerExtension.
*
* The following string code are returned:
* - GLOBAL for an extension installed in the global installation directory (where CamiTK SDK is installed)
* - LOCAL for an extension installed in the user configuration directory (local install)
* - WORKING for an extension loaded directly from the current working directory (build installation tree)
* - USER for an extension loaded manually by the user
* - NOT_REGISTERED the extension name was not found in the list of loaded extensions
*
* \note calls getInstallationString and Core methods.
*
* @return the enum value corresponding to the type of installation repository/directory
* @param extensionName the extension plugin name (i.e. the extension getName() value)
*/
static InstallationRepository getInstallationRepository(const QString& extensionName);
/** @name Component extension list management
*/
///@{
/** @brief get the plugin corresponding to a given extension or name.
*
*/
static ComponentExtension* getComponentExtension(QString);
/**
* @brief Get the list of registered ComponentExtension.
* The list contains unique elements (no duplicates possible) and is alphabetically sorted.
*
* @note
* The list is read-only and cannot be modified.
* This list is useful to loop over the loaded ComponentExtension, especially when order counts.
*
* @return list of unique ComponentExtension loaded in the Core.
*/
static const QList<ComponentExtension*> getComponentExtensionsList();
/** @brief get the plugin corresponding to a given data directory component extension's name.
*
*/
static ComponentExtension* getDataDirectoryComponentExtension(QString);
/**
* @brief Get the list of registered ComponentExtension working on directory.
* The list contains unique elements (no duplicates possible) and is alphabetically sorted.
*
* @note
* The list is read-only and cannot be modified.
* This list is useful to loop over the loaded ComponentExtension, especially when order counts.
*
* @return list of unique ComponentExtension working on data directory loaded in the Core.
*/
static const QList<ComponentExtension*> getDataDirectoryComponentsList();
/// get the list of all the suffixes managed by registered component extensions (all possible file suffix)
static QStringList getFileExtensions();
/// get the list of all the name of the registered Component data directory
static QStringList getDataDirectoryExtNames();
/** Register the file extension with the current application for opening
* This function is called by registerFileExtensions
* @param fileExtension the file extension to associate with the current application for opening
**/
static void registerFileExtension(QString fileExtension);
/** Unload a plugin corresponding to a given extension or component name.
* @return false if the plugin could not be unloaded - still in use somewhere
*/
static bool unloadComponentExtension(QString);
///@}
/// @name Action extension list management
///@{
/// unload all action extensions and delete instantiated actions
static void unloadAllActionExtensions();
/**
* @brief Get the list of registered ActionExtension.
* The list contains unique elements (no duplicates possible) and is alphabetically sorted.
*
* @note
* The list is read-only and cannot be modified.
* This list is useful to loop over the loaded ActionExtension, especially when order counts.
*
* @return list of unique ActionExtension loaded in the Core.
*/
static const QList<ActionExtension*> getActionExtensionsList();
/**
* @brief Get the ActionExtension corresponding to the given shared library file.
*
* If the given shared library is not loaded return nullptr. The shared library file should
* be given as a complete filepath in the QString.
*
* @return nullptr if the given shared library complete path is not loaded.
*/
static ActionExtension* getActionExtension(QString);
/** Unload an action extension using its .dll/.so/.dylib filename
* @return false if the plugin could not be unloaded - still in use somewhere
*/
static bool unloadActionExtension(QString);
///@}
/// @name Viewer extension list management
///@{
/// unload all viewer extensions and delete instantiated actions
static void unloadAllViewerExtensions();
/**
* @brief Get the list of registered ViewerExtension.
* The list contains unique elements (no duplicates possible) and is alphabetically sorted.
*
* @note
* The list is read-only and cannot be modified.
* This list is useful to loop over the loaded ViewerExtension, especially when order counts.
*
* @return list of unique ViewerExtension loaded in the Core.
*/
static const QList<ViewerExtension*> getViewerExtensionsList();
/**
* @brief Get the Viewer Extension corresponding to the given shared library file.
*
* If the given shared library is not loaded return nullptr. The shared library file should
* be given as a complete filepath in the QString.
*
* @return nullptr if the given shared library complete path is not loaded.
*/
static ViewerExtension* getViewerExtension(QString);
/** Unload an viewer extension using its .dll/.so/.dylib filename
* @return false if the plugin could not be unloaded - still in use somewhere
*/
static bool unloadViewerExtension(QString);
///@}
private:
/** get the singleton map of loaded component plugins for files (the key is the file extension)
* This is the private (intern) method.
* The component extension map is updated by loadComponentExtension, unloadComponentExtension and autoloadComponentExtensions.
* This method follows the "construct on first use" idiom/design-pattern.
* It therefore avoids the infamous "static initialization order fiasco",
* see http://www.parashift.com/c++-faq/ctors.html
*/
static QMap<QString, ComponentExtension*>& getComponentExtensionMap();
/** get the singleton map of loaded component plugins for data directory (the key is the name)
* This is the private (intern) method.
* The data directory component extension map is updated by loadExtension, unloadExtension and autoloadExtensions.
* This method follows the "construct on first use" idiom/design-pattern.
* It therefore avoids the infamous "static initialization order fiasco",
* see http://www.parashift.com/c++-faq/ctors.html
*/
static QMap<QString, ComponentExtension*>& getDataDirectoryComponentExtensionMap();
/** get the singleton map of loaded action plugins (the key is the shared object/dll/dylib filename)
* This is the private (intern) method.
* The action extension map is updated by loadActionExtension, unloadActionExtension and autoloadActionExtensions.
* This method follows the "construct on first use" idiom/design-pattern.
* It therefore avoids the infamous "static initialization order fiasco",
* see http://www.parashift.com/c++-faq/ctors.html
*/
static QMap<QString, ActionExtension*>& getActionExtensionMap();
/** get the singleton map of loaded viewer plugins (the key is the shared object/dll/dylib filename)
* This is the private (intern) method.
* The viewer extension map is updated by loadViewerExtension, unloadViewerExtension and autoloadViewerExtensions.
* This method follows the "construct on first use" idiom/design-pattern.
* It therefore avoids the infamous "static initialization order fiasco",
* see http://www.parashift.com/c++-faq/ctors.html
*/
static QMap<QString, ViewerExtension*>& getViewerExtensionMap();
/// return the list of shared objects in a directory considering debug/release on MSVC
static QStringList getPluginFileNames(QDir);
/** Add the private library directories (lib/camitk-version) in the current session PATH:
* - the current build library directory
* - the local installation library directory
* - the global installation library directory
* Note that we also add the actions and component private library subdirectories.
* Uses addLibraryPath().
* Takes multiarch into account.
*/
static void initPrivateLibDirs();
/// check if the given directory contains an extension repository and if it does
/// update PATH (on windows) and call QCoreApplication::addLibraryPath for
/// the given directory and all derived possible extension
/// directories (actions, components and viewers)
/// To check if it contains an extension repository, the given QString is used
static void addLibraryPath(QDir potentialPath, QString potentialLibDir);
/// @name Custom comparaison methods
/// @{
/**
* @brief Custom comparaison method between two ComponentExtension*
* This method uses the QString::<() (less than operator) to perform the comparaison
* of two ComponentExtension* based on their name.
* This method is used for sorting alphabetically a list of ComponentExtension*.
*
* @param left left ComponentExtension* to compare
* @param right right ComponentExtension* to compare
* @return the comparaison result, based on their name (alphabetically order)
*/
static bool componentExtensionLessThan(const ComponentExtension* left, const ComponentExtension* right);
/**
* @brief Custom comparaison method between two ActionExtension*
* This method uses the QString::<() (less than operator) to perform the comparaison
* of two ActionExtension* based on their name.
* This method is used for sorting alphabetically a list of ActionExtension*.
*
* @param left left ActionExtension* to compare
* @param right right ActionExtension* to compare
* @return the comparaison result, based on their name (alphabetically order)
*
* @note This method does not take const input arguments as the ActionExtension::getName() accessor
* is a mutable method (not const).
* This should be updated, but would change the CamiTK API
* check the Wiki for Code developer guidelines
*/
static bool actionExtensionLessThan(ActionExtension* left, ActionExtension* right);
/**
* @brief Custom comparaison method between two ViewerExtension*
* based on the same principle as actionExtensionLessThan(..)
* @see actionExtensionLessThan(..) for more information
*/
static bool viewerExtensionLessThan(ViewerExtension* left, ViewerExtension* right);
///@}
};
}
#endif //EXTENSIONS_MANAGER_H
|