tags:

views:

327

answers:

2

Hi,

I have registered an enumeration type "ClefType" within my header file - this enum is registered with the MetaObject system using the Q_DECLARE_METATYPE and Q_ENUMS macros. qRegisterMetaType is also called in the class constructor.

This allows me to use this type in a Q_PROPERTY, this all works fine. However, later on, I need to be able to get hold of the Q_PROPERTY of this enum type, given the object - in a form that is suitable for serialization.

Ideally, it would be useful to store the integer value for that enum member, because I don't want this to be specific to the type of enum that is used - eventually I want to have several different enums.

// This is inside a loop over all the properties on a given object
QMetaProperty property = metaObject->property(propertyId);
QString propertyName = propertyMeta.name();
QVariant variantValue = propertyMeta.read(serializeObject);

// If, internally, this QVariant is of type 'ClefType',
// how do I pull out the integer value for this enum?

Unfortunately variantValue.toInt(); does not work - custom enums don't seem to be directly 'castable' to an integer value.

Thanks in advance,

Henry

A: 

Try:

int x = variantValue.value<ClefType>();
chalup
While this will work specifically for ClefType, i'd ideally like this to work for any enumerated type.
Henry Thacker
A: 

You can use the >> and << operators of QVariant to accomplish this.

Saving (where MyClass *x = new MyClass(this); and out is a QDataStream):

const QMetaObject *pObj = x->pObj();
for(int id = pObj->propertyOffset(); id < pObj->propertyCount(); ++id)
{
    QMetaProperty pMeta = pObj->property(id);
    if(pMeta.isReadable() && pMeta.isWritable() && pMeta.isValid())
    {
        QVariant variantValue = pMeta.read(x);
        out << variantValue;
    }
}

Loading:

const QMetaObject *pObj = x->pObj();
for(int id = pObj->propertyOffset(); id < pObj->propertyCount(); ++id)
{
    QMetaProperty pMeta = pObj->property(id);
    if(pMeta.isReadable() && pMeta.isWritable() && pMeta.isValid())
    {
        QVariant variantValue;
        in >> variantValue;
        pMeta.write(x, variantValue);
    }
}

You will need to call

    qRegisterMetaType<CMyClass::ClefType>("ClefType");
    qRegisterMetaTypeStreamOperators<int>("ClefType");

in addition to using Q_OBJECT, Q_ENUMS and Q_PROPERTY. Calling qRegisterMetaTypeStreamOperators<int> tells Qt to use the int versions of operator<< and operator>>.

By the way: using qRegisterMetaType<CMyClass::ClefType>() instead of the form that takes a name doesn't work for me. It might if you used the returned id to lookup the name, but this is much easier.

FYI, here is the MyClass definition:

class CMyClass : public QObject
{
    Q_OBJECT
    Q_ENUMS(ClefType)
    Q_PROPERTY(ClefType cleftype READ getCleftype WRITE setCleftype)
public:
    CMyClass(QObject *parent) : QObject(parent), m_cleftype(One)
    {
        qRegisterMetaType<CMyClass::ClefType>("ClefType");
        qRegisterMetaTypeStreamOperators<int>("ClefType");
    }
    enum ClefType { Zero, One, Two, Three };
    void setCleftype(ClefType t) { m_cleftype = t; }
    ClefType getCleftype() const { return m_cleftype; }
private:
    ClefType m_cleftype;
};

Q_DECLARE_METATYPE(CMyClass::ClefType)
David Walthall
That works great - thanks a lot for your in depth response! Much appreciated
Henry Thacker