summaryrefslogtreecommitdiffstats
path: root/doc/src/declarative/qmlforcpp.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/declarative/qmlforcpp.qdoc')
-rw-r--r--doc/src/declarative/qmlforcpp.qdoc670
1 files changed, 670 insertions, 0 deletions
diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc
new file mode 100644
index 0000000..5838df7
--- /dev/null
+++ b/doc/src/declarative/qmlforcpp.qdoc
@@ -0,0 +1,670 @@
+/*!
+ \page qmlforcpp.html
+ \target qmlforcpp
+ \title QML for C++ Programmers
+
+ This page describes the QML format and how to use and extend it from C++.
+
+ The QML syntax declaratively describes how to construct an in memory
+ object tree. QML is usually used to describe a visual scene graph
+ but it is not conceptually limited to this: the QML format is an abstract
+ description of \bold any object tree.
+
+ QML also includes property bindings. Bindings are ECMAScript expressions
+ of a properties value. Whenever the value of the expression changes -
+ either for the first time at startup or subsequently thereafter - the
+ property is automatically updated with the new value.
+
+ \section1 Loading and using QML Files
+
+ QmlComponent is used to load a QML file and to create object instances.
+
+ In QML a component is the unit of instantiation, and the most basic unit
+ of scope. A component is like a template for how to construct an object
+ tree. One component can create multiple instances of this tree, but the
+ template remains constant.
+
+ The following code uses the C++ interface to create 100 red rectangles
+ based on a simple declarative component description.
+
+ \code
+ QmlEngine engine;
+ QmlComponent redRectangle(&engine, "Rectangle { color: \"red\"; width: 100; height: 100 }");
+ for (int ii = 0; ii < 100; ++ii) {
+ QObject *rectangle = redRectangle.create();
+ // ... do something with the rectangle ...
+ }
+ \endcode
+
+ Each independent file describes a QML component, but it is also possible to
+ create sub-components within a QML file as will be shown later.
+
+ \section1 QML Format 101
+
+ This is some sample QML code.
+
+ \code
+ Image {
+ id: myRect
+ x: 10
+ y: 10
+ width: 100
+ height: 100
+ source: "background.png"
+
+ Text {
+ height: 50
+ width: 100
+ color: "white"
+ font.fontSize: 16
+ text: "Hello world!"
+ }
+ }
+ \endcode
+
+ The QML snippet shown above instantiates one \c Image instance and one
+ \c Text instance and sets properties on both. \bold Everything in QML
+ ultimately comes down to either instantiating an object instance, or
+ assigning a property a value. QML relies heavily on Qt's meta object system
+ and can only instantiate classes that derive from QObject.
+
+ In the above example, each property is placed on its own line. You can
+ also place multiple properties on one line by separating them with a
+ semi-colon. The code below is equivalent to the example above.
+
+ \code
+ Image {
+ id: myRect
+ x: 10; y: 10; width: 100; height: 100
+ source: "background.png"
+ Text { height: 50; width: 100; color: "white"; font.fontSize: 16; text: "Hello world!" }
+ }
+ \endcode
+
+ QML can set properties that are more complex than just simple types like
+ integers and strings. Properties can be object pointers or Qt interface
+ pointers or even lists of object or Qt interface pointers! QML is typesafe,
+ and will ensure that only the valid types are assigned to properties.
+
+ Assigning an object to a property is as simple as assigning a basic
+ integer. Attempting to assign an object to a property when type coercian
+ fails will produce an error. The following shows an example of valid and of
+ invalid QML and the corresponding C++ classes.
+
+ \table
+ \row \o
+ \code
+ class Image : public QObject
+ {
+ ...
+ Q_PROPERTY(ImageFilter *filter READ filter WRITE setFilter)
+ };
+
+ class ImageFilter : public QObject
+ {
+ ...
+ };
+ \endcode
+ \o \code
+ // OK
+ Image {
+ filter: ImageFilter {}
+ }
+
+ // NOT OK: Image cannot be cast into ImageFilter
+ Image {
+ filter: Image {}
+ }
+ \endcode
+ \endtable
+
+ Classes can also define an optional default property. The default property
+ is used for assignment if no explicit property has been specified.
+ Any object property can be the default, even complex properties like lists
+ of objects. The default property of the \c Rect class is the \c children
+ property, a list of \c Item's. In the following example, as both \c Image
+ and \c Text inherit from \c Item the \c Image and \c Text instances are
+ added to the parent's \c children property.
+
+ \code
+ Rectangle {
+ Image {}
+ Text {}
+ }
+ \endcode
+
+ Properties that return read-only object pointers can be used recursively.
+ This can be used, for example, to group properties together. The
+ \c Text element has a \c font property that returns an object with a number
+ of sub-properties such as \c family, \c bold, \c italic and \c size.
+ QML makes it easy to interact with these grouped properties, as the
+ following shows - everything you would expect to work, just does.
+
+ \table
+ \row \o
+ \code
+ class Text : public ...
+ {
+ ...
+ Q_PROPERTY(Font *font READ font);
+ };
+ class Font : public QObject
+ {
+ ...
+ Q_PROPERTY(QString family READ family WRITE setFamily);
+ Q_PROPERTY(bool bold READ bold WRITE setBold);
+ Q_PROPERTY(bool italic READ italic WRITE setItalic);
+ Q_PROPERTY(int size READ size WRITE setSize);
+ };
+ \endcode
+ \o
+ \code
+ Text {
+ font.family: "helvetica"
+ font.pointSize: 12
+ font {
+ bold: true
+ italic: true
+ }
+ }
+ \endcode
+ \endtable
+
+ \section1 Defining QML Types
+
+ The QML engine has no intrinsic knowledge of any class types. Instead
+ the programmer must define the C++ types, their corresponding QML
+ name, library namespace, and version availability.
+
+ \code
+ #define QML_DECLARE_TYPE(T)
+ #define QML_DEFINE_TYPE(URI,VMAJ,VFROM,VTO,QmlName,T)
+ \endcode
+
+ Adding these macros to your library or executable automatically makes the
+ C++ type \a T available from the declarative markup language under the
+ name \a QmlName. Of course there's nothing stopping you using the same
+ name for both the C++ and the QML name!
+ Any type can be added to the QML engine using these macros. The only
+ requirements are that \a T inherits QObject, is not abstract,
+ and that it has a default constructor.
+
+ \section1 Property Binding
+
+ Assigning constant values and trees to properties will only get you so
+ far. Property binding allows a property's value to be dependant on the
+ value of other properties and data. Whenever these dependencies change,
+ the property's value is automatically updated.
+
+ Property bindings are ECMAScript expressions and can be applied to any
+ object property. C++ classes don't have to do anything special to get
+ binding support other than define appropriate properties. When a non-literal
+ property assignment appears in a QML file, it is automatically treated as a
+ property binding.
+
+ Here's a simple example that stacks a red, blue and green rectangle.
+ Bindings are used to ensure that the height of each is kept equal to it's
+ parent's. Were the root rectangle's height property to change, the child
+ rectangles height would be updated automatically.
+
+ \code
+ Rectangle {
+ color: "red"
+ width: 100
+ Rectangle {
+ color: "blue"
+ width: 50
+ height: parent.height
+ Rectangle {
+ color: "green"
+ width: 25
+ height: parent.height
+ }
+ }
+ }
+ \endcode
+
+ Binding expressions execute in a context. A context behaves as a scope and
+ defines how the expression resolves property and variable names. Although
+ the two expressions in the last example are the same, the value of \c parent
+ resolves differently because each executes in a different context. Although
+ QML generally takes care of everything for the programmer, a thorough
+ understanding of bind contexts is important in some of the more complex QML
+ structures.
+
+ Every expression is executed in a bind context, encapsulated by the
+ QmlContext C++ class. As covered in the class documentation, a
+ bind context contains a map of names to values, and a list of default
+ objects. When resolving a name, the name to value map is searched first.
+ If the name cannot be found, the default object's are iterated in turn and
+ the context attempts to resolve the name as a property of one of the default
+ objects.
+
+ There are generally two contexts involved in the execution of a binding.
+ The first is the "object context" - a bind context associated with the
+ closest instantiated object and containing just one default object, and
+ that's instantiated object itself. The effect of the object
+ context is pretty simple - names in the binding expression resolve to
+ properties on the object first. It is important to note - particularly in
+ the case of grouped properties - the object context is that of the
+ instantiated object, the consequences of which are shown below.
+
+ \code
+ // OK // NOT OK
+ Text { Text {
+ font { font {
+ bold: font.italic bold: italic
+ } }
+ } }
+ \endcode
+
+ The second context is the "component context". Each QML component (and
+ consequently each QML file) is created in its own unique binding context.
+ Like the object context, the component context contains just one default
+ object - but in this case it is the component's root object. An example
+ will illustrate best - the resultant text will read "background.png".
+
+ \code
+ Image {
+ source: "background.png"
+ Text {
+ text: source
+ }
+ }
+ \endcode
+
+ If the name is not found in either of these contexts, the context heirarchy
+ is searched parent-by-parent until the name is either found, or the
+ heirarchy is exhausted.
+
+ The first property binding example shown involved fixing the height of three
+ rectangles. It did this by fixing the height of each rectangle to its
+ parent, rather than fixing them all to a single common point. Here's the
+ example rewritten to do just that.
+
+ \code
+ Rectangle {
+ color: "red"
+ width: 100
+ Rectangle {
+ color: "blue"
+ width: 50
+ height: parent.height
+ Rectangle {
+ color: "green"
+ width: 25
+ height: parent.parent.height
+ }
+ }
+ }
+ \endcode
+
+ Clearly this sort of fragile relationship is undesirable and unmanageable -
+ moving the green rectangle to be a sibling of the blue or introducing a
+ further rectangle between the two would break the example.
+
+ To address this problem, QML includes a way to directly reference any object
+ within a component (or parent component for that matter), called "ids".
+ Developers assign an object an id, and can then reference it directly by
+ name. Developers assign an object an id by setting the special \c id
+ property. Every object automatically has this magical property (if the
+ object also has an actual property called \c id, that gets set too). As
+ an id allows an object to be referenced directly, it must be unique within
+ a component. By convention, id's should start with an uppercase letter.
+
+ \code
+ Rectangle {
+ id: Root
+ color: "red"
+ width: GreenRect.width + 75
+ height: Root.height
+ Rectangle {
+ color: "blue"
+ width: GreenRect.width + 25
+ Rectangle {
+ id: GreenRect
+ color: "green"
+ width: 25
+ height: Root.height
+ }
+ }
+ }
+ \endcode
+
+ To relate id's back to QmlContext, id's exist as properties on the
+ component context.
+
+ Bind expressions can reference any object property. The QML bind engine
+ relies on the presence of the NOTIFY signal in the Q_PROPERTY declaration
+ on a class to alert it that a property's value has changed. If this is
+ omitted, the bind expression can still access the property's value, but
+ the expression will not be updated if the value changes. The following is
+ an example of a QML friendly property declaration.
+
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(int sample READ sample WRITE setSample NOTIFY sampleChanged)
+ public:
+ int sample() const;
+ void setSample(int);
+ signals:
+ void sampleChanged(int);
+ };
+ \endcode
+
+ While generally no changes are needed to a C++ class to use property
+ binding, sometimes more advanced interaction between the binding engine and
+ an object is desirable. To facilitate this, there is a special exception
+ in the bind engine for allowing an object to access the binding directly.
+
+ If a binding is assigned to a property with a type of QmlBindableValue
+ pointer (ie. QmlBindableValue *), each time the binding value changes,
+ a QmlBindableValue instance is assigned to that property. The
+ QmlBindableValue instance allows the object to read the binding and to
+ evaluate the binding's current value.
+
+ \section1 Signal Properties
+
+ In addition to reading and writing regular properties, QML allows you to
+ easily associate ECMAScript with signals. Consider the following example,
+ in which Button is a made-up type with a clicked() signal.
+
+ \code
+ Button {
+ text: "Hello world!"
+ onClicked: print(text)
+ }
+ \endcode
+
+ Clicking on the button causes "Hello world!" to be printed to the console
+ (or lost forever if you're running Windows).
+
+ Like properties, signals automatically become available in QML without
+ any additional work. As illustrated signals are mapped into QML as special
+ "signal properties", using the name "on<Signal Name>" where the first
+ character of the signal's name is uppercased. If more than one signal of
+ the same name is exist on a class, only the first is available (see the
+ \l Connection element for more general signal connections).
+
+ An important observation to make here is the lack of braces. While both
+ property bindings and signal properties involve executing ECMAScript code,
+ property bindings dynamically update the property value (hence the braces),
+ whereas with signal properties the constant script "value" is actually
+ assigned to the signal property. Trying to bind a value to a signal
+ property will not work!
+
+ Signal parameters are also available to the executing script, as shown
+ below, as long as you remember to name the parameters of your signal
+ in C++ (see QMetaMethod::parameterNames()).
+
+ \table
+ \row \o
+ \code
+ Example {
+ onDoSomething: for(var ii = 0; ii &lt; count; ++ii)
+ print(message)
+ }
+ \endcode
+ \o
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ signals:
+ void doSomething(int count, const QString &message);
+ };
+ \endcode
+ \endtable
+
+ Just like property bindings, signal scripts are executed in a context. The
+ signal script context is identical in scope to the "object context" under
+ property binding, with the exception that it has the signal parameters
+ bound in.
+
+ In addition to scripts, it is possible to assign objects to signal properties.
+ This automatically connects the signal to the object's default method. A
+ default method is defined just like a default property, though the special
+ "DefaultMethod" class info.
+
+ \code
+ Q_CLASSINFO("DefaultMethod", "myMethod(int)");
+ \endcode
+
+ This is useful in achieving several use cases, like that below which moves
+ the button when it is clicked.
+
+ \code
+ Button {
+ id: MyButton
+ onClicked: NumberAnimation {
+ target: MyButton
+ property: "x"
+ to: 100
+ }
+ }
+ \endcode
+
+ If the class itself actually defines a property called "on<Name>", this will
+ be assigned the string value and the signal handling behaviour will be
+ disabled.
+
+ \section1 Attached Properties
+
+ Attached properties allow unrelated types to annotate another type with some
+ additional properties. Some APIs or operations are inherintly imperative,
+ and attached properties help out when translating these APIs into the
+ declarative QML language.
+
+ Qt's QGridLayout is one such example.
+
+ \code
+ QGridLayout {
+ QLabel {
+ QGridLayout.row: 0
+ QGridLayout.column: 0
+ text: "Name:"
+ }
+ QLineEdit {
+ QGridLayout.row: 0
+ QGridLayout.column: 1
+ }
+
+ QLabel {
+ QGridLayout.row: 1
+ QGridLayout.column: 0
+ text: "Occupation:"
+ }
+ QLineEdit {
+ QGridLayout.row: 1
+ QGridLayout.column: 1
+ }
+ }
+ \endcode
+
+ Attached properties are identified by the use of a type name, in the
+ case shown \c QGridLayout, as a grouped property specifier. To prevent
+ ambiguity with actual class instantiations, attached properties must
+ always be specified to include a period but can otherwise be used just like
+ regular properties.
+
+ C++ types provide attached properties by declaring the public function \c qmlAttachedProperties like this example.
+
+ \table
+ \row \o
+ \code
+ static QObject *Type::qmlAttachedProperties(QObject *);
+ \endcode
+ \o
+ \code
+ class Example : public QObject
+ {
+ Q_OBJECT
+ public:
+ static QObject *qmlAttachedProperties(QObject *);
+ };
+ \endcode
+ \endtable
+
+ When an attached property is accessed, the QML engine will call this method
+ to create an attachment object, passing in the object instance that the
+ attached property applies to. The attachment object should define all
+ the attached properties, and is generally parented to the provided object
+ instance to avoid memory leaks. The QML engine does not saves this object,
+ so it is not necessary for the attached property function to ensure that
+ multiple calls for the same instance object return the same attached object.
+
+ While conceptually simple, implementing an attachment object is not quite
+ so easy. The \c qmlAttachedProperties function is static - attachment
+ objects are not associated with any particular instance. How the values
+ of the attached properties apply to the behaviour they are controlling is
+ entirely implementation dependent. An additional consequence of this is
+ that \bold any object can attach \bold any attached property. The following is
+ perfectly valid, although the attached property has no actual effect:
+
+ \code
+ FancyGridLayout {
+ Item {
+ Button {
+ QGridLayout.row: 1
+ }
+ }
+ }
+ \endcode
+
+ The property has no effect because the (made-up) FancyGridLayout type defines the meaning
+ of the \c row attached property only to apply to its direct children. It
+ is possible that other types may have attached properties that affect
+ objects that aren't their direct children.
+
+ Attached properties are an advanced feature that should be used with
+ caution.
+
+ \note We may implement a convenience wrapper that makes using attached
+ properties easier for the common "attach to children" case.
+
+ \section1 Property Value Sources
+
+ Intrinsically, the QML engine can assign a property either a static value,
+ such as a number or an object tree, or a property binding. It is possible for
+ advanced users to extend the engine to assign other "types" of values to
+ properties. These "types" are known as property value sources.
+
+ Consider the following example.
+
+ \code
+ Rectangle {
+ x: NumberAnimation { running: true; repeat; true; from: 0; to: 100; }
+ }
+ \endcode
+
+ Here the \c x property of the rectangle will be animated from 0 to 100.
+ To support this, the NumberAnimation class inherits the
+ QmlPropertyValueSource class. If a type inherits this class and is assigned
+ to a property for which type assignment would otherwise fail (ie. the
+ property itself doesn't have a type of QmlPropertyValueSource *), the QML
+ engine will automatically set the property as the target of the value
+ source.
+
+ \section1 Parser Status
+
+ Generally using QML is a breeze - you implement your classes in C++, add
+ the appropriate properties, signals and slots and off you go. The QML
+ engine takes care of instantiating your classes and setting the properties
+ and everything works fine.
+
+ However, sometimes it is helpful to know a little more about the status of
+ the QML parser. For example, it might be beneficial from a performance
+ standpoint to delay initializing some data structures until all the
+ properties have been set.
+
+ To assist with this, the QML engine defines an interface class called
+ QmlParserStatus. The interface defines a number of virtual methods that are
+ invoked at various stages of the component instantiation. To receive
+ these notifications, all a class has to do is to inherit the interface, and
+ notify the Qt meta system using the Q_INTERFACES() macro. For example,
+
+ \code
+ class Example : public QObject, public QmlParserStatus
+ {
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ public:
+ virtual void componentComplete()
+ {
+ qDebug() << "Woohoo! Now to do my costly initialization";
+ }
+ };
+ \endcode
+
+ \section1 Extended Type Definitions
+
+ QML requires that types have the appropriate properties and signals to
+ work well within the declarative environment. In the case of existing
+ types, it is sometimes necessary to add signals, properties or slots to a
+ target class to make it more QML friendly but the original type cannot be
+ modified. For these cases, the QML engine supports extended type
+ definitions.
+
+ An extended type definition allows the programmer to supply an additional
+ type - known as the extension type - when registering the target class
+ whose properties, signals and slots are transparently merged with the
+ original target class when used from within QML.
+
+ An extension class is a regular QObject, with a constructor that takes a
+ QObject pointer. When needed (extension classes are delay created
+ until the first extension attribute is accessed) the extension
+ class is created and the target object is passed in as the parent. When
+ an extension attribute on the original is accessed, the appropriate signal,
+ property or slots on the extension object is used instead.
+
+ When an extended type is installed, the
+ \code
+ #define QML_DEFINE_EXTENDED_TYPE(T,QmlName,ExtendedTypeName)
+ \endcode
+ macro should be used instead of the regular \c QML_DEFINE_TYPE.
+
+ This example shows the addition of a read-only \c textLength property to
+ QLabel being implemented as an extension.
+
+ \table
+ \row
+ \o
+ \code
+ class QLabelExtension : public QObject
+ {
+ Q_OBJECT
+ Q_PROPERTY(int textLength READ textLength)
+ public:
+ QWidgetExtension(QObject *parent) : QObject(parent) {}
+ int textLength() const {
+ return static_cast<QLabel *>(parent())->text().count();
+ }
+ };
+ QML_DEFINE_EXTENDED_TYPE(QLabel,QLabel,QLabelExtension);
+ \endcode
+ \o
+ \code
+ QLabel {
+ id: Label1
+ text: "Hello World!"
+ }
+ QLabel {
+ text: "Label1 text length: " + Label1.textLength
+ }
+ \endcode
+ \endtable
+
+ Attributes defined through extensions are inherited, just like attributes
+ defined on a normal class. Any types that inherit from \c QLabel, will
+ also have the \c textLength property. Derived types can include additional
+ extensions which are merged together, but only a single extension can be
+ specified for each single C++ class.
+
+ Extended type definitions can even be used to add an attached properties
+ function to a type - just declare the \c qmlAttachedProperties function on
+ the extension object.
+
+*/
+