File: ExtensionManager.h

package info (click to toggle)
camitk 6.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 389,508 kB
  • sloc: cpp: 103,476; sh: 2,448; python: 1,618; xml: 984; makefile: 128; perl: 84; sed: 20
file content (379 lines) | stat: -rw-r--r-- 17,538 bytes parent folder | download
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