Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How can I make my listview that uses custom widgets more efficient?



  • Hi!

    Here is a picture of my QListView:

    My QListView

    Essentially, I have a QSortFilterProxyModel and in the data function I call QListView::setIndexWidget in order to insert my custom widget into the item.

    If you're curious about what this looks like, here is the code inside the data function to set the widget:

      if ( !m_view->indexWidget(index) ) {
        QWidget *widget = new NoteListItemWidget(item->note());
        m_view->setIndexWidget( index, widget );
        item->setWidget(widget);
        if ( m_view->currentIndex() == index )
          item->setSelectedStyle(true);
      }
    

    How it works: I first check if the current QModelIndex has an existing indexWidget. If not, I create a new instance of my custom widget and set it as the index widget. The extra code there tweaks the styling if it is a selected item.

    Question

    So, I am wondering how I could make this more efficient. This will work fine for many users of my app, but for those who have over 1,000 notes it can add some delay when the user clicks the "All Notes" button which would create ~1,000 instances of my custom widget.

    The Qt docs basically state that I should not be using setIndexWidget: "This function should only be used to display static content within the visible area corresponding to an item of data. If you want to display custom dynamic content or implement a custom editor widget, subclass QItemDelegate instead."

    I've looked into QItemDelegate and it seems like it would be pretty complex to re-make my custom widget by painting it all from scratch.

    What do you think I should do? I was also thinking that it might be faster to take my logic code above and offload it to a thread. This would likely solve the lag problem when trying to view 1,000+ notes.

    EDIT: If you'd like to see the source code, all of it is on Gitlab. Here's the QSortFilterProxyModel.


  • Lifetime Qt Champion

    Hi
    You could try
    https://pastebin.com/XrppLZ3m
    It would basically use an image for your custom widget and should speed up creation of many notes.
    Its a compromise between setIndexWidget and a full Delegate. So when not in edit mode, an image is drawn
    which should be faster overall. However, i never got around to speed test it so no promises :)



  • That's neat! I don't think my star button would work then. (It's a QToolButton that toggles).


  • Lifetime Qt Champion

    @DougBeney
    well you would have to adjust the code slightly to allow it to handle that since the image would
    be different.

    However, i do wonder if your custom widget is just some fonts & text and a star
    in that case paint it from a delegate should be not that demanding ?



  • You're right!

    I ended up successfully moving to a delegate!

    success

    Works beautifully. Painting in Qt was way less scary than I thought it would be.

    Before this I actually got my threaded idea working. It got the job done, but was not the best solution. This is so much better.

    Thanks for the help.

    In case anyone runs into this post in the future, here is my custom delegate.

    I also had to create a custom ListView in order to get the correct click behavior I wanted. (When you click the star, it shouldn't select the listview item)


Log in to reply