PluginProgramming.docu 11.1 KB
Newer Older
Jan Möbius's avatar
 
Jan Möbius committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*! \page pluginProgramming Plugin Programming
 * \section plugin_sec Plugin Basics
 * 
 * As mentioned above Openflipper is a plugin  based system. It uses the qt plugin implementation to
 * load and unload plugins at runtime. Every algorithm should be added as one of these plugins. 
 * 
 * The plugins have to be created as .so (or under windows : .dll) files which should be symlinked or 
 * copied to the Plugin subfolder. OpenFlipper distinguishes between 32/64-bit plugin versions and
 * max or dbg (release/debug) versions. So the compiled plugins have to reside in the right subdir of
 * Plugins. The Plugins are loaded on startup of the application (they may also be loaded at runtime 
 * later). 
 * 
 * \section plugin_prog_sec Plugin programming
 * The interface between the core and the plugins is managed via simple interfaces based on the signal/slot
Dirk Wilden's avatar
Dirk Wilden committed
15
 * metaphor of qt. Your plugins have to be derived from these interfaces. You dont have to implement
Jan Möbius's avatar
 
Jan Möbius committed
16
17
18
19
20
21
22
 * all functions or signals of the interfaces you include. This has only to be done for the BaseInterface 
 * which must be implemented by every plugin. See the BaseInterface Documentation for details.
 * 
 * Unimplemented functions will be left unconnected from the core and wont have any impact on the applications
 * speed or stability. As stated above, every plugin has to be derived from the BaseInterface. This is the
 * basic factory which makes the core aware of the plugin. The name and the description of the plugin is 
 * exported via the baseinterface. The initialization of each plugin is done via this interface too.
23
 * See \ref dataFlow for an overview of OpenFlipper's data flow and interface function calls.
Jan Möbius's avatar
 
Jan Möbius committed
24
25
26
27
 * 
 * After this interface of the plugin is sucessfully processed all other interfaces will be initialized
 * and connected to the core. For details about the individual interfaces see their documentation. 
 * \ref interfaces
28
29
30
31
32
33
34
35
36
 *
 * \section ex1 A simple example
 *
 * In this section we are going to build our own OpenFlipper plugin step by step. The goal of this
 * tutorial is to build a simple plugin that is loaded by OpenFlipper at launch.
 *
 * We start by creating the plugin directory in OpenFlipper's root directory,
 * naming it e.g. \c Plugin-SimplePlugin.
 * The interface definition should contain the following header includes:
Jan Möbius's avatar
 
Jan Möbius committed
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
 * \dontinclude example/simplePlugin.hh
 * \skipline #include
 * \until Types.hh>
 *
 * As we know the plugin class has to be derived from at least \c BaseInterface,
 * the class definition will look like:
 *
 * \dontinclude example/simplePlugin.hh
 * \skipline class
 *
 * (Since we implement a Qt-class, our base object is QObject which provides
 * some basic functionality and type definitions.)
 * We then use the macros \c Q_OBJECT and \c Q_INTERFACES in order to make accessible the signals and
 * slots which have to be overridden later on. See BaseInterface documentation for signals and slots
 * that can be overriden.
 *
 * \dontinclude example/simplePlugin.hh
 * \skipline Q_OBJECT
 * \skipline Q_INTERFACES
 *
 * For now, the only thing we override from our base class is \c name() and \c description() which
 * each returns the name and description of our plugin, respectively. The override of these two
 * functions is mandatory, all other slots/signals are optional.
 * Each of the functions returns a QString (see Qt documentation for information on Qt types).
 *
 * \dontinclude example/simplePlugin.hh
 * \skipline QString name(
 * \skipline QString description(
 *
 * If you made it to this point, don't give up, we're almost there! Looks like this is it for
 * the interface definition. We're now considering our implementation which consists of only a few lines.
 * (Since we don't want to implement any functionality at this point).
 *
 * The implementation only contains the macro
 *
 * \dontinclude example/simplePlugin.cc
 * \skipline Q_EXPORT
 *
 * which exports the plugin class \c SimplePlugin with the name \c simplePlugin (note that our class
 * name is with a capital s whereas the export name is lower case). An important constraint is
 * that the export name has to be unique (in case there exist multiple plugins).
 *
80
 * The complete source code of the plugin looks like this:
81
82
83
84
85
86
 *
 * simplePlugin.hh
 * \include example/simplePlugin.hh
 *
 * simplePlugin.cc
 * \include example/simplePlugin.cc
87
88
89
90
91
92
93
 *
 * \section ex1b Building our plugin
 * 
 * The only thing that's still left to be created is our qmake project file
 * that is used to generate the Makefiles for the plugin. For general information on how to build
 * OpenFlipper with qmake see \ref buildingOpenFlipper.
 * So lets get started! First off we create a file \c Plugin-SimplePlugin.pro in the plugins's directory.
Mike Kremer's avatar
Mike Kremer committed
94
 * It is mandatory to name the project file after the project's directory.
95
96
 *
 * Our first line includes OpenFlipper's predefined qmake functions. This allows us to simply call
Mike Kremer's avatar
Mike Kremer committed
97
 * \c Plugin() in order to build our code as a plugin. The variable \c DIRECTORY holds
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 * the directories that are to be build (we only need the plugin's directory here since the plugin does not
 * depend on external libraries or sources). Our project file looks like this:
 *
 * Plugin-SimplePlugin.pro
 * \include example/Plugin-SimplePlugin.pro
 *
 * The \c HEADERS and \c SOURCES variables should be self-explanatory. \c FORMS contains qt user interface
 * files which aren't needed at this time but become important when using user forms for the plugin.
 *
 * Now go to the root path of OpenFlipper and enter \c qmake (be sure to use version 4 of qmake; some
 * linux distributions use the link \c qmake-qt4 against the executable) in order to create
 * the new Makefiles now containing our plugin. We now build OpenFlipper by entering \c make.
 *
 * To test if our plugin has been successfully loaded, we launch OpenFlipper and select \c Plugins->Unload \c Plugin.
 * If our plugin \c SimplePlugin is listed, everything is fine. If it's not listed, read OpenFlippers
Dirk Wilden's avatar
Dirk Wilden committed
113
 * log to see what went wrong.
114
115
 *
 * See \ref dataFlow for further information on interface function calls.
Dirk Wilden's avatar
Dirk Wilden committed
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
 *
 *
 * \section ex2 Implementing a mesh smoother Plugin
 *
 * The last section dealt with the implementation of a first plugin without any functionality at all. This section
 * will show you how to progam a simple mesh smoother. We are assuming that you have read \ref ex1 and will only
 * explain parts that have to be added in order to include new functionality.
 *
 *
 * \subsection ex2Header Definition of the header
 *
 * To start of we first have to add two additional header files. The first one is the \c ToolboxInterface.
 * We need this interface because we want to add a Toolbox to our plugin in order to be able to set parameters.
 * Additionally, we want to use the \c LoggingInterface so that we can inform the user of our plugin when something
 * went wrong.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline #include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
 * \skipline #include <OpenFlipper/BasePlugin/LoggingInterface.hh>
 *
 * In order to work with the Interfaces we have to define that the plugin will implement the additional interfaces.
 * The class definition then looks as follows:
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline class SmootherPlugin
 *
 * Furthermore we have to insert the \c Q_INTERFACES macro. This makes the signals and slots from both interfaces available.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline Q_INTERFACES(ToolboxInterface)
 * \skipline Q_INTERFACES(LoggingInterface)
 *
 * Now that we have defined which Interfaces to implement, we can look at which signals and slots we want to implement.
 * Firstly, we need two additional signals from the \c BaseInterface :
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline void updateView()
 * \skipline void updatedObject(
 *
 * The first signal updateView() is emitted when we have finished computing the smoothed mesh. The signal tells OpenFlipper
 * to redraw its viewer(s). The second signal updatedObjects() is emitted to inform all other plugins that an object
 * has changed and therfore allows each plugin to react on this change.
 *
 * Since we also want to use the \c LoggingInterface we have to define the following signals which allow us to send
 * log messages to the OpenFlipper Loggers.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline void log(
 * \skipline void log(
 *
 *
 * The last Interface that's left over is the \c ToolboxInterface from which we are only implenting one function:
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline bool initializeToolbox
 *
 * As we will see later, this function is used to setup a ToolBox (i.e. a \c QWidget ) and return a reference of this
 * ToolBox to OpenFlipper so that it can be intergrated into the GUI.
 *
 * As a last step we have to add to include additional class members to control the parameter for the smoothing and
 * to actually compute the smoothed mesh.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline private:
 * \until Laplace();
 *
 * That's it for the header of the plugin. The complete header looks like this:
 *
 * \include example/SmootherPlugin.hh 
 *
 *
 * \subsection ex2Implemenation1 Implemention of the GUI
 *
 * As we have already mentioned in \ref ex2Header, the ToolBox is generated inside the initializeToolbox() function.
 * So inside this function we begin with creating the elements of the ToolBox:
 * 
 * \dontinclude example/SmootherPlugin.cc
 * \skipline QWidget
 * \until Iterations:");
 *
 * Later, the smoothButton is used to start the mesh smoothing and the iterationsSpinbox_ allows the user to control
 * the number of smoothing iterations that should be performed.
 *
 * The created Toolbox elements are then combined into a Layout
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline QGridLayout
 * \until 2,0,1,2);
 *
 * Here, the SpacerItem, which is added last, only helps aligning the elements at the top of the toolbox.
 *
 * We have to connect the smoothButton to the simpleLaplace() slot of our class, so that after clicking
 * the button the slot is called. Finally, we return a reference to the new Toolbox by assigning it to _widget and
 * return true because we succesfully created the Toolbox.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline connect
 * \until true;
 *
 *
 * \subsection ex2Implemenation2 Implemention of the Smoother
 *
 * Now that the Toolbox is completely setup, we can start implementing the smoother. We begin with searching objects
 * on which we have to compute the smoothing. The algorithm takes all objects marked as target and tries to apply the
 * smoothing.
 *
 * To find all these Objects we use an ObjectIterator. This iterator can be found in the PluginFunctions. Every
 * communication between OpenFlipper and its Plugins is accomplished through either an interface or the PluginFunctions.
 * So these are the places to look for if you want to add additional functionality and therefore need to communicate
 * with OpenFlipper.
 *
 * We initialize the PluginFunctions::ObjectIterator with PluginFunctions::TARGET_OBJECTS and thereby make sure that the
 * the iteration is restricted to target objects only.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline void SmootherPlugin::simpleLaplace() {
 * \until ++o_it) {
 *
 *
 *
 *
 *
Jan Möbius's avatar
 
Jan Möbius committed
238
 */