12.4.  QVariant Class: Accessing Properties

[ fromfile: reflection.xml id: qvariantaccess ]

To retrieve the value of any property, you call this method:

QVariant QObject::property(QString propertyName);

QVariant is a union [89] wrapper for all the basic types and all permitted Q_PROPERTY types. You can create a QVariant as a wrapper around another typed value. A QVariant remembers its type and has member functions for getting and setting its value.

QVariant has a rich interface for data conversion and validity checking. In particular, there is a toString() function that returns a QString representation for many of its supported types.[90] This class greatly simplifies the property interface.

Example 12.5 shows how you can get and set the same property values via the direct getters and setters, or via the indirect property() and setProperty() methods.

Example 12.5. src/properties/testcustomerprops.cpp

[ . . . . ]

#include "customer-props.h"
void TestCustomerProps::test() {
    Customer cust;
    cust.setObjectName("Customer");                         1
    cust.setName("Falafal Pita");                           2
    cust.setAddress("41 Temple Street; Boston, MA; 02114");
    cust.setPhone("617-555-1212");
    cust.setType("Government");                             3
    QCOMPARE(cust.getType(), Customer::Government);         4
    QString originalid = "834";                             5
    cust.setId(originalid);
    QVariant v = cust.property("id");                       6
    QString str = v.toString();
    QCOMPARE(originalid, str);
    QDate date(2003, 7, 15);
    cust.setProperty("dateEstablished", QVariant(date));    7
    QDate anotherDate = cust.getDateEstablished();          8
    QEXPECT_FAIL("", "These are different dates", Continue);
    QCOMPARE(date, anotherDate);
    cust.setId(QString("anotherId"));
    qDebug() << objToString(&cust);
    cust.setType(Customer::Educational);
    qDebug() << " Educational=" << cust.getType();
    cust.setType("BogusType");
    qDebug() << " Bogus= " << cust.getType();
    return;
}

QTEST_MAIN(TestCustomerProps)

1

QObject function call.

2

Setting some simple properties.

3

Setting enum property as a string.

4

Comparing to enum value.

5

Setting a string property.

6

Getting it back as a QVariant through the QObject base class method.

7

Setting date properties, wrapped in QVariants.

8

The date comes back through the type-specific getter.


Example 12.6 shows a reflective objToString() method that works on any class with Qt properties defined. It works by iterating through the indexed property() values in a way that is comparable to the java.lang.reflect interface. Only the variant types that canConvert(QVariant::String) will be printed.

Example 12.6. src/properties/testcustomerprops.cpp

[ . . . . ]

QString objToString(const QObject* obj) {
    QStringList result;
    const QMetaObject* meta = obj->metaObject();            1
    result += QString("class %1 : public %2 {")
        .arg(meta->className())
        .arg(meta->superClass()->className());
    for (int i=0; i < meta->propertyCount(); ++i) {
        const QMetaProperty qmp = meta->property(i);        2
        QVariant value = obj->property(qmp.name());
        if (value.canConvert(QVariant::String))
            result += QString("  %1 %2 = %3;")
            .arg(qmp.typeName())  
            .arg(qmp.name())
            .arg(value.toString());
    }
    result += "};";
    return result.join("\n");
}

1

Introspect into the object via the QMetaObject.

2

Each property has a QMetaProperty.


To build this program it is necessary for the project file to contain the line

CONFIG += qtestlib

The program outputs an object's state in a C++-style format:

Example 12.7. src/properties/output.txt

********* Start testing of TestCustomerProps *********
Config: Using QTest library 4.6.2, Qt 4.6.2
PASS   : TestCustomerProps::initTestCase()
QDEBUG : TestCustomerProps::test() "class CustProps : public QObject {
  QString objectName = Customer;
  QString id = anotherId;
  QString name = Falafal Pita;
  QString address = 41 Temple Street; Boston, MA; 02114;
  QString phone = 617-555-1212;
  QDate dateEstablished = 2003-07-15;
  CustomerType type = 3;
};"
QDEBUG : TestCustomerProps::test()  Educational= 2
QDEBUG : TestCustomerProps::test()  Bogus=  -1
PASS   : TestCustomerProps::test()
PASS   : TestCustomerProps::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped
********* Finished testing of TestCustomerProps *********



[89] In C and C++, a union is a struct that can declare two or more alternative data members to be allocated at the same address. This means that the union will occupy only enough memory to accommodate the largest of the declared data members. When instantiated, a union can store only a value for one of the declared members.

[90] See QVariant::canConvert() for more details.