Results 1 to 12 of 12

Thread: Q_PROPERTY of type QMap

  1. #1
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Q_PROPERTY of type QMap

    I'd like to have a Q_PROPERTY of type QMap<GtVariant,int>, where GtVariant subclasses QVariant and implements operator< and a global qHash function. The docs state:

    For QMap, QList, and QValueList properties, the property value is a QVariant whose value is the entire list or map. Note that the Q_PROPERTY string cannot contain commas, because commas separate macro arguments. Therefore, you must use QMap as the property type instead of QMap<QString,QVariant>
    http://doc.trolltech.com/4.5/properties.html

    I parse that to mean my property declaration should look like:

    Qt Code:
    1. Q_PROPERTY(QMap values READ getValues WRITE setValues)
    2.  
    3. public:
    4. QMap<GtVariant,int> getValues();
    5. void setValues(QMap<GtVariant,int> values);
    To copy to clipboard, switch view to plain text mode 

    Perhaps that's incorrect? Regardless, I'm getting inscrutable-to-me moc errors (see below). If the above is indeed correct, then I suspect my problem relates to the interaction of my QVariant-derived class within a QMap; I can post additional details assuming I get a response to this. Thanks to anyone for your review.

    debug\moc_abstractfilterwidget.cpp: In member function `virtual int AbstractFilterWidget::qt_metacall(QMetaObject::Cal l, int, void**)':
    debug\moc_abstractfilterwidget.cpp:93: error: no match for 'operator=' in '*(QMap<QString, QVariant>*)_v = AbstractFilterWidget::getValues()()'
    c:/Qt/2009.04/qt/include/QtCore/../../src/corelib/tools/qmap.h:396: note: candidates are: QMap<aKey, aT>& QMap<Key, T>::operator=(const QMap<Key, T>&) [with Key = QString, T = QVariant]
    debug\moc_abstractfilterwidget.cpp:100: error: no matching function for call to `AbstractFilterWidget::setValues(QMap<QString, QVariant>&)'
    debug\../abstractfilterwidget.h:26: note: candidates are: void AbstractFilterWidget::setValues(QMap<GtVariant, int>)
    Last edited by eclarkso; 29th October 2009 at 20:14. Reason: Problem seems to be independent of QMap key type

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Does the following compile?:
    Qt Code:
    1. 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.

  3. #3
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by high_flyer View Post
    Does the following compile?:
    Qt Code:
    1. Q_PROPERTY(QMap<GtVariant,int> values READ getValues WRITE setValues)
    To copy to clipboard, switch view to plain text mode 
    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:
    1. #ifndef ABSTRACTFILTERWIDGET_H
    2. #define ABSTRACTFILTERWIDGET_H
    3.  
    4. #include <QtGui>
    5. #include <QMap>
    6.  
    7. class AbstractFilterWidget : public QFrame
    8. {
    9.  
    10. Q_OBJECT
    11.  
    12. public:
    13. Q_PROPERTY(QString name READ getName WRITE setName)
    14. Q_PROPERTY(QMap values READ getValues WRITE setValues)
    15.  
    16. AbstractFilterWidget(QWidget * parent = 0);
    17. AbstractFilterWidget(QString n, QString valQueryString, QWidget * parent = 0);
    18. AbstractFilterWidget(QString n, QMap<QString,int> values, QWidget * parent = 0);
    19.  
    20. QString getName();
    21. void setName(QString name);
    22.  
    23. QMap<QString,int> getValues();
    24. void setValues(QMap<QString,int> values);
    25.  
    26. private:
    27. QString facetName;
    28. QMap<QString,int> facetValues;
    29.  
    30. void initialize(QString n, QMap<QString,int> & vals, QWidget * parent);
    31. };
    32.  
    33. #endif // ABSTRACTFILTERWIDGET_H
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    No--per the docs, Q_PROPERTY cannot contain commas (error is "`Q_PROPERTY` does not name a type").
    Oops, sorry.

    When I read the doc you quoted:
    For QMap, QList, and QValueList properties, the property value is a QVariant whose value is the entire list or map.
    I understand the following:
    Qt Code:
    1. Q_PROPERTY(QMap values READ getValues WRITE setValues)
    2.  
    3. QVariant getValues();
    4. void setValues(QVariant values);
    To copy to clipboard, switch view to plain text mode 

    And I guess you go something like:
    Qt Code:
    1. 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.

  5. #5
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by high_flyer View Post
    Oops, sorry.

    When I read the doc you quoted:

    For QMap, QList, and QValueList properties, the property value is a QVariant whose value is the entire list or map.
    I understand the following:
    Qt Code:
    1. Q_PROPERTY(QMap values READ getValues WRITE setValues)
    2.  
    3. QVariant getValues();
    4. void setValues(QVariant values);
    To copy to clipboard, switch view to plain text mode 
    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:

    Therefore, you must use QMap as the property type instead of QMap<QString,QVariant>.
    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?

    And I guess you go something like:
    Qt Code:
    1. 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.
    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:

    http://lists.trolltech.com/qt-intere...ad01529-0.html

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Let's start from the beginning maybe... Why do you need the GtVariant class?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by wysota View Post
    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.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by eclarkso View Post
    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").
    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.

    QVariant is an obvious candidate,
    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.

    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,
    You don't need to subclass QVariant to do that. Just implement the following function, it should work:
    Qt Code:
    1. bool operator<(const QVariant &v1, const QVariant &v2);
    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:
    1. QMap<QVariant, QVariant> map;
    2. map[1000] = "x";
    3. map["1000"] = "x";
    4. // which key is "less", the first or the second one?
    To copy to clipboard, switch view to plain text mode 

    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>.
    There are templates, you know...

    Qt Code:
    1. template <typename T> MyClass {
    2. QMap<T, int> map;
    3. };
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by wysota View Post
    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.
    I suppose, though I thought it easier just to remove the property declaration and not introducing basically unnecessary typedef/subclassing.

    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.
    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.

    You don't need to subclass QVariant to do that. Just implement the following function, it should work:

    Qt Code:
    1. bool operator<(const QVariant &v1, const QVariant &v2);
    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...
    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.

    There are templates, you know...

    Qt Code:
    1. template <typename T> MyClass {
    2. QMap<T, int> map;
    3. };
    To copy to clipboard, switch view to plain text mode 
    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).

    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.

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Q_PROPERTY of type QMap<[user-type],int>?

    Quote Originally Posted by eclarkso View Post
    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.
    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.

    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.
    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:
    Qt Code:
    1. map["2009-09-01"] = x;
    To copy to clipboard, switch view to plain text mode 
    You have to write:
    Qt Code:
    1. map[QDate::fromString("2009-09-01", Qt::ISODate)] = x;
    To copy to clipboard, switch view to plain text mode 

    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).
    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).

    Qt Code:
    1. class X : public QObject {
    2. Q_OBJECT
    3. };
    4.  
    5. template <typename T> Y {
    6. QMap<T,int> map;
    7. };
    To copy to clipboard, switch view to plain text mode 

    Of course you can't use Q_PROPERTY in the final subclass.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. The following user says thank you to wysota for this useful post:

    eclarkso (30th October 2009)

  12. #11
    Join Date
    Oct 2009
    Location
    Atlanta, GA, USA
    Posts
    8
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Q_PROPERTY of type QMap

    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.]

  13. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Q_PROPERTY of type QMap

    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.

    [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.]
    I already told you how to do it.

    Qt Code:
    1. typedef QMap<QString, int> StringIntMap;
    2. class X : public QObject {
    3. Q_OBJECT
    4. Q_PROPERTY(StringIntMap name READ name WRITE setName)
    5. //...
    6. };
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Convert between a custom data type wrapped in a QVariant
    By darkadept in forum Qt Programming
    Replies: 2
    Last Post: 17th March 2009, 09:07
  2. Compile 4.4.0
    By LordQt in forum Installation and Deployment
    Replies: 18
    Last Post: 29th May 2008, 13:43
  3. Template classes and abstraction of type
    By Raistlin in forum General Programming
    Replies: 15
    Last Post: 1st April 2008, 10:18
  4. dummy question(Error)
    By Masih in forum Qt Programming
    Replies: 12
    Last Post: 19th July 2007, 23:38

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.