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