Home · All Classes · Main Classes · Grouped Classes · Modules · Functions

Qt's Property System

Qt provides a sophisticated property system similar to those supplied by some compiler vendors. However, as a compiler- and platform-independent library, Qt cannot rely on non-standard compiler features like __property or [property]. Our solution works with any standard C++ compiler on every platform we support. It's based on the meta-object system that also provides object communication through signals and slots.

Requirements

The Q_PROPERTY() macro in a class declaration declares a property. Properties can only be declared in classes that inherit QObject.

To the outer world, a property appears to be similar to a data member. But properties have several features that distinguish them from ordinary data members:

The read, write and reset functions can be just about any member functions, inherited or not, virtual or not. The only exception is that member functions must be inherited from the first inherited class in the case of multiple inheritance.

Reading and Writing Properties

Properties can be read and written through generic functions in QObject without knowing anything about the class in use. In the code snippet below, the QObject::setProperty() call is equivalent to the QAbstractButton::setDown() call:

    QPushButton *button = new QPushButton;
    QObject *object = button;
    // button and object point to the same object

    button->setDown(true);
    object->setProperty("down", true);

Equivalent, that is, except that the first is faster and provides much better diagnostics at compile time. When practical, the first is better. However, since you can get a list of all available properties for any QObject through its QMetaObject, QObject::setProperty() can give you control over classes that weren't available at compile time.

As well as QObject::setProperty(), there is a corresponding QObject::property() function. QMetaObject::propertyCount() returns the number of all available properties. QMetaObject::property() returns the property data for a given property index: a QMetaProperty object.

A Simple Example

Here's a simple example that shows the most important property functions in use:

    class MyClass : public QObject
    {
        Q_OBJECT

    public:
        MyClass(QObject *parent = 0);
        ~MyClass();

        enum Priority { High, Low, VeryHigh, VeryLow };
        void setPriority(Priority priority);
        Priority priority() const;
    };

The class has a property priority that is not yet known to the meta-object system. In order to make the property known, you must declare it with the Q_PROPERTY() macro. The syntax is as follows:

    Q_PROPERTY(type name
               READ getFunction
               [WRITE setFunction]
               [RESET resetFunction]
               [DESIGNABLE bool]
               [SCRIPTABLE bool]
               [STORED bool])

For the declaration to be valid, the get function must be const and to return either the type itself, a pointer to it, or a reference to it. The optional write function must return void and must take exactly one argument, either the type itself, a pointer or a const reference to it. The meta-object compiler enforces this.

The type of a property can be any QVariant supported type or an enumeration type declared in the class itself. Since MyClass uses the enumeration type Priority for the property, this type must be registered with the property system as well.

There are two exceptions to the above: The type of a property can also be either QList<QVariant> or QMap<QString, QVariant>. In these cases the type must be specified as QList or as QMap, without any template parameters.

It is possible to set a value by name, like this:

    obj->setProperty("priority", "VeryHigh");

In the case of QList and QMap properties, the value passes is a QVariant whose value is the entire list or map.

Header Files

It is usually necessary to include the header files for each value type that you use in property definitions. For example:

    Q_PROPERTY(QDate date READ getDate WRITE setDate)

Since the property is based on the QDate class, the <QDate> header file should be included in the file containing the above property definition.

Using Enums and Flags in Properties

Enumeration types are registered with the Q_ENUMS() macro. Here's the final class declaration including the property related declarations:

    class MyClass : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(Priority priority READ priority WRITE setPriority)
        Q_ENUMS(Priority)

    public:
        MyClass(QObject *parent = 0);
        ~MyClass();

        enum Priority { High, Low, VeryHigh, VeryLow };
        void setPriority(Priority priority);
        Priority priority() const;
    };

Another similar macro is Q_FLAGS(). Like Q_ENUMS(), it registers an enumeration type but marks it in addition as a set of "flags", i.e. the enumeration values can be OR'd together. An I/O class might have enumeration values Read and Write and accept Read | Write: such an enum is best handled with Q_FLAGS(), rather than Q_ENUMS().

The remaining keywords in the Q_PROPERTY() section are RESET, DESIGNABLE, SCRIPTABLE, and STORED.

Adding Additional Information to a Class

Connected to the property system is an additional macro, Q_CLASSINFO(), that can be used to attach additional name--value pairs to a class's meta-object, for example:

    Q_CLASSINFO("Version", "3.0.0")

Like other meta-data, class information is accessible at run-time through the meta-object; see QMetaObject::classInfo() for details.

See also Meta-Object System and Signals and Slots.


Copyright © 2005 Trolltech Trademarks
Qt 4.1.0
Hosted by uCoz