1

I've got a Qt related question (for c++) regarding the QTreeWidget and hope someone can help.

I am working with the QTreeWidget and have run into a performance issue that I can't seem to solve. I basically have made a simple extension of it that allows me to easily filter the tree (hide items depending on filters). Running through all top level items and hiding/showing them depending on the filter is very easy, however it slows down whenever the tree is allowed to be sorted (e.g. by calling setSortingEnabled(true) on the QTreeWidget). Does anyone know a way around this or a better way to do this?

The way I filter the the items is as follows:

setUpdatesEnabled(false);

for(int i = 0; i < topLevelItemCount(); ++i)
{
   // Retrieve item 
   const auto pItem = topLevelItem( i );
   
   
   bool hide = false;

   for(filter : mFilters){
        // Stop if a filter already hides the item
        if(hide) break;

        // Check filter
        hide = filter.checkFilter(pItem); 
   }

   pItem->setHidden(false);
}

setUpdatesEnabled(true);

This function itself is very fast, it can run in one or two seconds for a test with 1 million items. However once setSortingEnabled(true) is called to also allow sorting it slows down significantly. I've checked with debugging and it's not the sorting that slows things down, the function above will now take ages to complete. It will now take a few minute at least compared to the mere seconds it took previously (when sorting is not allowed).

To me it appears that if sorting is enabled even once then the call

const auto pItem = topLevelItem( i );

or

pItem->setHidden(hide) 

slows down significantly.

Can anyone shed some light on this issue or suggest a faster/better way to apply filters and/or loop through all top level items in the QTreeWidget?

I've looked online for faster ways to loop through the top level items, but most suggest topLevelItem(int i). I've not seen any thread regarding slowdown after sorting is enabled.

I've tried a few things, namely

  • Using QTreeWidgetIterators rather than topLevelItem(int i)
  • Calling setUpdatesEnabled(false) and setUpdatesEnabled(true) before and after the filter check respectively
  • Calling setSortingEnabled(false) and setSortingEnabled(true) before and after the filter check respectively
  • Retrieving all items in a QList findItems when searching for a wildcard string and looping over the returned QList
  • Looping over the QList<QTreeWidgetItem*> with pointers to items used when the tree was populated via addTopLevelItems(list)

None of these have had any impact on the performance unfortunately. If sorting has ever been enabled, then looping over items slows down significantly.

Fiurilli
  • 11
  • 2
  • Why don't you use QSortFilterProxyModel? – e.n.shirokov Dec 21 '22 at 14:41
  • A colleague of mine originally made this extension to QTreeWidget, which I'm now trying to speed up. I was hoping to speed up looping through all the items when sorting has every been enabled, then the performance is good enough for our purposes. Would you suggest using QSortFilterProxyModel instead of a QTreeWidget? – Fiurilli Dec 21 '22 at 14:44
  • I think you should use QTableView with QStandardItemModel + QSortFilterProxyModel. It will be faster to filtering your data. Read about MVC. https://doc.qt.io/qt-6/model-view-programming.html – e.n.shirokov Dec 21 '22 at 14:53
  • But the problem isn't really that filtering is necessarily slow, it only slows down (significantly) when sorting is enabled (which I think is weird). Is that just to be expected with QTreeWidget and switching to other methods is the only way around this? if so, then I've got some major refactoring to do unfortunately (the question only concerns a minimal working example). – Fiurilli Dec 21 '22 at 14:57
  • setSortingEnabled() should not be active when you do massive changes to a QTree/Table/ListWidget since every time you change something, a re-sorting needs to be done. It may even kill your logic because then item position may change so you're accessing a wrong item (see the [documentation](https://doc.qt.io/qt-6/qtablewidget.html#details)). So disable sorting before changing anything, do your changes and re-enable it afterwards. – chehrlic Dec 21 '22 at 16:09
  • @chehrlic I'm aware of that, however I get the same problem. Once setSortingEnabled(true) has been called sometime in the past the filtering slows down even if I disable it before actually filtering (and enable it again after). – Fiurilli Dec 21 '22 at 16:20
  • 1
    Please provide a minimal, compilable example then. – chehrlic Dec 21 '22 at 18:52

0 Answers0