Qt Toolkit - Properties

| Classes - Annotated - Tree - Functions - Home - Structure

# Properties

Qt provides a sophisticated property system similar to those shipped 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.

The `Q_PROPERTY` macro in a class declaration declares a property. Properties can only be declared in classes that inherit QObject. A second macro - `Q_OVERRIDE` - can be used to override some aspects of an inherited property in a subclass.

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

- a read method. This always exists.
- a write method. Optional: read-only properties like QWidget::isDesktop() do not have this.
- an attribute "stored" that indicates persistence. Most properties are stored, but a few janus-faced properties like QWidget::minimumWidth() aren't: That property is just way of looking at QWidget::minimumSize(), it has no data of its own.
- a reset method to set a property back to its context specific default value. Very unusual, but e.g. QWidget::font() needs it: The default is to follow its surroundings, and no call to QWidget::setFont() can mean that.
- an attribute "designable" that indicates whether a property is considered to be designable in a GUI Designer. Most are, but e.g. QButton::isDown() can't be designed. The user can press buttons, and the application programmer can make the program press its own buttons, but a GUI design tool can't press buttons.

Properties can be read and written through generic functions in QObject without knowing anything about class in use. These two are equivalent:

        //QButton * b and QObject * o point to the same button
        b->setDown( TRUE );
        o->setProperty( "down", TRUE );

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

As well as QObject::setProperty(), there is a QObject::property(). QMetaObject::propertyNames() returns the names of all available properties. QMetaObject::property() returns the property data for a named property: a QMetaProperty object.

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, const char * name=0 );
            ~MyClass();

            enum Priority { High, Low, VeryHigh, VeryLow };
            void setPriority( 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 have to declare it with the `Q_PROPERTY` macro. The syntax is as follows:

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

For the declaration to be valid, the get function has to be const and to return either the type itself, a pointer to it, or a reference to it. The optional write function has to return void and to 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 everything QVariant provides or an enumeration type declared in the class itself. Since `MyClass` uses the enumeration type `Priority` for the property, this type has to be registered with the property system as well. This way it will be possible to set a value by name, like this:

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

Enumeration types are registered with the `Q_ENUMS` macro. Here's the final class declaration including the property declaration:

        class MyClass : public QObject
        {
            Q_OBJECT
            Q_PROPERTY( Priority priority READ priority WRITE setPriority )
            Q_ENUMS( Priority )
        public:
            MyClass( QObject * parent=0, const char * name=0 );
            ~MyClass();

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

Another similar macro is `Q_SETS.` Like `Q_ENUMS,` it registers an enumeration type but marks it in addition as "set", i.e. the enumeration values can be or'ed together. An I/O class might have enumeration values "Read" and "Write" and accept "Read|Write": Such an enum is best handled with `Q_SETS,` not `Q_ENUMS.`

The remaining keywords in the `Q_PROPERTY` section are `STORED,` `DESIGNABLE` and `RESET.`

`STORED` declares whether the property's value is stored in the object. Stored makes only sense for writable properties. The default value is `true.`

`DESIGNABLE` declares whether this property is suited for modification by a GUI designer program. The default is `true` for writable properties, otherwise `false.`

`RESET` names a function that will set the property to its default state (which may have changed since initialization). The function must return void and take no arguments.