CopperSpice API  1.7.2
Creating Custom Widgets

The Designer application plugin architecture allows user-defined and third party custom widgets to be edited just like you do with standard CopperSpice widgets. All of the custom widget's features are made available to QtDesigner, including widget properties, signals, and slots. Since the Designer application uses real widgets during the form design process, custom widgets will appear the same as they do when previewed.

To integrate a custom widget with QtDesigner a suitable description for the widget and an appropriate project file is required.

Providing an Interface Description

To inform QtDesigner about the type of widget you want to provide, create a subclass of QDesignerCustomWidgetInterface that describes the various properties your widget exposes. Most of these are supplied by functions that are pure virtual in the base class, because only the author of the plugin can provide this information.

FunctionDescription of the return value
name()The name of the class that provides the widget.
group()The group in QtDesigner's widget box that the widget belongs to.
toolTip()A short description to help users identify the widget in QtDesigner.
whatsThis()A longer description of the widget for users of QtDesigner.
includeFile()The header file that must be included in applications that use this widget. This information is stored in UI files and will be used by uic to create a suitable #includes statement in the code it generates for the form containing the custom widget.
icon()An icon that can be used to represent the widget in QtDesigner's widget box.
isContainer()True if the widget will be used to hold child widgets; false otherwise.
createWidget()A QWidget pointer to an instance of the custom widget, constructed with the parent supplied. Note: createWidget() is a factory function responsible for creating the widget only. The custom widget's properties will not be available until load() returns.
domXml()A description of the widget's properties, such as its object name, size hint, and other standard QWidget properties.
codeTemplate()This function is reserved for future use by QtDesigner.

Two other virtual functions can also be reimplemented:

initialize()Sets up extensions and other features for custom widgets. Custom container extensions (see QDesignerContainerExtension) and task menu extensions (see QDesignerTaskMenuExtension) should be set up in this function.
isInitialized()Returns true if the widget has been initialized; returns false otherwise. Reimplementations usually check whether the initialize() function has been called and return the result of this test.

Notes on the domXml() Function

The domXml() function returns a UI file snippet that is used by QtDesigner's widget factory to create a custom widget and its applicable properties.

QtDesigner's widget box allows for a complete UI file to describe one custom widget. The UI file can be loaded using the <ui> tag. Specifying the <ui> tag allows for adding the <customwidget> element that contains additional information for custom widgets. The <widget> tag is sufficient if no additional information is required

If the custom widget does not provide a reasonable size hint, it is necessary to specify a default geometry in the string returned by the domXml() function in your subclass. The following code is an example of how to define a default widgetgeometry:

...
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>100</width>\n"
" <height>100</height>\n"
" </rect>\n"
" </property>\n"
...

An additional feature of the domXml() function is that, if it returns an empty string, the widget will not be installed in QtDesigner's widget box. However, it can still be used by other widgets in the form. This feature is used to hide widgets that should not be explicitly created by the user, but are required by other widgets.

A complete custom widget specification looks like:

<ui language="c++"> displayname="MyWidget">
<widget class="widgets::MyWidget" name="mywidget"/>
<customwidgets>
<customwidget>
<class>widgets::MyWidget</class>
<addpagemethod>addPage</addpagemethod>
<propertyspecifications>
<stringpropertyspecification name="fileName" notr="true" type="singleline"
<stringpropertyspecification name="text" type="richtext"
</propertyspecifications>
</customwidget>
</customwidgets>
</ui>

Attributes of the <ui> tag:

AttributePresenceValuesComment
languageoptional"c++"This attribute specifies the language the custom widget is intended for
displaynameoptionalClass nameThe value of the attribute appears in the Widget box and can be used to strip away namespaces.

The <addpagemethod> tag tells QtDesigner and uic which method should be used to add pages to a container widget. This applies to container widgets that require calling a particular method to add a child rather than adding the child by passing the parent. In particular, this is relevant for containers that are not a subclass of the containers provided in QtDesigner, but are based on the notion of Current Page. In addition, you will need to provide a container extension for them.

The <propertyspecifications> element can contain a list of property meta information. Currently, properties of type string are supported. For these properties, the <stringpropertyspecification> tag can be used. This tag has the following attributes:

AttributePresenceValuesComment
namerequiredName of the property
typerequiredSee below tableThe value of the attribute determines how the property editor will handle them.
notroptional"true", "false"If the attribute is "true", the value is not meant to be translated.

Values of the type attribute of the string property:

ValueType
"richtext"Rich text.
"multiline"Multi-line plain text.
"singleline"Single-line plain text.
"stylesheet"A CSS-style sheet.
"objectname"An object name (restricted set of valid characters).
"url"URL, file name.

Plugin Requirements

In order for plugins to work correctly on all platforms ensure the plugin class implements the properties required by QtDesigner.

Refer to Creating Plugins for more information about creating plugins.

Creating Well Behaved Widgets

Some custom widgets have special user interface features that may make them behave differently to many of the standard widgets found in QtDesigner. Specifically, if a custom widget grabs the keyboard as a result of a call to QWidget::grabKeyboard(), the operation of QtDesigner will be affected.

To give custom widgets special behavior in QtDesigner, provide an implementation of the initialize() function to configure the widget construction process for QtDesigner specific behavior. This function will be called for the first time before any calls to createWidget() and could perhaps set an internal flag that can be tested later when QtDesigner calls the plugin's createWidget() function.

Building and Installing the Plugin

The project files for a plugin must specify the headers and source for both the custom widget and the plugin interface. Typically, this file only has to specify that the plugin's project is to be built as a library, but with specific plugin support for QtDesigner.

If plugins are built in a mode that is incompatible with QtDesigner they will not be loaded and installed. It is also necessary to ensure that the plugin is installed together with other QtDesigner widget plugins.

The $[QT_INSTALL_PLUGINS] variable is a placeholder to the location of the installed CopperSpice plugins. You can configure QtDesigner to look for plugins in other locations by setting the CS_PLUGIN_PATH environment variable before running the application.

QtDesigner will look for a designer subdirectory in each path supplied. Refer to QCoreApplication::libraryPaths() for more information about customizing paths for libraries and plugins with CopperSpice applications.

Splitting up the Plugin

In a real world scenario, you do not want to have dependencies of the application making use of the custom widgets to the QtDesigner headers and libraries as introduced by the simple approach explained above.

There are two different ways to resolve this issue.

  • Create a build file which contains the headers and sources of the custom widget
  • Create a standalone shared library containing the custom widget. This library would then be used by the application in addition to the QtDesigner plugin. Care must be taken to ensure the plugin can locate the library at run time.

Refer to QDesignerCustomWidgetCollectionInterface class to combine several custom widgets into a single library.