Does the following compile?:
Qt Code:
Q_PROPERTY(QMap<GtVariant,int> values READ getValues WRITE setValues)To copy to clipboard, switch view to plain text mode
Does the following compile?:
Qt Code:
Q_PROPERTY(QMap<GtVariant,int> values READ getValues WRITE setValues)To copy to clipboard, switch view to plain text mode
==========================signature=============== ==================
S.O.L.I.D principles (use them!):
https://en.wikipedia.org/wiki/SOLID_...iented_design)
Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.
No--per the docs, Q_PROPERTY cannot contain commas (error is "`Q_PROPERTY` does not name a type").
As futher information, the stuff about my QVariant-derived class and such seems irrelevant now, as replacing 'GtVariant' with 'QString' above triggers the same moc errors.
Below is the entire widget header for further reference, which triggers the same moc error output as the original post:
Qt Code:
#ifndef ABSTRACTFILTERWIDGET_H #define ABSTRACTFILTERWIDGET_H #include <QtGui> #include <QMap> { Q_OBJECT public: QMap<QString,int> getValues(); void setValues(QMap<QString,int> values); private: QString facetName; QMap<QString,int> facetValues; }; #endif // ABSTRACTFILTERWIDGET_HTo copy to clipboard, switch view to plain text mode
Oops, sorry.No--per the docs, Q_PROPERTY cannot contain commas (error is "`Q_PROPERTY` does not name a type").
When I read the doc you quoted:
I understand the following:For QMap, QList, and QValueList properties, the property value is a QVariant whose value is the entire list or map.
Qt Code:
To copy to clipboard, switch view to plain text mode
And I guess you go something like:
Qt Code:
QMap<GtVariant,int> values = pObject->getValues().value<QMap<GtVariant,int> >();To copy to clipboard, switch view to plain text mode
When you want to use it.
See docs about QVariant and userTypes.
==========================signature=============== ==================
S.O.L.I.D principles (use them!):
https://en.wikipedia.org/wiki/SOLID_...iented_design)
Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.
Hm, I read the doc. w/r/t storing QMaps, etc. in a QVariant as something it did internally, not something that the user needs to mess with. Especially because of the next sentence:
In any case, the usage of QVariant in the getters/setters mixed with a QMap property type as above isn't right, since declaring a Q_PROPERTY with a QMap type is going to demand getters and setters that use that class (I verified this). Did you mean for the property type to be QVariant too?Therefore, you must use QMap as the property type instead of QMap<QString,QVariant>.
I'll try this, but that seems awfully cumbersome. I wish there were example somewhere, since I'm not the first to have this uncertainty:And I guess you go something like:
Qt Code:
QMap<GtVariant,int> values = pObject->getValues().value<QMap<GtVariant,int> >();To copy to clipboard, switch view to plain text mode
When you want to use it.
See docs about QVariant and userTypes.
http://lists.trolltech.com/qt-intere...ad01529-0.html
Let's start from the beginning maybe... Why do you need the GtVariant class?
I'm happy to go into that, but note above that this issue is independent of using that class(I should change the thread title to "Q_PROPERTY of type QMap").
But if you REALLY want to know: I need a widget that stored pairs of values and counts (at lets me do contains() and count retrieval easily). A QMap or QHash is a pretty standard way of handling that kind of thing.
My values can be numbers or strings, but either way they're handled exactly the same way within the widget class--so it would be good to use a single class that could store data of either type. QVariant is an obvious candidate, but it can't be used as the key type for a QMap (no operator<) or QHash (no global qHash). My solution was subclassing QVariant and implementing one or both of the above functions, which seems preferable to having WidgetForStrings and WidgetForInt with literally the only difference being a property/member variable QMap<QString,int> vs. QMap<int,int>.
But as I said, the original error occurs regardless of what key type I use for QMap, so I'm not sure what I'm doing wrong.
Not really. Using QMap in Q_PROPERTY is easy, just use typedef or subclass to avoid using a comma inside the macro. That's not a problem.
How about just QString? It can store both integers and texts as well. That would leave you with QVariantMap (or even QMap<QString,int>) which is already supported.QVariant is an obvious candidate,
You don't need to subclass QVariant to do that. Just implement the following function, it should work:but it can't be used as the key type for a QMap (no operator<) or QHash (no global qHash). My solution was subclassing QVariant and implementing one or both of the above functions,
Qt Code:
To copy to clipboard, switch view to plain text mode
On the other hand I'm not sure how you would like to use this structure...
Qt Code:
QMap<QVariant, QVariant> map; map[1000] = "x"; map["1000"] = "x"; // which key is "less", the first or the second one?To copy to clipboard, switch view to plain text mode
There are templates, you know...which seems preferable to having WidgetForStrings and WidgetForInt with literally the only difference being a property/member variable QMap<QString,int> vs. QMap<int,int>.
Qt Code:
template <typename T> MyClass { QMap<T, int> map; };To copy to clipboard, switch view to plain text mode
I suppose, though I thought it easier just to remove the property declaration and not introducing basically unnecessary typedef/subclassing.
That's something I did just to get some further testing done, but in the larger scope I could be using Date or DateTime values as well, and at some point it becomes difficult and/or error prone to determine the 'actual' datatype from the string content.How about just QString? It can store both integers and texts as well. That would leave you with QVariantMap (or even QMap<QString,int>) which is already supported.
It might should work... but it didn't for me (same moc errors). As for how it would be used: operator< is arbitrary for variants of different types and of types that don't make sense (i.e., not int/double/String/Date/etc.), and otherwise returns the natural operation.You don't need to subclass QVariant to do that. Just implement the following function, it should work:
Qt Code:
To copy to clipboard, switch view to plain text mode
On the other hand I'm not sure how you would like to use this structure...
Templates are a great idea and would be my preferred solution were it not for the interaction of the Q_OBJECT macro with templates (since my class is QWidget-derived and needs signals/slots, I need Q_OBJECT).There are templates, you know...
Qt Code:
template <typename T> MyClass { QMap<T, int> map; };To copy to clipboard, switch view to plain text mode
http://lists.trolltech.com/qt-intere...ad00693-0.html
http://doc.trolltech.com/qq/qq15-academic.html
There are workarounds, they don't really appeal to me. My solution (which I've verified works) is just to not declare my QMap as a Q_PROPERTY (but keep the same getters/setters), and I can use my GtVariant subclass (and use it with a QHash if I need to later). I lose property introspection and whatnot, but for my specific use case it's not such a big deal.
Thanks for the help everyone.
I guess it all boils down to a question whether you can have more than one data type as a key at once. If not, then QVariant will just be a liability sooner or later.
But you have to return something meaningful in all cases. And if you want to detect variant types, you always have to explicitly go through QVariant constructor, i.e. you can't write:As for how it would be used: operator< is arbitrary for variants of different types and of types that don't make sense (i.e., not int/double/String/Date/etc.), and otherwise returns the natural operation.
You have to write:Qt Code:
To copy to clipboard, switch view to plain text mode
This is easy to overcome actually. First subclass a base class with Q_OBJECT macro and then subclass again with templates (and without Q_OBJECT macro).Templates are a great idea and would be my preferred solution were it not for the interaction of the Q_OBJECT macro with templates (since my class is QWidget-derived and needs signals/slots, I need Q_OBJECT).
Qt Code:
Q_OBJECT }; template <typename T> Y { QMap<T,int> map; };To copy to clipboard, switch view to plain text mode
Of course you can't use Q_PROPERTY in the final subclass.
eclarkso (30th October 2009)
I agree the QVariant-as-key starts to get a little dangerous, but necessary I think for me. In particular, we have both float values and version numbers as values. The string representations can be indistinguishable (e.g., 4.5), so we need to retain type information somehow. This is also important because farther down the chain we make decisions on how to display the values based on their type (e.g., as a list of nominal categories or as a line chart).
I appreciate your points re: template workarounds, but having all these functionally unnecessary subclasses and whatnot to work around offends my sense of neatness :). Basically, it offense my neatness less to remove the Q_PROPERTY declaration and not template-enforce that QMap values will be of the same type per instance.
[And for any future googlers of this thread, I'm still confused as to the proper declaration/usage of Q_PROPERTY with QMap/QHash, sorry.]
Doesn't it offend your sense neatness to use QVariant in the fiirst place? Especially that if you intend to use QVariant as the key, it will lead to spaghetti code when trying to determine the type of the key.
I already told you how to do it.[And for any future googlers of this thread, I'm still confused as to the proper declaration/usage of Q_PROPERTY with QMap/QHash, sorry.]
Qt Code:
typedef QMap<QString, int> StringIntMap; Q_OBJECT Q_PROPERTY(StringIntMap name READ name WRITE setName) //... };To copy to clipboard, switch view to plain text mode
Bookmarks