|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example tools/plugandpaint |
|
44 \title Plug & Paint Example |
|
45 |
|
46 The Plug & Paint example demonstrates how to write Qt |
|
47 applications that can be extended through plugins. |
|
48 |
|
49 \image plugandpaint.png Screenshot of the Plug & Paint example |
|
50 |
|
51 A plugin is a dynamic library that can be loaded at run-time to |
|
52 extend an application. Qt makes it possible to create custom |
|
53 plugins and to load them using QPluginLoader. To ensure that |
|
54 plugins don't get lost, it is also possible to link them |
|
55 statically to the executable. The Plug & Paint example uses |
|
56 plugins to support custom brushes, shapes, and image filters. A |
|
57 single plugin can provide multiple brushes, shapes, and/or |
|
58 filters. |
|
59 |
|
60 If you want to learn how to make your own application extensible |
|
61 through plugins, we recommend that you start by reading this |
|
62 overview, which explains how to make an application use plugins. |
|
63 Afterward, you can read the |
|
64 \l{tools/plugandpaintplugins/basictools}{Basic Tools} and |
|
65 \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} |
|
66 overviews, which show how to implement static and dynamic |
|
67 plugins, respectively. |
|
68 |
|
69 Plug & Paint consists of the following classes: |
|
70 |
|
71 \list |
|
72 \o \c MainWindow is a QMainWindow subclass that provides the menu |
|
73 system and that contains a \c PaintArea as the central widget. |
|
74 \o \c PaintArea is a QWidget that allows the user to draw using a |
|
75 brush and to insert shapes. |
|
76 \o \c PluginDialog is a dialog that shows information about the |
|
77 plugins detected by the application. |
|
78 \o \c BrushInterface, \c ShapeInterface, and \c FilterInterface are |
|
79 abstract base classes that can be implemented by plugins to |
|
80 provide custom brushes, shapes, and image filters. |
|
81 \endlist |
|
82 |
|
83 \section1 The Plugin Interfaces |
|
84 |
|
85 We will start by reviewing the interfaces defined in \c |
|
86 interfaces.h. These interfaces are used by the Plug & Paint |
|
87 application to access extra functionality. They are implemented |
|
88 in the plugins. |
|
89 |
|
90 |
|
91 \snippet examples/tools/plugandpaint/interfaces.h 0 |
|
92 |
|
93 The \c BrushInterface class declares four pure virtual functions. |
|
94 The first pure virtual function, \c brushes(), returns a list of |
|
95 strings that identify the brushes provided by the plugin. By |
|
96 returning a QStringList instead of a QString, we make it possible |
|
97 for a single plugin to provide multiple brushes. The other |
|
98 functions have a \c brush parameter to identify which brush |
|
99 (among those returned by \c brushes()) is used. |
|
100 |
|
101 \c mousePress(), \c mouseMove(), and \c mouseRelease() take a |
|
102 QPainter and one or two \l{QPoint}s, and return a QRect |
|
103 identifying which portion of the image was altered by the brush. |
|
104 |
|
105 The class also has a virtual destructor. Interface classes |
|
106 usually don't need such a destructor (because it would make |
|
107 little sense to \c delete the object that implements the |
|
108 interface through a pointer to the interface), but some compilers |
|
109 emit a warning for classes that declare virtual functions but no |
|
110 virtual destructor. We provide the destructor to keep these |
|
111 compilers happy. |
|
112 |
|
113 \snippet examples/tools/plugandpaint/interfaces.h 1 |
|
114 |
|
115 The \c ShapeInterface class declares a \c shapes() function that |
|
116 works the same as \c{BrushInterface}'s \c brushes() function, and |
|
117 a \c generateShape() function that has a \c shape parameter. |
|
118 Shapes are represented by a QPainterPath, a data type that can |
|
119 represent arbitrary 2D shapes or combinations of shapes. The \c |
|
120 parent parameter can be used by the plugin to pop up a dialog |
|
121 asking the user to specify more information. |
|
122 |
|
123 \snippet examples/tools/plugandpaint/interfaces.h 2 |
|
124 |
|
125 The \c FilterInterface class declares a \c filters() function |
|
126 that returns a list of filter names, and a \c filterImage() |
|
127 function that applies a filter to an image. |
|
128 |
|
129 \snippet examples/tools/plugandpaint/interfaces.h 4 |
|
130 |
|
131 To make it possible to query at run-time whether a plugin |
|
132 implements a given interface, we must use the \c |
|
133 Q_DECLARE_INTERFACE() macro. The first argument is the name of |
|
134 the interface. The second argument is a string identifying the |
|
135 interface in a unique way. By convention, we use a "Java package |
|
136 name" syntax to identify interfaces. If we later change the |
|
137 interfaces, we must use a different string to identify the new |
|
138 interface; otherwise, the application might crash. It is therefore |
|
139 a good idea to include a version number in the string, as we did |
|
140 above. |
|
141 |
|
142 The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin |
|
143 and the \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} |
|
144 plugin shows how to derive from \c BrushInterface, \c |
|
145 ShapeInterface, and \c FilterInterface. |
|
146 |
|
147 A note on naming: It might have been tempting to give the \c |
|
148 brushes(), \c shapes(), and \c filters() functions a more generic |
|
149 name, such as \c keys() or \c features(). However, that would |
|
150 have made multiple inheritance impractical. When creating |
|
151 interfaces, we should always try to give unique names to the pure |
|
152 virtual functions. |
|
153 |
|
154 \section1 The MainWindow Class |
|
155 |
|
156 The \c MainWindow class is a standard QMainWindow subclass, as |
|
157 found in many of the other examples (e.g., |
|
158 \l{mainwindows/application}{Application}). Here, we'll |
|
159 concentrate on the parts of the code that are related to plugins. |
|
160 |
|
161 \snippet examples/tools/plugandpaint/mainwindow.cpp 4 |
|
162 |
|
163 The \c loadPlugins() function is called from the \c MainWindow |
|
164 constructor to detect plugins and update the \gui{Brush}, |
|
165 \gui{Shapes}, and \gui{Filters} menus. We start by handling static |
|
166 plugins (available through QPluginLoader::staticInstances()) |
|
167 |
|
168 To the application that uses the plugin, a Qt plugin is simply a |
|
169 QObject. That QObject implements plugin interfaces using multiple |
|
170 inheritance. |
|
171 |
|
172 \snippet examples/tools/plugandpaint/mainwindow.cpp 5 |
|
173 |
|
174 The next step is to load dynamic plugins. We initialize the \c |
|
175 pluginsDir member variable to refer to the \c plugins |
|
176 subdirectory of the Plug & Paint example. On Unix, this is just a |
|
177 matter of initializing the QDir variable with |
|
178 QApplication::applicationDirPath(), the path of the executable |
|
179 file, and to do a \l{QDir::cd()}{cd()}. On Windows and Mac OS X, |
|
180 this file is usually located in a subdirectory, so we need to |
|
181 take this into account. |
|
182 |
|
183 \snippet examples/tools/plugandpaint/mainwindow.cpp 6 |
|
184 \snippet examples/tools/plugandpaint/mainwindow.cpp 7 |
|
185 \snippet examples/tools/plugandpaint/mainwindow.cpp 8 |
|
186 |
|
187 We use QDir::entryList() to get a list of all files in that |
|
188 directory. Then we iterate over the result using \l foreach and |
|
189 try to load the plugin using QPluginLoader. |
|
190 |
|
191 The QObject provided by the plugin is accessible through |
|
192 QPluginLoader::instance(). If the dynamic library isn't a Qt |
|
193 plugin, or if it was compiled against an incompatible version of |
|
194 the Qt library, QPluginLoader::instance() returns a null pointer. |
|
195 |
|
196 If QPluginLoader::instance() is non-null, we add it to the menus. |
|
197 |
|
198 \snippet examples/tools/plugandpaint/mainwindow.cpp 9 |
|
199 |
|
200 At the end, we enable or disable the \gui{Brush}, \gui{Shapes}, |
|
201 and \gui{Filters} menus based on whether they contain any items. |
|
202 |
|
203 \snippet examples/tools/plugandpaint/mainwindow.cpp 10 |
|
204 |
|
205 For each plugin (static or dynamic), we check which interfaces it |
|
206 implements using \l qobject_cast(). First, we try to cast the |
|
207 plugin instance to a \c BrushInterface; if it works, we call the |
|
208 private function \c addToMenu() with the list of brushes returned |
|
209 by \c brushes(). Then we do the same with the \c ShapeInterface |
|
210 and the \c FilterInterface. |
|
211 |
|
212 \snippet examples/tools/plugandpaint/mainwindow.cpp 3 |
|
213 |
|
214 The \c aboutPlugins() slot is called on startup and can be |
|
215 invoked at any time through the \gui{About Plugins} action. It |
|
216 pops up a \c PluginDialog, providing information about the loaded |
|
217 plugins. |
|
218 |
|
219 \image plugandpaint-plugindialog.png Screenshot of the Plugin dialog |
|
220 |
|
221 |
|
222 The \c addToMenu() function is called from \c loadPlugin() to |
|
223 create \l{QAction}s for custom brushes, shapes, or filters and |
|
224 add them to the relevant menu. The QAction is created with the |
|
225 plugin from which it comes from as the parent; this makes it |
|
226 convenient to get access to the plugin later. |
|
227 |
|
228 \snippet examples/tools/plugandpaint/mainwindow.cpp 0 |
|
229 |
|
230 The \c changeBrush() slot is invoked when the user chooses one of |
|
231 the brushes from the \gui{Brush} menu. We start by finding out |
|
232 which action invoked the slot using QObject::sender(). Then we |
|
233 get the \c BrushInterface out of the plugin (which we |
|
234 conveniently passed as the QAction's parent) and we call \c |
|
235 PaintArea::setBrush() with the \c BrushInterface and the string |
|
236 identifying the brush. Next time the user draws on the paint |
|
237 area, \c PaintArea will use this brush. |
|
238 |
|
239 \snippet examples/tools/plugandpaint/mainwindow.cpp 1 |
|
240 |
|
241 The \c insertShape() is invoked when the use chooses one of the |
|
242 shapes from the \gui{Shapes} menu. We retrieve the QAction that |
|
243 invoked the slot, then the \c ShapeInterface associated with that |
|
244 QAction, and finally we call \c ShapeInterface::generateShape() |
|
245 to obtain a QPainterPath. |
|
246 |
|
247 \snippet examples/tools/plugandpaint/mainwindow.cpp 2 |
|
248 |
|
249 The \c applyFilter() slot is similar: We retrieve the QAction |
|
250 that invoked the slot, then the \c FilterInterface associated to |
|
251 that QAction, and finally we call \c |
|
252 FilterInterface::filterImage() to apply the filter onto the |
|
253 current image. |
|
254 |
|
255 \section1 The PaintArea Class |
|
256 |
|
257 The \c PaintArea class contains some code that deals with \c |
|
258 BrushInterface, so we'll review it briefly. |
|
259 |
|
260 \snippet examples/tools/plugandpaint/paintarea.cpp 0 |
|
261 |
|
262 In \c setBrush(), we simply store the \c BrushInterface and the |
|
263 brush that are given to us by \c MainWindow. |
|
264 |
|
265 \snippet examples/tools/plugandpaint/paintarea.cpp 1 |
|
266 |
|
267 In the \l{QWidget::mouseMoveEvent()}{mouse move event handler}, |
|
268 we call the \c BrushInterface::mouseMove() function on the |
|
269 current \c BrushInterface, with the current brush. The mouse |
|
270 press and mouse release handlers are very similar. |
|
271 |
|
272 \section1 The PluginDialog Class |
|
273 |
|
274 The \c PluginDialog class provides information about the loaded |
|
275 plugins to the user. Its constructor takes a path to the plugins |
|
276 and a list of plugin file names. It calls \c findPlugins() |
|
277 to fill the QTreeWdiget with information about the plugins: |
|
278 |
|
279 \snippet examples/tools/plugandpaint/plugindialog.cpp 0 |
|
280 |
|
281 The \c findPlugins() is very similar to \c |
|
282 MainWindow::loadPlugins(). It uses QPluginLoader to access the |
|
283 static and dynamic plugins. Its helper function \c |
|
284 populateTreeWidget() uses \l qobject_cast() to find out which |
|
285 interfaces are implemented by the plugins: |
|
286 |
|
287 \snippet examples/tools/plugandpaint/plugindialog.cpp 1 |
|
288 |
|
289 \section1 Importing Static Plugins |
|
290 |
|
291 The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin |
|
292 is built as a static plugin, to ensure that it is always |
|
293 available to the application. This requires using the |
|
294 Q_IMPORT_PLUGIN() macro somewhere in the application (in a \c |
|
295 .cpp file) and specifying the plugin in the \c .pro file. |
|
296 |
|
297 For Plug & Paint, we have chosen to put Q_IMPORT_PLUGIN() in \c |
|
298 main.cpp: |
|
299 |
|
300 \snippet examples/tools/plugandpaint/main.cpp 0 |
|
301 |
|
302 The argument to Q_IMPORT_PLUGIN() is the plugin's name, as |
|
303 specified with Q_EXPORT_PLUGIN2() in the \l{Exporting the |
|
304 Plugin}{plugin}. |
|
305 |
|
306 In the \c .pro file, we need to specify the static library. |
|
307 Here's the project file for building Plug & Paint: |
|
308 |
|
309 \snippet examples/tools/plugandpaint/plugandpaint.pro 0 |
|
310 |
|
311 The \c LIBS line variable specifies the library \c pnp_basictools |
|
312 located in the \c ../plugandpaintplugins/basictools directory. |
|
313 (Although the \c LIBS syntax has a distinct Unix flavor, \c qmake |
|
314 supports it on all platforms.) |
|
315 |
|
316 The \c CONFIG() code at the end is necessary for this example |
|
317 because the example is part of the Qt distribution and Qt can be |
|
318 configured to be built simultaneously in debug and in release |
|
319 modes. You don't need to for your own plugin applications. |
|
320 |
|
321 This completes our review of the Plug & Paint application. At |
|
322 this point, you might want to take a look at the |
|
323 \l{tools/plugandpaintplugins/basictools}{Basic Tools} example |
|
324 plugin. |
|
325 */ |
|
326 |
|
327 /*! |
|
328 \example tools/plugandpaintplugins/basictools |
|
329 \title Plug & Paint Basic Tools Example |
|
330 |
|
331 The Basic Tools example is a static plugin for the |
|
332 \l{tools/plugandpaint}{Plug & Paint} example. It provides a set |
|
333 of basic brushes, shapes, and filters. Through the Basic Tools |
|
334 example, we will review the four steps involved in writing a Qt |
|
335 plugin: |
|
336 |
|
337 \list 1 |
|
338 \o Declare a plugin class. |
|
339 \o Implement the interfaces provided by the plugin. |
|
340 \o Export the plugin using the Q_EXPORT_PLUGIN2() macro. |
|
341 \o Build the plugin using an adequate \c .pro file. |
|
342 \endlist |
|
343 |
|
344 \section1 Declaration of the Plugin Class |
|
345 |
|
346 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 0 |
|
347 |
|
348 We start by including \c interfaces.h, which defines the plugin |
|
349 interfaces for the \l{tools/plugandpaint}{Plug & Paint} |
|
350 application. For the \c #include to work, we need to add an \c |
|
351 INCLUDEPATH entry to the \c .pro file with the path to Qt's \c |
|
352 examples/tools directory. |
|
353 |
|
354 The \c BasicToolsPlugin class is a QObject subclass that |
|
355 implements the \c BrushInterface, the \c ShapeInterface, and the |
|
356 \c FilterInterface. This is done through multiple inheritance. |
|
357 The \c Q_INTERFACES() macro is necessary to tell \l{moc}, Qt's |
|
358 meta-object compiler, that the base classes are plugin |
|
359 interfaces. Without the \c Q_INTERFACES() macro, we couldn't use |
|
360 \l qobject_cast() in the \l{tools/plugandpaint}{Plug & Paint} |
|
361 application to detect interfaces. |
|
362 |
|
363 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 2 |
|
364 |
|
365 In the \c public section of the class, we declare all the |
|
366 functions from the three interfaces. |
|
367 |
|
368 \section1 Implementation of the Brush Interface |
|
369 |
|
370 Let's now review the implementation of the \c BasicToolsPlugin |
|
371 member functions inherited from \c BrushInterface. |
|
372 |
|
373 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 0 |
|
374 |
|
375 The \c brushes() function returns a list of brushes provided by |
|
376 this plugin. We provide three brushes: \gui{Pencil}, \gui{Air |
|
377 Brush}, and \gui{Random Letters}. |
|
378 |
|
379 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 1 |
|
380 |
|
381 On a mouse press event, we just call \c mouseMove() to draw the |
|
382 spot where the event occurred. |
|
383 |
|
384 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 2 |
|
385 |
|
386 In \c mouseMove(), we start by saving the state of the QPainter |
|
387 and we compute a few variables that we'll need later. |
|
388 |
|
389 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 3 |
|
390 |
|
391 Then comes the brush-dependent part of the code: |
|
392 |
|
393 \list |
|
394 \o If the brush is \gui{Pencil}, we just call |
|
395 QPainter::drawLine() with the current QPen. |
|
396 |
|
397 \o If the brush is \gui{Air Brush}, we start by setting the |
|
398 painter's QBrush to Qt::Dense6Pattern to obtain a dotted |
|
399 pattern. Then we draw a circle filled with that QBrush several |
|
400 times, resulting in a thick line. |
|
401 |
|
402 \o If the brush is \gui{Random Letters}, we draw a random letter |
|
403 at the new cursor position. Most of the code is for setting |
|
404 the font to be bold and larger than the default font and for |
|
405 computing an appropriate bounding rect. |
|
406 \endlist |
|
407 |
|
408 At the end, we restore the painter state to what it was upon |
|
409 entering the function and we return the bounding rectangle. |
|
410 |
|
411 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 4 |
|
412 |
|
413 When the user releases the mouse, we do nothing and return an |
|
414 empty QRect. |
|
415 |
|
416 \section1 Implementation of the Shape Interface |
|
417 |
|
418 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 5 |
|
419 |
|
420 The plugin provides three shapes: \gui{Circle}, \gui{Star}, and |
|
421 \gui{Text...}. The three dots after \gui{Text} are there because |
|
422 the shape pops up a dialog asking for more information. We know |
|
423 that the shape names will end up in a menu, so we include the |
|
424 three dots in the shape name. |
|
425 |
|
426 A cleaner but more complicated design would have been to |
|
427 distinguish between the internal shape name and the name used in |
|
428 the user interface. |
|
429 |
|
430 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 6 |
|
431 |
|
432 The \c generateShape() creates a QPainterPath for the specified |
|
433 shape. If the shape is \gui{Text}, we pop up a QInputDialog to |
|
434 let the user enter some text. |
|
435 |
|
436 \section1 Implementation of the Filter Interface |
|
437 |
|
438 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 7 |
|
439 |
|
440 The plugin provides three filters: \gui{Invert Pixels}, \gui{Swap |
|
441 RGB}, and \gui{Grayscale}. |
|
442 |
|
443 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 8 |
|
444 |
|
445 The \c filterImage() function takes a filter name and a QImage as |
|
446 parameters and returns an altered QImage. The first thing we do |
|
447 is to convert the image to a 32-bit RGB format, to ensure that |
|
448 the algorithms will work as expected. For example, |
|
449 QImage::invertPixels(), which is used to implement the |
|
450 \gui{Invert Pixels} filter, gives counterintuitive results for |
|
451 8-bit images, because they invert the indices into the color |
|
452 table instead of inverting the color table's entries. |
|
453 |
|
454 \section1 Exporting the Plugin |
|
455 |
|
456 Whereas applications have a \c main() function as their entry |
|
457 point, plugins need to contain exactly one occurrence of the |
|
458 Q_EXPORT_PLUGIN2() macro to specify which class provides the |
|
459 plugin: |
|
460 |
|
461 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 9 |
|
462 |
|
463 This line may appear in any \c .cpp file that is part of the |
|
464 plugin's source code. |
|
465 |
|
466 \section1 The .pro File |
|
467 |
|
468 Here's the project file for building the Basic Tools plugin: |
|
469 |
|
470 \snippet examples/tools/plugandpaintplugins/basictools/basictools.pro 0 |
|
471 |
|
472 The \c .pro file differs from typical \c .pro files in many |
|
473 respects. First, it starts with a \c TEMPLATE entry specifying \c |
|
474 lib. (The default template is \c app.) It also adds \c plugin to |
|
475 the \c CONFIG variable. This is necessary on some platforms to |
|
476 avoid generating symbolic links with version numbers in the file |
|
477 name, which is appropriate for most dynamic libraries but not for |
|
478 plugins. |
|
479 |
|
480 To make the plugin a static plugin, all that is required is to |
|
481 specify \c static in addition to \c plugin. The |
|
482 \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} plugin, |
|
483 which is compiled as a dynamic plugin, doesn't specify \c static |
|
484 in its \c .pro file. |
|
485 |
|
486 The \c INCLUDEPATH variable sets the search paths for global |
|
487 headers (i.e., header files included using \c{#include <...>}). |
|
488 We add Qt's \c examples/tools directory (strictly speaking, |
|
489 \c{examples/tools/plugandpaintplugins/basictools/../..}) to the |
|
490 list, so that we can include \c <plugandpaint/interfaces.h>. |
|
491 |
|
492 The \c TARGET variable specifies which name we want to give the |
|
493 target library. We use \c pnp_ as the prefix to show that the |
|
494 plugin is designed to work with Plug & Paint. On Unix, \c lib is |
|
495 also prepended to that name. On all platforms, a |
|
496 platform-specific suffix is appended (e.g., \c .dll on Windows, |
|
497 \c .a on Linux). |
|
498 |
|
499 The \c CONFIG() code at the end is necessary for this example |
|
500 because the example is part of the Qt distribution and Qt can be |
|
501 configured to be built simultaneously in debug and in release |
|
502 modes. You don't need to for your own plugins. |
|
503 */ |
|
504 |
|
505 /*! |
|
506 \example tools/plugandpaintplugins/extrafilters |
|
507 \title Plug & Paint Extra Filters Example |
|
508 |
|
509 The Extra Filters example is a plugin for the |
|
510 \l{tools/plugandpaint}{Plug & Paint} example. It provides a set |
|
511 of filters in addition to those provided by the |
|
512 \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin. |
|
513 |
|
514 Since the approach is identical to |
|
515 \l{tools/plugandpaintplugins/basictools}{Basic Tools}, we won't |
|
516 review the code here. The only part of interes is the |
|
517 \c .pro file, since Extra Filters is a dynamic plugin |
|
518 (\l{tools/plugandpaintplugins/basictools}{Basic Tools} is |
|
519 linked statically into the Plug & Paint executable). |
|
520 |
|
521 Here's the project file for building the Extra Filters plugin: |
|
522 |
|
523 \snippet examples/tools/plugandpaintplugins/extrafilters/extrafilters.pro 0 |
|
524 |
|
525 The \c .pro file differs from typical \c .pro files in many |
|
526 respects. First, it starts with a \c TEMPLATE entry specifying \c |
|
527 lib. (The default template is \c app.) It also adds \c plugin to |
|
528 the \c CONFIG variable. This is necessary on some platforms to |
|
529 avoid generating symbolic links with version numbers in the file |
|
530 name, which is appropriate for most dynamic libraries but not for |
|
531 plugins. |
|
532 |
|
533 The \c INCLUDEPATH variable sets the search paths for global |
|
534 headers (i.e., header files included using \c{#include <...>}). |
|
535 We add Qt's \c examples/tools directory (strictly speaking, |
|
536 \c{examples/tools/plugandpaintplugins/basictools/../..}) to the |
|
537 list, so that we can include \c <plugandpaint/interfaces.h>. |
|
538 |
|
539 The \c TARGET variable specifies which name we want to give the |
|
540 target library. We use \c pnp_ as the prefix to show that the |
|
541 plugin is designed to work with Plug & Paint. On Unix, \c lib is |
|
542 also prepended to that name. On all platforms, a |
|
543 platform-specific suffix is appended (e.g., \c .dll on Windows, |
|
544 \c .so on Linux). |
|
545 |
|
546 The \c DESTDIR variable specifies where we want to install the |
|
547 plugin. We put it in Plug & Paint's \c plugins subdirectory, |
|
548 since that's where the application looks for dynamic plugins. |
|
549 |
|
550 The \c CONFIG() code at the end is necessary for this example |
|
551 because the example is part of the Qt distribution and Qt can be |
|
552 configured to be built simultaneously in debug and in release |
|
553 modes. You don't need to for your own plugins. |
|
554 */ |