No simple QListWidget "items()" member?



  • I am using QListWidget. (My observation might also concern the QListView or QAbstractItemView it's derived from, or possibly other multi-item-widget-types.)

    There are a couple of member methods which return a QList<QListWidgetItem *> --- selectedItems(), findItems(), and a protected items(const QMimeData *data) const --- but no simple, plain items() which just returns a list/collection of all the items.

    I use Python/PyQt, but I think the issue is the same in C++. I find this irritating for iterating:

    for (int row = 0; row < listWidget.count(); row++)
    {
        QListWidgetItem *item = listWidget.itemAt(row);
        ...
    }
    

    when I'd like to use a Python for item in listWidget.items(), and there's no member to pass to other code for just the items (without the widget).

    Given the usually comprehensive set of Qt methods/members, why is this absent, am I the only person who finds this lacking? Or, am I perchance supposed to get all the items some other way...?



  • Not as concise as an items() method but does this work for you:

    for (auto item : listWidget.findItems("*", Qt::MatchWildcard){
           //do something with each item
    }
    


  • @mchinand
    Sorry --- and I don't want to sound rude/ungrateful, I don't mean it like that --- it may work, but doing a "findItems-with-wildcard-match-method" is not what I had in mind/acceptable when what I want is just the list of items it contains. I have no desire to have code which inspects the items. Its lack seems like a surprisingly inconvenient omission to me.



  • That's understandable. You can subclass QListWidget and add your own methods.



  • Why you want a List of that Items? The QListWidget is a List of Items. If you want a second List just copy QListWidget in another QListWidget. Sorry but i dont get it maybe


  • Moderators

    An API that returns all items of a model would be asking for trouble. With QListView and QAbstractItemView this is a very very bad idea. In your particular case it might be fine, but imagine a model connecting to a remote database with millions of items (GBs of transfer). A single call to items() could grind it to a halt or even crash it. Also there are "infinite" models that generate more and more data (see canFetchMore() method). In this case the whole set might not even be known at any given time.
    For QListWidget this would also be a heavy performance hit. Imagine a list of few thousands elements - generating that list (allocating and populating the list) every time someone calls items() would be terrible for performance.
    selectedItems and findItems are fine(ish), because they are designed to return a small subset of the whole thing. Even with them, if you use them naively you can kill performance.



  • @Fuel
    Because items() is a perfectly obvious method to supply with a QListWidget, or indeed any widget which encapsulates a list of items. There is no need for behind-the-scenes code to inspect each item to see if its text matches a wildcard in order to just return the list of items.

    If that is what is on offer, I will accept I don't have an items() method and just iterate via row index as I am already.

    I don't wish to get into a disagreement with anyone about their opinion versus mine, I was just surprised that nobody else wanted this method years ago.



  • @Chris-Kawa said in No simple QListWidget "items()" member?:

    An API that returns all items of a model would be asking for trouble. With QListView and QAbstractItemView this is a very very bad idea. In your particular case it might be fine, but imagine a model connecting to a remote database with millions of items (GBs of transfer). A single call to items() could grind it to a halt or even crash it. Also there are "infinite" models that generate more and more data (see canFetchMore() method). In this case the whole set might not even be known at any given time.
    For QListWidget this would also be a heavy performance hit. Imagine a list of few thousands elements - generating that list (allocating and populating the list) every time someone calls items() would be terrible for performance.
    selectedItems and findItems are fine(ish), because they are designed to return a small subset of the whole thing. Even with them, if you use them naively you can kill performance.

    That makes Sense.



  • @Chris-Kawa
    OK, at least your explanation makes sense to me.

    Yes, because it's a QListWidget --- a list of a few items to pick from --- they are in-memory for me. I had not thought about attaching it to a database.

    I also take your point about selectedItems/findItems being intended "to return a small subset" (though not for findItems("*", Qt::MatchWildcard))!

    I come from a .NET background. I have written a Qt-equivalent CheckBoxList. The .NET CheckBoxList, RadioButtonList and other such controls all have an Items[] member of the items. Of course, there are not intended to be 1,000 items, and the architecture is quite different, in that you populate the list, not have a dynamic hook to an on-going database query.

    I appreciate the explanation, and understand that I am not missing some method I was unaware of now.

    Thank you.


  • Moderators

    Iterating over an entire list is not something you should be doing often (again - performance considerations). Depending on what you're actually doing in that loop you may consider adding a specialized method for that on the model.
    Iterating like you did in the example is the safest (performance wise) API that can be made, because it's your responsibility to judge how much is too much. As for the .NET equivalents... well, that's the contrast with c++. Here you don't pay for what you don't use.

    If you find yourself doing that often you can consider creating a helper class that will give you begin/end iterators so that you can write something like:

    for (QListWidgetItem* item : wrapper(listWidget))
    {
        //do something with item
    }
    


  • @Chris-Kawa said in No simple QListWidget "items()" member?:

    If you find yourself doing that often you can consider creating a helper class that will give you begin/end iterators so that you can write something like:

    for (QListWidgetItem* item : wrapper(listWidget))
    {
        //do something with item
    }
    

    Unfortunately, in addition to being a Qt newcomer, I am having to program in Python, which is equally new to me. So my chances of figuring "begin/end iterators" code in Python are probably limited... :) I wish I could have my C# back ;-)


  • Moderators

    items() is a terrible API, and if you miss it I'd say it's a withdrawal syndrome ;) C# is just giving you (syntactic) sugar and hiding the big performance cost. Yeah, to some ignorance is bliss, but don't you rather be able to decide for yourself what you want to pay? C++ lets you do that, but, as with all decision making, it's a little bit more work. As for Python... well, it's another sugar pill :P



  • @Chris-Kawa

    items() is a terrible API

    No, it isn't. I asked (or was thinking of) in the context of a control like a checkbox list or a radiobutton list. These are obviously intended to have a "limited" number of items, in the same sense as you pointed out for, say, selectedItems(). Like 10, or 20. And the model is pre-populated.

    Now that you have explained how the Qt model-view architecture which QListWidget is using can be tied to a database or dynamic generation of items I ahve said I do see the point of why it is not suitable in that context.

    BTW, I believe I see that the same principle applies to QComboBox --- there is no items() collection/list --- so I also see this is consistent across Qt widgets.


  • Moderators

    items() is a terrible API

    No, it isn't

    Right. In specific cases it might be benign. I should rather have said it would be a terrible API in a generic class, like QListWidget.
    Easy enough to add it in a derived (specialized for your case) class.



  • @Chris-Kawa
    Yes, thanks, I get that now. As I said, until you explained I had not been thinking in terms of the genericicity(?) of the Qt model-view architecture for these widgets. It's a different approach from .NET, for me.

    P.S.
    OOI, I just looked a MFC CComboBox class (https://msdn.microsoft.com/en-us/library/12h9x0ch.aspx) and I see that like Qt it does not have a GetItems() (in fact, it does not even seem to have a GetItem(index) from what I can see, which is bit worrying, at least Qt has itemText(index)!) So I am beginning to see that ASP.NET (it's that, rather than C# itself, which is providing access to the "Items" collection), which I have grown used to, has been allowing me to program more conveniently than I had appreciated, and I love it even more ;-) (But Qt is good too!)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.