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

QTreeView questions



  • Hello!

    I've got a couple of questions about QTreeView.

    First things first: I'm using PySide6.

    Currently I've got a QTreeView which loads a series of nested items. The first time it loads them, it works almost flawlessly: the thing that's not working is that it shows an empty row at the bottom which, if clicked, crashes the UI without any traceback.

    If I don't touch the last row and try to update the model (by removing all the rows and filling it again with new rows), the application eats all the memory in a couple of seconds (something like... 32GB of RAM) and I'm forced to kill it.

    I'm doing something wrong for sure.

    This is the code I've written for it:

        def load_functions_from_project(self):
            logger = logging.getLogger(__name__)
    
            model = self.functionsTreeView.model()
            if not model:
                model = QStandardItemModel()
                self.functionsTreeView.setModel(model)
    
            self.functionsTreeView.setUpdatesEnabled(False)  # Attempt to optimize
            if model.hasChildren():
                model.removeRows(0, model.rowCount())  # here it eats all the memory and freezes
    
            if not self.project:
                return
    
            functions = self.project.functions  # just a dataclass
            functions.sort(key=lambda fn: f'{fn.module}{fn.name}')
    
            rootNode = model.invisibleRootItem()
            items: Dict[str, TreeItem] = {}
            for fn in functions:
                module_path = fn.module.split('.')  # a.b.c.d
                current_path = ''
                for path in module_path:
                    previous_path = current_path
                    if not previous_path:
                        current_path = path
                    else:
                        current_path = '.'.join([current_path, path])
                    if current_path not in items:
                        node = TreeItem(text=path)  # It's a subclass of QStandardItem which sets enabled, text, drag enabled
                        items[current_path] = node
                        if not previous_path:
                            rootNode.appendRow(node)
                        else:
                            items[previous_path].appendRow(node)
                node = TreeItem(text=fn.name, function=fn)
                items[fn.module].appendRow(node)
    
            model.appendRow(rootNode)
            self.functionsTreeView.setUpdatesEnabled(False)
    
            self.functionsTreeView.collapseAll()
    

    May you please help me?

    Thank you very much :)


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    @jim87 said in QTreeView questions:

    model.removeRows(0, model.rowCount()) # here it eats all the memory and freezes

    Aren't you removing one row too many ?

    [edit: wrong function signature in mind SGaist]



  • @SGaist said in QTreeView questions:

    Aren't you removing one row too many ?

    Why do you say this? [Unless there is something about using a model for a QTreeView requiring one to preserve one item, but I'm not aware of that.]

    [removeRows() takes a count of rows to remove, not an index-of-last-row if that's what you're thinking?]



  • @SGaist I tried replacing the whole model with, say, self.functionsTreeView.setModel(None) - same result of eating memory and freezing



  • @jim87
    It's probably not relevant, but you leave treeview updates disabled. I assume your second

    self.functionsTreeView.setUpdatesEnabled(False)
    

    near the end is supposed to pass True. Correct that and/or comment out these "optimizations" while diagnosing the problem.



  • @JonB thanks to pointing that out. Unfortunately this did nothing about the problem.

    I think we should concentrate on the empty item which shouldn't be there:

    d721a2ca-ab01-4ecc-bc58-eda9159b89ee-immagine.png

    According to the code, there should be at least a Function with an empty 'module' attribute, but there isn't:

    5f7283cb-8aad-407c-83ee-c318553c634f-immagine.png



  • Ok, I've made a PoC for this issue, where both the "extra" tree element appears and when you try to load twice it will eat all the memory, freezing .

    I'm running Python 3.10.1 with PySide6 6.2.2.1 under Linux Fedora 35.

    I can't attach the zip file here, though you can download it from the following link: https://drive.google.com/file/d/1vBZDIAZGhnS_Gi-rFalpxZKgB5zqLh7a/view?usp=sharing

    Thanks :)

    EDIT: I finally caught the error! I was creating the model's root item and I was appending all the items in it, though I was also appending the root item to the model itself (see line 184 of the last example). It was as easy as that.

    Thanks for the support though :)