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 :)
-
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 :)
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]
-
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?] -
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 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 secondself.functionsTreeView.setUpdatesEnabled(False)
near the end is supposed to pass
True
. Correct that and/or comment out these "optimizations" while diagnosing the problem. -
@jim87
It's probably not relevant, but you leave treeview updates disabled. I assume your secondself.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:
According to the code, there should be at least a Function with an empty 'module' attribute, but there isn't:
-
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 :)