source: trunk/doc/src/examples/containerextension.qdoc@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 23.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \example designer/containerextension
30 \title Container Extension Example
31
32 The Container Extension example shows how to create a custom
33 multi-page plugin for Qt Designer using the
34 QDesignerContainerExtension class.
35
36 \image containerextension-example.png
37
38 To provide a custom widget that can be used with \QD, we need to
39 supply a self-contained implementation. In this example we use a
40 custom multi-page widget designed to show the container extension
41 feature.
42
43 An extension is an object which modifies the behavior of \QD. The
44 QDesignerContainerExtension enables \QD to manage and manipulate a
45 custom multi-page widget, i.e. adding and deleting pages to the
46 widget.
47
48 There are four available types of extensions in \QD:
49
50 \list
51 \o QDesignerMemberSheetExtension provides an extension that allows
52 you to manipulate a widget's member functions which is displayed
53 when configuring connections using Qt Designer's mode for editing
54 signals and slots.
55 \o QDesignerPropertySheetExtension provides an extension that
56 allows you to manipulate a widget's properties which is displayed
57 in Qt Designer's property editor.
58 \o QDesignerTaskMenuExtension provides an extension that allows
59 you to add custom menu entries to \QD's task menu.
60 \o QDesignerContainerExtension provides an extension that allows
61 you to add (and delete) pages to a multi-page container plugin
62 in \QD.
63 \endlist
64
65 You can use all the extensions following the same pattern as in
66 this example, only replacing the respective extension base
67 class. For more information, see the \l {QtDesigner Module}.
68
69 The Container Extension example consists of four classes:
70
71 \list
72 \o \c MultiPageWidget is a custom container widget that lets the user
73 manipulate and populate its pages, and navigate among these
74 using a combobox.
75 \o \c MultiPageWidgetPlugin exposes the \c MultiPageWidget class
76 to \QD.
77 \o \c MultiPageWidgetExtensionFactory creates a
78 \c MultiPageWidgetContainerExtension object.
79 \o \c MultiPageWidgetContainerExtension provides the container
80 extension.
81 \endlist
82
83 The project file for custom widget plugins needs some additional
84 information to ensure that they will work within \QD. For example,
85 custom widget plugins rely on components supplied with \QD, and
86 this must be specified in the project file that we use. We will
87 first take a look at the plugin's project file.
88
89 Then we will continue by reviewing the \c MultiPageWidgetPlugin
90 class, and take a look at the \c MultiPageWidgetExtensionFactory
91 and \c MultiPageWidgetContainerExtension classes. Finally, we will
92 take a quick look at the \c MultiPageWidget class definition.
93
94 \section1 The Project File: containerextension.pro
95
96 The project file must contain some additional information to
97 ensure that the plugin will work as expected:
98
99 \snippet examples/designer/containerextension/containerextension.pro 0
100 \snippet examples/designer/containerextension/containerextension.pro 1
101
102 The \c TEMPLATE variable's value makes \c qmake create the custom
103 widget as a library. Later, we will ensure that the widget will be
104 recognized as a plugin by Qt by using the Q_EXPORT_PLUGIN2() macro
105 to export the relevant widget information.
106
107 The \c CONFIG variable contains two values, \c designer and \c
108 plugin:
109
110 \list
111 \o \c designer: Since custom widgets plugins rely on components
112 supplied with \QD, this value ensures that our plugin links against
113 \QD's library (\c libQtDesigner.so).
114
115 \o \c plugin: We also need to ensure that \c qmake considers the
116 custom widget a \e plugin library.
117 \endlist
118
119 When Qt is configured to build in both debug and release modes,
120 \QD will be built in release mode. When this occurs, it is
121 necessary to ensure that plugins are also built in release
122 mode. For that reason we add a \c debug_and_release value to the
123 \c CONFIG variable. Otherwise, if a plugin is built in a mode that
124 is incompatible with \QD, it won't be loaded and installed.
125
126 The header and source files for the widget are declared in the
127 usual way:
128
129 \snippet examples/designer/containerextension/containerextension.pro 2
130
131 We provide an implementation of the plugin interface so that \QD
132 can use the custom widget. In this particular example we also
133 provide implementations of the container extension interface and
134 the extension factory.
135
136 It is important to ensure that the plugin is installed in a
137 location that is searched by \QD. We do this by specifying a
138 target path for the project and adding it to the list of items to
139 install:
140
141 \snippet doc/src/snippets/code/doc_src_examples_containerextension.qdoc 0
142
143 The container extension is created as a library, and will be
144 installed alongside the other \QD plugins when the project is
145 installed (using \c{make install} or an equivalent installation
146 procedure).
147
148 Note that if you want the plugins to appear in a Visual Studio
149 integration, the plugins must be built in release mode and their
150 libraries must be copied into the plugin directory in the install
151 path of the integration (for an example, see \c {C:/program
152 files/trolltech as/visual studio integration/plugins}).
153
154 For more information about plugins, see the \l {How to Create Qt
155 Plugins} documentation.
156
157 \section1 MultiPageWidgetPlugin Class Definition
158
159 The \c MultiPageWidgetPlugin class exposes the \c MultiPageWidget
160 class to \QD. Its definition is similar to the \l
161 {designer/customwidgetplugin}{Custom Widget Plugin} example's
162 plugin class which is explained in detail. The parts of the class
163 definition that is specific to this particular custom widget is
164 the class name and a couple of private slots:
165
166 \snippet examples/designer/containerextension/multipagewidgetplugin.h 0
167
168 The plugin class provides \QD with basic information about our
169 plugin, such as its class name and its include file. Furthermore
170 it knows how to create instances of the \c MultiPageWidget widget.
171 \c MultiPageWidgetPlugin also defines the \l
172 {QDesignerCustomWidgetInterface::initialize()}{initialize()}
173 function which is called after the plugin is loaded into \QD. The
174 function's QDesignerFormEditorInterface parameter provides the
175 plugin with a gateway to all of \QD's API's.
176
177 In the case of a multipage widget such as ours, we must also implement
178 two private slots, currentIndexChanged() and pageTitleChanged(),
179 to be able to update \QD's property editor whenever the user views
180 another page or changes one of the page titles. To be able to give
181 each page their own title, we have chosen to use the
182 QWidget::windowTitle property to store the page title (for more
183 information see the MultiPageWidget class \l
184 {designer/containerextension/multipagewidget.cpp}{implementation}). Note
185 that currently there is no way of adding a custom property (e.g.,
186 a page title) to the pages without using a predefined property as
187 placeholder.
188
189 The \c MultiPageWidgetPlugin class inherits from both QObject and
190 QDesignerCustomWidgetInterface. It is important to remember, when
191 using multiple inheritance, to ensure that all the interfaces
192 (i.e. the classes that doesn't inherit Q_OBJECT) are made known to
193 the meta object system using the Q_INTERFACES() macro. This
194 enables \QD to use \l qobject_cast() to query for supported
195 interfaces using nothing but a QObject pointer.
196
197 \section1 MultiPageWidgetPlugin Class Implementation
198
199 The MultiPageWidgetPlugin class implementation is in most parts
200 equivalent to the \l {designer/customwidgetplugin}{Custom Widget
201 Plugin} example's plugin class:
202
203 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 0
204 \codeline
205 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 3
206
207 One of the functions that differ is the isContainer() function
208 which returns true in this example since our custom widget is
209 intended to be used as a container.
210
211 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 1
212
213 Another function that differ is the function creating our custom widget:
214
215 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 2
216
217 In addition to create and return the widget, we connect our custom
218 container widget's currentIndexChanged() signal to the plugin's
219 currentIndexChanged() slot to ensure that \QD's property editor is
220 updated whenever the user views another page. We also connect the
221 widget's pageTitleChanged() signal to the plugin's
222 pageTitleChanged() slot.
223
224 The currentIndexChanged() slot is called whenever our custom
225 widget's currentIndexChanged() \e signal is emitted, i.e. whenever
226 the user views another page:
227
228 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 8
229
230 First, we retrieve the object emitting the signal using the
231 QObject::sender() and qobject_cast() functions. If it's called in
232 a slot activated by a signal, QObject::sender() returns a pointer
233 to the object that sent the signal; otherwise it returns 0.
234
235 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 9
236
237 Once we have the widget we can update the property editor. \QD
238 uses the QDesignerPropertySheetExtension class to feed its
239 property editor, and whenever a widget is selected in its
240 workspace, Qt Designer will query for the widget's property sheet
241 extension and update the property editor.
242
243 So what we want to achieve is to notify \QD that our widget's \e
244 internal selection has changed: First we use the static
245 QDesignerFormWindowInterface::findFormWindow() function to
246 retrieve the QDesignerFormWindowInterface object containing the
247 widget. The QDesignerFormWindowInterface class allows you to query
248 and manipulate form windows appearing in Qt Designer's
249 workspace. Then, all we have to do is to emit its \l
250 {QDesignerFormWindowInterface::emitSelectionChanged()}{emitSelectionChanged()}
251 signal, forcing an update of the property editor.
252
253 When changing a page title a generic refresh of the property
254 editor is not enough because it is actually the page's property
255 extension that needs to be updated. For that reason we need to
256 access the QDesignerPropertySheetExtension object for the page
257 which title we want to change. The QDesignerPropertySheetExtension
258 class also allows you to manipulate a widget's properties, but to
259 get hold of the extension we must first retrieve access to \QD's
260 extension manager:
261
262 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 10
263 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 11
264
265 Again we first retrieve the widget emitting the signal, using the
266 QObject::sender() and qobject_cast() functions. Then we retrieve
267 the current page from the widget that emitted the signal, and we
268 use the static QDesignerFormWindowInterface::findFormWindow()
269 function to retrieve the form containing our widget.
270
271 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 12
272
273 Now that we have the form window, the QDesignerFormWindowInterface
274 class provides the \l
275 {QDesignerFormWindowInterface::core()}{core()} function which
276 returns the current QDesignerFormEditorInterface object. The
277 QDesignerFormEditorInterface class allows you to access Qt
278 Designer's various components. In particular, the
279 QDesignerFormEditorInterface::extensionManager() function returns
280 a reference to the current extension manager.
281
282 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 13
283
284 Once we have the extension manager we can update the extension
285 sheet: First we retrieve the property extension for the page which
286 title we want to change, using the qt_extension() function. Then
287 we retrieve the index for the page title using the
288 QDesignerPropertySheetExtension::indexOf() function. As previously
289 mentioned, we have chosen to use the QWidget::windowTitle property
290 to store the page title (for more information see the
291 MultiPageWidget class \l
292 {designer/containerextension/multipagewidget.cpp}{implementation}).
293 Finally, we implicitly force an update of the page's property
294 sheet by calling the
295 QDesignerPropertySheetExtension::setChanged() function.
296
297 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 4
298
299 Note also the initialize() function: The \c initialize() function
300 takes a QDesignerFormEditorInterface object as argument.
301
302 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 5
303
304 When creating extensions associated with custom widget plugins, we
305 need to access \QD's current extension manager which we retrieve
306 from the QDesignerFormEditorInterface parameter.
307
308 In addition to allowing you to manipulate a widget's properties,
309 the QExtensionManager class provides extension management
310 facilities for \QD. Using \QD's current extension manager you can
311 retrieve the extension for a given object. You can also register
312 and unregister an extension for a given object. Remember that an
313 extension is an object which modifies the behavior of \QD.
314
315 When registrering an extension, it is actually the associated
316 extension factory that is registered. In \QD, extension factories
317 are used to look up and create named extensions as they are
318 required. So, in this example, the container extension itself is
319 not created until \QD must know whether the associated widget is a
320 container, or not.
321
322 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 6
323
324 We create a \c MultiPageWidgetExtensionFactory object that we
325 register using \QD's current \l {QExtensionManager}{extension
326 manager} retrieved from the QDesignerFormEditorInterface
327 parameter. The first argument is the newly created factory and the
328 second argument is an extension identifier which is a string. The
329 \c Q_TYPEID() macro simply convert the string into a
330 QLatin1String.
331
332 The \c MultiPageWidgetExtensionFactory class is a subclass of
333 QExtensionFactory. When \QD must know whether a widget is a
334 container, or not, \QD's extension manager will run through all
335 its registered factories invoking the first one which is able to
336 create a container extension for that widget. This factory will in
337 turn create a \c MultiPageWidgetExtension object.
338
339 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 7
340
341 Finally, take a look at the \c domXml() function. This function
342 includes default settings for the widget in the standard XML
343 format used by \QD. In this case, we specify the container's first
344 page; any inital pages of a multi-page widget must be specified
345 within this function.
346
347 \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 14
348
349 Remember to use the Q_EXPORT_PLUGIN2() macro to export the
350 MultiPageWidgetPlugin class for use with Qt's plugin handling
351 classes: This macro ensures that \QD can access and construct the
352 custom widget. Without this macro, there is no way for \QD to use
353 the widget.
354
355 \section1 MultiPageWidgetExtensionFactory Class Definition
356
357 The \c MultiPageWidgetExtensionFactory class inherits QExtensionFactory
358 which provides a standard extension factory for \QD.
359
360 \snippet examples/designer/containerextension/multipagewidgetextensionfactory.h 0
361
362 The subclass's purpose is to reimplement the
363 QExtensionFactory::createExtension() function, making it able to
364 create a \c MultiPageWidget container extension.
365
366
367 \section1 MultiPageWidgetExtensionFactory Class Implementation
368
369 The class constructor simply calls the QExtensionFactory base
370 class constructor:
371
372 \snippet examples/designer/containerextension/multipagewidgetextensionfactory.cpp 0
373
374 As described above, the factory is invoked when \QD must know
375 whether the associated widget is a container, or not.
376
377 \snippet examples/designer/containerextension/multipagewidgetextensionfactory.cpp 1
378
379 \QD's behavior is the same whether the requested extension is
380 associated with a container, a member sheet, a property sheet or a
381 task menu: Its extension manager runs through all its registered
382 extension factories calling \c createExtension() for each until
383 one responds by creating the requested extension.
384
385 So the first thing we do in \c
386 MultiPageWidgetExtensionFactory::createExtension() is to check if
387 the QObject, for which the extension is requested, is in fact a \c
388 MultiPageWidget object. Then we check if the requested extension
389 is a container extension.
390
391 If the object is a MultiPageWidget requesting a container
392 extension, we create and return a \c MultiPageWidgetExtension
393 object. Otherwise, we simply return a null pointer, allowing \QD's
394 extension manager to continue its search through the registered
395 factories.
396
397
398 \section1 MultiPageWidgetContainerExtension Class Definition
399
400 The \c MultiPageWidgetContainerExtension class inherits
401 QDesignerContainerExtension which allows you to add (and delete)
402 pages to a multi-page container plugin in \QD.
403
404 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.h 0
405
406 It is important to recognize that the QDesignerContainerExtension
407 class only is intended to provide \QD access to your custom
408 multi-page widget's functionality; your custom multi-page widget
409 must implement functionality corresponding to the extension's
410 functions.
411
412 Note also that we implement a constructor that takes \e two
413 arguments: the parent widget, and the \c MultiPageWidget object
414 for which the task menu is requested.
415
416 QDesignerContainerExtension provides a couple of menu entries in
417 \QD's task menu by default, enabling the user to add or delete
418 pages to the associated custom multi-page widget in \QD's
419 workspace.
420
421 \section1 MultiPageWidgetContainerExtension Class Implementation
422
423 In the constructor we save the reference to the \c MultiPageWidget
424 object sent as parameter, i.e the widget associated with the
425 extension. We will need this later to access the custom multi-page
426 widget performing the requested actions.
427
428 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 0
429
430 To fully enable \QD to manage and manipulate your custom
431 multi-page widget, you must reimplement all the functions of
432 QDesignerContainerExtension:
433
434 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 1
435 \codeline
436 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 2
437 \codeline
438 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 3
439
440 You must reimplement \l
441 {QDesignerContainerExtension::addWidget()}{addWidget()} adding a
442 given page to the container, \l
443 {QDesignerContainerExtension::count()}{count()} returning the
444 number of pages in the container, and \l
445 {QDesignerContainerExtension::currentIndex()}{currentIndex()}
446 returning the index of the currently selected page.
447
448 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 4
449 \codeline
450 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 5
451 \codeline
452 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 6
453 \codeline
454 \snippet examples/designer/containerextension/multipagewidgetcontainerextension.cpp 7
455
456 You must reimplement \l
457 {QDesignerContainerExtension::insertWidget()}{insertWidget()}
458 adding a given page to the container at a given index, \l
459 {QDesignerContainerExtension::remove()}{remove()} deleting the
460 page at a given index, \l
461 {QDesignerContainerExtension::setCurrentIndex()}{setCurrentIndex()}
462 setting the index of the currently selected page, and finally \l
463 {QDesignerContainerExtension::widget()}{widget()} returning the
464 page at a given index.
465
466 \section1 MultiPageWidget Class Definition
467
468 The MultiPageWidget class is a custom container widget that lets
469 the user manipulate and populate its pages, and navigate among
470 these using a combobox.
471
472 \snippet examples/designer/containerextension/multipagewidget.h 0
473
474 The main detail to observe is that your custom multi-page widget
475 must implement functionality corresponding to the
476 QDesignerContainerExtension's member functions since the
477 QDesignerContainerExtension class only is intended to provide Qt
478 Designer access to your custom multi-page widget's functionality.
479
480 In addition, we declare the \c currentIndex and \c pageTitle
481 properties, and their associated set and get functions. By
482 declaring these attributes as properties, we allow \QD to manage
483 them in the same way it manages the properties the MultiPageWidget
484 widget inherits from QWidget and QObject, for example featuring
485 the property editor.
486
487 Note the \c STORED attribute in the declaration of the \c
488 pageTitle property: The \c STORED attribute indicates persistence,
489 i.e. it declares whether the property's value must be remembered
490 when storing an object's state. As mentioned above, we have chosen
491 to store the page title using the QWidget::windowTitle property to
492 be able to give each page their own title. For that reason the \c
493 pageTitle property is a "fake" property, provided for editing
494 purposes, and doesn't need to be stored.
495
496 We must also implement and emit the currentIndexChanged() and
497 pageTitleChanged() signals to ensure that \QD's property editor is
498 updated whenever the user views another page or changes one of the
499 page titles.
500
501 See the MultiPageWidget class \l
502 {designer/containerextension/multipagewidget.cpp}{implementation}
503 for more details.
504*/
Note: See TracBrowser for help on using the repository browser.