OpenCOR relies on a plugin approach. Some of its plugins are used to provide access to third-party libraries or APIs while others are used to organise, edit or simulate files, or are plugins that do not fit anywhere else and are therefore put under the miscellaneous category.
We rely on Qt's support for plugins which means that, for each plugin, we must create a couple of files (e.g. [OpenCOR]/src/plugins/misc/Core/src/coreplugin.cpp
and [OpenCOR]/src/plugins/misc/Core/src/coreplugin.h
).
A plugin may implement any of the core, file, GUI, internationalisation and solver interfaces. For example, the Core plugin implements the core, GUI and internationalisation interfaces (see [OpenCOR]/src/plugins/misc/Core/src/coreplugin.h
) while the QScintilla plugin does not implement any interface at all since its sole purpose is to provide access to the QScintilla library (see [OpenCOR]/src/plugins/3rdparty/QScintilla/src/qscintillaplugin.h
).
A plugin's code must be made available under both the OpenCOR
namespace and the plugin's own namespace (e.g. [OpenCOR]/src/plugins/misc/Core/src/coreplugin.cpp
and [OpenCOR]/src/plugins/misc/Core/src/coreplugin.h
):
... namespace OpenCOR { namespace Core { ... } // namespace Core } // namespace OpenCOR [...]
Every plugin must provide the following information (see [OpenCOR]/src/plugins/plugininfo.h):
mInterfaceVersion
in PluginManager
's constructor).
For the Core plugin, the above required information can be found in the PLUGININFO_FUNC CorePluginInfo()
function in [OpenCOR]/src/plugins/misc/Core/src/coreplugin.cpp
and [OpenCOR]/src/plugins/misc/Core/src/coreplugin.h
.
As can be seen, the name of the function is related to the name of the plugin and is <PluginName>PluginInfo
. OpenCOR uses the name of the plugin file to determine the name of that function. This ensures the uniqueness of a plugin.
Support for internationalisation of a plugin's description would normally be done using Qt's tr()
function, but it cannot be done here. So, instead, we use a QMap
-based approach, as can be seen in [OpenCOR]/src/plugins/misc/Core/src/coreplugin.cpp
.
To support plugin dependencies on Windows requires some classes and/or functions to be imported/exported (using Q_DECL_IMPORT
/Q_DECL_EXPORT
, respectively). To handle this, we must create a header file which defines a macro that refers to either Q_DECL_IMPORT
or Q_DECL_EXPORT
, depending on how the plugin code is to be compiled. For the Core plugin, the header file in question is [OpenCOR]/src/plugins/misc/Core/src/coreglobal.h
.
ADD_PLUGIN
macro
Our CMake ADD_PLUGIN
macro is used to both build and package a plugin. However, this requires one or several types of arguments to be passed to ADD_PLUGIN
:
SOURCES
: impementation files.HEADERS_MOC
: header files which define at least one QObject-based class.UIS
: user interface files.INCLUDE_DIRS
: various locations where header files can be found.DEFINITIONS
: definitions needed to build the plugin (e.g. [OpenCOR]/src/plugins/3rdparty/SUNDIALS/CMakeLists.txt
).PLUGIN_DEPENDENCIES
: plugins on which the plugin depends (e.g. [OpenCOR]/src/plugins/misc/Help/CMakeLists.txt
).PLUGIN_BINARY_DEPENDENCIES
: the binary version of other OpenCOR plugins on which the plugin depends (e.g. [OpenCOR]/src/plugins/misc/Compiler/CMakeLists.txt
).QT_MODULES
: Qt modules on which the plugin relies.QT_DEPENDENCIES
: Qt libraries on which the plugin depends.EXTERNAL_BINARY_DEPENDENCIES_DIR
: location of any external binaries needed by the plugin (e.g. [OpenCOR]/src/plugins/api/CellMLAPI/CMakeLists.txt
).EXTERNAL_BINARY_DEPENDENCIES
: external binaries needed by the plugin (e.g. [OpenCOR]/src/plugins/api/CellMLAPI/CMakeLists.txt
).TESTS
: tests for the plugin (e.g. [OpenCOR]/src/plugins/misc/Compiler/CMakeLists.txt
).Due to the intrinsic nature of OS X binaries, it is critical that you list all the Qt libraries on which a plugin depends. Failure to do so may result in OpenCOR not behaving as expected.