Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Nicest way to have QListWidgetItem with extra data?
QtWS25 Last Chance

Nicest way to have QListWidgetItem with extra data?

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 5.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JonB
    wrote on 13 Feb 2019, 14:41 last edited by JonB
    #1

    I would like the experts' opinion on how I should implement the following in the "nicest" way....

    I have a list of items to present to the user to choose from. The items just present text to the user, but --- as in many situations --- they also need a value (integer) associated with each item, which I will to retrieve when items are selected. So I start with a list of items (Python, not a QList, nor model rows, so we don't start from anything particular suitable for Qt) with text & value, like:

    "Some Item", 3
    "Different", 4
    ...
    "Another Item", 1
    

    Now, if the list were single-selection, I would be using a QComboBox. That allows for items having a QVariant userData, and nice functions like https://doc.qt.io/qt-5/qcombobox.html#itemData or https://doc.qt.io/qt-5/qcombobox.html#findData. I have used that elsewhere.

    The problem is that the list is multi-selection. That rules out QComboBox, and I do not wish to display with a table-type widget only showing one column, I wish to use a list-type widget. That has led me to QListWidget & QListWidgetItem. I then see about 3 ways I could store my data:

    1. Sub-class QListWidgetItem and store the value in an explicit member variable.

    2. Sub-class QListWidgetItem and store the value via QListWidgetItem::setData() with some role. (I'm not sure I actually need to sub-class here: I think I can just use that for my purpose on a QListWidgetItem...?)

    3. Decide that I'd be better in this case moving to a QListView. Create a model with 2 columns (text & value), and use QListView::setModelColumn() to display the text column.

    Which would you do (and why)? My definition of "nicest" usually means "least lines of code for me to add", but for example if trying to use QListWidget(Item) for this is really pushing a round peg into a square hole I'm willing to move off that.

    J 1 Reply Last reply 13 Feb 2019, 14:46
    0
    • J JonB
      13 Feb 2019, 14:41

      I would like the experts' opinion on how I should implement the following in the "nicest" way....

      I have a list of items to present to the user to choose from. The items just present text to the user, but --- as in many situations --- they also need a value (integer) associated with each item, which I will to retrieve when items are selected. So I start with a list of items (Python, not a QList, nor model rows, so we don't start from anything particular suitable for Qt) with text & value, like:

      "Some Item", 3
      "Different", 4
      ...
      "Another Item", 1
      

      Now, if the list were single-selection, I would be using a QComboBox. That allows for items having a QVariant userData, and nice functions like https://doc.qt.io/qt-5/qcombobox.html#itemData or https://doc.qt.io/qt-5/qcombobox.html#findData. I have used that elsewhere.

      The problem is that the list is multi-selection. That rules out QComboBox, and I do not wish to display with a table-type widget only showing one column, I wish to use a list-type widget. That has led me to QListWidget & QListWidgetItem. I then see about 3 ways I could store my data:

      1. Sub-class QListWidgetItem and store the value in an explicit member variable.

      2. Sub-class QListWidgetItem and store the value via QListWidgetItem::setData() with some role. (I'm not sure I actually need to sub-class here: I think I can just use that for my purpose on a QListWidgetItem...?)

      3. Decide that I'd be better in this case moving to a QListView. Create a model with 2 columns (text & value), and use QListView::setModelColumn() to display the text column.

      Which would you do (and why)? My definition of "nicest" usually means "least lines of code for me to add", but for example if trying to use QListWidget(Item) for this is really pushing a round peg into a square hole I'm willing to move off that.

      J Offline
      J Offline
      J.Hilk
      Moderators
      wrote on 13 Feb 2019, 14:46 last edited by
      #2

      hi @JonB

      even so I personally don't do it, most of the time, option 3 is the way to go :)

      Not the fastest, least amount if code, but the cleanest and most fool proof one.

      Alternativ, you could use the Text as Key for a QHash, or normal hash, and go that way -> most likely the least amount of work.


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      J 1 Reply Last reply 13 Feb 2019, 14:53
      1
      • J J.Hilk
        13 Feb 2019, 14:46

        hi @JonB

        even so I personally don't do it, most of the time, option 3 is the way to go :)

        Not the fastest, least amount if code, but the cleanest and most fool proof one.

        Alternativ, you could use the Text as Key for a QHash, or normal hash, and go that way -> most likely the least amount of work.

        J Offline
        J Offline
        JonB
        wrote on 13 Feb 2019, 14:53 last edited by
        #3

        @J.Hilk
        Thanks for your prompt :)

        Alternativ, you could use the Text as Key for a QHash, or normal hash, and go that way -> most likely the least amount of work.

        At least theoretically, I can't do that just in case a given text is duplicated with different values. Yes I know that's "dodgy", but it's not "right" to do it by look-up....

        So you'd rather create an explicit model than a special member variable or data role.... I suppose QListWidget actually just creates a model for you and attaches a QListView behind the scenes?

        J 1 Reply Last reply 13 Feb 2019, 15:03
        0
        • J JonB
          13 Feb 2019, 14:53

          @J.Hilk
          Thanks for your prompt :)

          Alternativ, you could use the Text as Key for a QHash, or normal hash, and go that way -> most likely the least amount of work.

          At least theoretically, I can't do that just in case a given text is duplicated with different values. Yes I know that's "dodgy", but it's not "right" to do it by look-up....

          So you'd rather create an explicit model than a special member variable or data role.... I suppose QListWidget actually just creates a model for you and attaches a QListView behind the scenes?

          J Offline
          J Offline
          J.Hilk
          Moderators
          wrote on 13 Feb 2019, 15:03 last edited by
          #4

          @JonB said in Nicest way to have QListWidgetItem with extra data?:

          So you'd rather create an explicit model than a special member variable or data role.... I suppose QListWidget actually just creates a model for you and attaches a QListView behind the scenes?

          I'm unsure, models and Views were always and still are an area I've the least experience in.

          That said, looking into the QListWidgetItem constructor, there's actually an constructor overload that accepts an int as 3rd parameter

          QListWidgetItem::QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type)

          and you can access it via type(), maybe you don't need to do anything extra?


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          J 1 Reply Last reply 13 Feb 2019, 15:08
          0
          • J J.Hilk
            13 Feb 2019, 15:03

            @JonB said in Nicest way to have QListWidgetItem with extra data?:

            So you'd rather create an explicit model than a special member variable or data role.... I suppose QListWidget actually just creates a model for you and attaches a QListView behind the scenes?

            I'm unsure, models and Views were always and still are an area I've the least experience in.

            That said, looking into the QListWidgetItem constructor, there's actually an constructor overload that accepts an int as 3rd parameter

            QListWidgetItem::QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type)

            and you can access it via type(), maybe you don't need to do anything extra?

            J Offline
            J Offline
            JonB
            wrote on 13 Feb 2019, 15:08 last edited by JonB
            #5

            @J.Hilk

            QListWidgetItem::QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type)

            No, I looked at that already, you can't store arbitrary data against each item via the int type = Type. That is used to indicate only the type of the item (custom item types, if you have need for that), it can only store values greater than QListWidgetItem::UserType.

            1 Reply Last reply
            0
            • V Offline
              V Offline
              VRonin
              wrote on 13 Feb 2019, 15:28 last edited by
              #6

              No need to subclass anything or do anything fancy. The functionality is already implemented

              // QListWidgetItem* item
              item->setData(Qt::DisplayRole,QStringLiteral("Some Item"));
              item->setData(Qt::UserRole,3);
              

              now you can use item->data(Qt::UserRole).toInt() to retrieve it.

              As you QComboBox, it uses this method internally

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              J 1 Reply Last reply 13 Feb 2019, 16:41
              5
              • V VRonin
                13 Feb 2019, 15:28

                No need to subclass anything or do anything fancy. The functionality is already implemented

                // QListWidgetItem* item
                item->setData(Qt::DisplayRole,QStringLiteral("Some Item"));
                item->setData(Qt::UserRole,3);
                

                now you can use item->data(Qt::UserRole).toInt() to retrieve it.

                As you QComboBox, it uses this method internally

                J Offline
                J Offline
                JonB
                wrote on 13 Feb 2019, 16:41 last edited by JonB
                #7

                @VRonin
                Yeah, that was indeed one of my proposed methods above, #2. As you say, I came to the conclusion that it didn't require sub-classing. Very interesting to hear that's the approach QComboBox is taking, gives me a warm, wet feeling :)

                Can I just ask you if you have a comment on the alternative approach #1 above, whereby I would sub-class QListWidgetItem to add a value member? Makes it so neat to access from code. It's the way my beloved ASP.NET does its ListItems --- they have text & (optional) value members --- whether these are in a combobox, list or whatever, and kind of feels "clean". What do you think of adding explicit member fields to derived-QListWidgetItems compared to going down the data() route? (BTW, I will probably use whichever solution generically to cover other places I will want this functionality, not just the particular case I have now, if that makes any difference.)

                V 1 Reply Last reply 13 Feb 2019, 16:49
                0
                • J JonB
                  13 Feb 2019, 16:41

                  @VRonin
                  Yeah, that was indeed one of my proposed methods above, #2. As you say, I came to the conclusion that it didn't require sub-classing. Very interesting to hear that's the approach QComboBox is taking, gives me a warm, wet feeling :)

                  Can I just ask you if you have a comment on the alternative approach #1 above, whereby I would sub-class QListWidgetItem to add a value member? Makes it so neat to access from code. It's the way my beloved ASP.NET does its ListItems --- they have text & (optional) value members --- whether these are in a combobox, list or whatever, and kind of feels "clean". What do you think of adding explicit member fields to derived-QListWidgetItems compared to going down the data() route? (BTW, I will probably use whichever solution generically to cover other places I will want this functionality, not just the particular case I have now, if that makes any difference.)

                  V Offline
                  V Offline
                  VRonin
                  wrote on 13 Feb 2019, 16:49 last edited by VRonin
                  #8

                  @JonB said in Nicest way to have QListWidgetItem with extra data?:

                  What do you think of adding explicit member fields

                  🤮

                  How a class stores its data is an implementation detail and should not be exposed to the outside.
                  I'd be 100% on board with subclassing and adding something like

                  public:
                  int type() const { return data(Qt::UserRole).toInt(); }
                  void setType(int val) { setData(Qt::UserRole,val);}
                  

                  But as a C++ programmer everytime I see a:

                  public:
                  int type;
                  

                  I shoot a bunny. So up to you if you want the soul of an innocent rabbit to haunt you forever for your sins

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  J 1 Reply Last reply 13 Feb 2019, 16:56
                  2
                  • V VRonin
                    13 Feb 2019, 16:49

                    @JonB said in Nicest way to have QListWidgetItem with extra data?:

                    What do you think of adding explicit member fields

                    🤮

                    How a class stores its data is an implementation detail and should not be exposed to the outside.
                    I'd be 100% on board with subclassing and adding something like

                    public:
                    int type() const { return data(Qt::UserRole).toInt(); }
                    void setType(int val) { setData(Qt::UserRole,val);}
                    

                    But as a C++ programmer everytime I see a:

                    public:
                    int type;
                    

                    I shoot a bunny. So up to you if you want the soul of an innocent rabbit to haunt you forever for your sins

                    J Offline
                    J Offline
                    JonB
                    wrote on 13 Feb 2019, 16:56 last edited by JonB
                    #9

                    @VRonin
                    Well.... I'm a C/C#/JS/Python/Prolog programmer. C++ gives me headaches :) Of course I can wrap that public variable in a set/getter function (give me C# for this as a property any time...). So we'll be exposing int type() const & void setType(int val) from a sub-class in either approach.

                    Now without that as an issue, I'm still really interested to hear whether you, as the implementer, want to store the value in a member variable or in the data() "table"/"property"/whatever you wish to call it?

                    P.S.
                    Absolutely no bunnies were harmed in composing this email.

                    V 1 Reply Last reply 13 Feb 2019, 17:20
                    0
                    • J JonB
                      13 Feb 2019, 16:56

                      @VRonin
                      Well.... I'm a C/C#/JS/Python/Prolog programmer. C++ gives me headaches :) Of course I can wrap that public variable in a set/getter function (give me C# for this as a property any time...). So we'll be exposing int type() const & void setType(int val) from a sub-class in either approach.

                      Now without that as an issue, I'm still really interested to hear whether you, as the implementer, want to store the value in a member variable or in the data() "table"/"property"/whatever you wish to call it?

                      P.S.
                      Absolutely no bunnies were harmed in composing this email.

                      V Offline
                      V Offline
                      VRonin
                      wrote on 13 Feb 2019, 17:20 last edited by
                      #10

                      @JonB said in Nicest way to have QListWidgetItem with extra data?:

                      whether you, as the implementer, want to store the value in a member variable or in the data()

                      I would use data but only because that way you can pass that value to whatever other tool that uses the QAbstarctItemModel API. But this is really down to the programmer, if you prefer a personalised private integer you are welcome to use it

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      J 1 Reply Last reply 13 Feb 2019, 19:27
                      2
                      • V VRonin
                        13 Feb 2019, 17:20

                        @JonB said in Nicest way to have QListWidgetItem with extra data?:

                        whether you, as the implementer, want to store the value in a member variable or in the data()

                        I would use data but only because that way you can pass that value to whatever other tool that uses the QAbstarctItemModel API. But this is really down to the programmer, if you prefer a personalised private integer you are welcome to use it

                        J Offline
                        J Offline
                        JonB
                        wrote on 13 Feb 2019, 19:27 last edited by
                        #11

                        @VRonin
                        Perfect answer, thank you! Your point about doing it the data() way allowing it to be accessible to others who only know about QAbstractItemModel is an interesting one.

                        1 Reply Last reply
                        0

                        3/11

                        13 Feb 2019, 14:53

                        8 unread
                        • Login

                        • Login or register to search.
                        3 out of 11
                        • First post
                          3/11
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved