12.3. Q_PROPERTY Macro - Describing QObject Properties

[ fromfile: reflection.xml id: qproperty ]

Example 12.3. src/properties/customer-props.h

[ . . . . ]
class Customer : public QObject {
    Q_OBJECT                                                        1

    /* Each property declaration has the following syntax:
            
    Q_PROPERTY( type name READ getFunction [WRITE setFunction]
    [RESET resetFunction] [NOTIFY notifySignal] [DESIGNABLE bool]
    [SCRIPTABLE bool] [STORED bool] )
    */

    Q_PROPERTY( QString id READ getId WRITE setId NOTIFY valueChanged);
    Q_PROPERTY( QString name READ getName WRITE setName 
                NOTIFY valueChanged);
    Q_PROPERTY( QString address READ getAddress WRITE setAddress 
                NOTIFY addressChanged);
    Q_PROPERTY( QString phone READ getPhone WRITE setPhone 
                NOTIFY phoneChanged);
    Q_PROPERTY( QDate dateEstablished READ getDateEstablished );    2
    Q_PROPERTY( CustomerType type READ getType WRITE setType 
                NOTIFY valueChanged);

  public:
    enum CustomerType
    { Corporate, Individual, Educational, Government };             3
    Q_ENUMS( CustomerType ) ;                                       4

    explicit Customer(const QString name = QString(),               5 
        QObject* parent = 0);                                       
                                                                  
    QString getId() const {
        return m_id;
    }
[ . . . . ]
    // Overloaded, so we can set the type 2 different ways:
    void setType(CustomerType newType);
    void setType(QString newType);
signals:
    void addressChanged(QString newAddress);
    void phoneChanged(QString newPhone);
    void typeChanged(CustomerType type);
    void valueChanged(QString propertyName,
        QVariant newValue, QVariant oldValue = QVariant());
private:
    QString m_id, m_name, m_address, m_phone;
    QDate m_date;
    CustomerType m_type;
};
[ . . . . ]

1

Macro required for moc to preprocess class.

2

Read-only property

3

The enum type definition must be in the same class definition as the Q_ENUMS macro.

4

Special macro to generate string-to-enum conversion functions; must be in same class.

5

Declared explicit because we do not want accidental conversions from QString to Customer.


Example 12.4. src/properties/customer-props.cpp

[ . . . . ]
Customer::Customer(const QString name, QObject* parent)
:QObject(parent) {
    setObjectName(name);
}

void Customer::setId(const QString &newId) {
    if (newId != m_id) {  
        QString oldId = m_id;
        m_id = newId;     
        emit valueChanged("id", newId, oldId);
    }
}
[ . . . . ]
void Customer::setType(CustomerType theType) {
    if (m_type != theType) {
        CustomerType oldType = m_type;
        m_type = theType;
        emit valueChanged("type", theType, oldType);
    }
}

/* Method for setting enum values from Strings. */
void Customer::setType(QString newType) {           1

    static const QMetaObject* meta = metaObject();  2
    static int propindex = meta->indexOfProperty("type");
    static const QMetaProperty mp = meta->property(propindex);

    QMetaEnum menum = mp.enumerator();              3
    const char* ntyp = newType.toAscii().data();
    CustomerType theType =
                   static_cast<CustomerType>(menum.keyToValue(ntyp));
    
    if (theType != m_type) {                        4
        CustomerType oldType = m_type;
        m_type = theType;
        emit valueChanged("type", theType, oldType);
    }
}

QString Customer::getTypeString() const {
    return property("type").toString();
}
[ . . . . ]

1

Overloaded version that accepts a string as an argument. Sets value to -1 if unknown.

2

Because they are static locals, the initializations happen only once.

3

This code gets executed each time.

4

Always check if valueChanged signal is needed.




[59] Of course, this depends on how expensive creating the objects are and how often the function is called.