PDA

View Full Version : Making enums "setProperty" enabled.



hickscorp
27th July 2011, 02:59
Hello,

The code i'm talking about is part of a library. In this context, and in the following lines, the macro RELibOpt will expand to either Q_DECL_EXPORT or Q_DECL_IMPORT depending on what "end" the header is being included.

i have a namespace named RE, containing enums declared like this:
// This trick is to allow the namespace to act as a class for Qt MetaObject stuff.
#ifdef Q_MOC_RUN
class RELibOpt RE {
// To avoid making a heavy Q_OBJECT for the RE namespace.
Q_GADGET
Q_ENUMS (ReadingDirection /* and other enums... */)
public:
#else
namespace RE {
#endif
// This gets declared in the generated moc... Very handy trick BTW.
extern QMetaObject const staticMetaObject;
// Here comes one of my enum declaration...
enum ReadingDirection {
ReadingDirectionUnknown = 0,
ReadingDirectionLeftToRight,
ReadingDirectionRightToLeft,
ReadingDirectionBottomToTop,
ReadingDirectionTopToBottom
};
// See explaination below for that macro, it doesn't changes anything of the problem anyway.
RegisterEnumStreamingOperators (ReadingDirection);
// This is a macro i made to avoid repeating code for each enum i'd like to stream from / to QDataStream.
#define RegisterEnumStreamingOperators(T) \
static QDataStream& operator<< (QDataStream& s, T const& t) { return s << (qint32)t; }; \
static QDataStream& operator>> (QDataStream& s, T &t) { qint32 q; s >> q; t = (T)q; return s; }
};
Q_DECLARE_METATYPE(RE::ReadingDirection);

Later on my program (At exec time), i call:
qRegisterMetaTypeStreamOperators<RE::ReadingDirection>("RE::ReadingDirection");
qRegisterMetaType<RE::ReadingDirection>("RE::ReadingDirection")

Then, i have objects using these enums as properties. For instance:

class RELibOpt AnObject : public QObject {
Q_OBJECT
Q_PROPERTY (RE::ReadingDirection readingDirection READ readingDirection WRITE setReadingDirection)
public:
// Constructor.
Q_INVOKABLE AnObject (QObject *p=0);
// Accessors.
RE::ReadingDirection const& readingDirection () const { return _readingDirection; }
void setReadingDirection (RE::ReadingDirection const &v) { _readingDirection = v; }
};

Using any kind of property setter / getter via QObject::property() / QObject::setProperty() works just fine for everything, but not for my enum types. For instance, doing:
AnObject *obj = new AnObject(this);
obj->setProperty("readingDirection", RE::ReadingDirectionTopToBottom);
// OR, as specified in the docs:
obj->setProperty("readingDirection", "RE::ReadingDirectionTopToBottom");

i have noticed that:
QVariant v = qVariantFromValue(RE::ReadingDirectionBottomToTop) ;
qDebug() << v.isValid() << v.canConvert<RE::ReadingDirection>() << v;Gives output:
true true QVariant(RE::ReadingDirection, )
In other words, the QVariant appears to be valid, but doesn't contain the right value...

Any idea what i'm doing wrong here please?
Thanks for your help,
Pierre.

high_flyer
27th July 2011, 15:46
Bases on this:

If you want to register an enum that is declared in another class, the enum must be fully qualified with the name of the class defining it. In addition, the class defining the enum has to inherit QObject as well as declare the enum using Q_ENUMS().
I'd say you need to add this:


class RELibOpt AnObject : public QObject {
Q_OBJECT
Q_ENUMS(RE::ReadingDirection) //<<----
Q_PROPERTY (RE::ReadingDirection readingDirection READ readingDirection WRITE setReadingDirection)
public:
// Constructor.
Q_INVOKABLE AnObject (QObject *p=0);
// Accessors.
RE::ReadingDirection const& readingDirection () const { return _readingDirection; }
void setReadingDirection (RE::ReadingDirection const &v) { _readingDirection = v; }
};