[ fromfile: reflection.xml id: dynamicproperties ]
It is possible to load and store properties in a QObject without having to define them on the class with Q_PROPERTY
.
Up to this point we have been dealing exclusively with properties that are defined with the Q_PROPERTY
macro.
These properties are known to the QMetaObject of that class, and have a QMetaProperty defined.
All objects of the same class share the same metaObject
and thus have the same set of meta properties.
Dynamic properties, on the other hand, are acquired at runtime and are specific to the object that acquired them.
In Example 12.8, we define a class with a single Q_PROPERTY
, which we name someString
.
Example 12.8. src/properties/dynamic/dynoprops.h
[ . . . . ] class DynoProps : public QObject { Q_OBJECT Q_PROPERTY(QString someString READ someString WRITE setSomeString); public: friend QDataStream& operator<<(QDataStream& os, const DynoProps& dp); friend QDataStream& operator>>(QDataStream& is, DynoProps& dp); QString someString() { return m_someString; } void setSomeString(QString ss) { m_someString = ss; } QString propsInventory(); private: QString m_someString; }; [ . . . . ]
In Example 12.9, the implementation of propsInventory()
shows a way to display fixed and dynamic properties.
The list of the fixed properties comes from the QMetaObject.
You can access property values using QMetaProperty::read()
or QObject::property()
.
The dynamic properties are not known by the QMetaObject.
You can iterate through the QList returned by QObject::dynamicPropertyNames()
for the list of names,
and use QObject::property()
to obtain values.
Example 12.9. src/properties/dynamic/dynoprops.cpp
[ . . . . ] QString DynoProps::propsInventory() { static const QMetaObject* meta = metaObject(); QStringList res; res << "Fixed Properties:"; QString propData; for(int i = 0; i < meta->propertyCount(); ++i) { res << QString("%1\t%2").arg(QString(meta->property(i).name())) .arg(meta->property(i).read(this).toString()); } res << "Dynamic Properties:"; foreach(QByteArray dpname, dynamicPropertyNames()) { res << QString("%1\t%2").arg(QString(dpname)) .arg(property(dpname).toString()); } return res.join("\n"); }
Aside from the slight awkwardness of accessing them, dynamic properties can be used in much the same way as fixed properties; for example, they can be serialized.
Example 12.10. src/properties/dynamic/dynoprops.cpp
[ . . . . ] QDataStream& operator<< (QDataStream& os, const DynoProps& dp) { static const QMetaObject* meta = dp.metaObject(); for(int i = 0; i < meta->propertyCount(); ++i) { const char* name = meta->property(i).name(); os << QString::fromLocal8Bit(name) << dp.property(name); } qint32 N(dp.dynamicPropertyNames().count()); os << N; foreach(QByteArray propname, dp.dynamicPropertyNames()) { os << QString::fromLocal8Bit(propname) << dp.property(propname); } return os; } QDataStream& operator>> (QDataStream& is, DynoProps& dp) { static const QMetaObject* meta = dp.metaObject(); QString propname; QVariant propqv; int propcount(meta->propertyCount()); for(int i = 0; i < propcount; ++i) { is >> propname; is >> propqv; dp.setProperty(propname.toLocal8Bit(), propqv); } qint32 dpcount; is >> dpcount; for(int i = 0; i < dpcount; ++i) { is >> propname; is >> propqv; dp.setProperty(propname.toLocal8Bit(), propqv); } return is; }
Example 12.11. src/properties/dynamic/dynoprops-client.cpp
#include <QtCore> #include "dynoprops.h" int main() { QTextStream cout(stdout); DynoProps d1, d2; d1.setObjectName("d1"); d2.setObjectName("d2"); d1.setSomeString("Washington"); d1.setProperty("AcquiredProp", "StringValue"); d2.setProperty("intProp", 42); d2.setProperty("realProp", 3.14159); d2.setProperty("dateProp", QDate(2012, 01, 04)); cout << d1.propsInventory() << endl; cout << d2.propsInventory() << endl; cout << "\nNow we save both objects to a file, close the file,\n" "reopen the file, read the data from the file, and use it\n" "to create new DynoProps objects.\n" << endl; QFile file("file.dat"); file.open(QIODevice::WriteOnly); QDataStream out(&file); out << d1 << d2; file.close(); DynoProps nd1, nd2; file.open(QIODevice::ReadOnly); QDataStream in(&file); in >> nd1 >> nd2; file.close(); cout << "Here are the property inventories for the new objects.\n"; cout << nd1.propsInventory() << endl; cout << nd2.propsInventory() << endl; }
Example 12.12. src/properties/dynamic/output.txt
Fixed Properties: objectName d1 someString Washington Dynamic Properties: AcquiredProp StringValue Fixed Properties: objectName d2 someString Dynamic Properties: intProp 42 realProp 3.14159 dateProp 2012-01-04 Now we save both objects to a file, close the file, reopen the file, read the data from the file, and use it to create new DynoProps objects. Here are the property inventories for the new objects. Fixed Properties: objectName d1 someString Washington Dynamic Properties: AcquiredProp StringValue Fixed Properties: objectName d2 someString Dynamic Properties: intProp 42 realProp 3.14159 dateProp 2012-01-04
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |