Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved QTreeView questions

    Qt for Python
    pyside python qt for python
    3
    7
    475
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      jim87 last edited by

      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 :)

      SGaist 1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion @jim87 last edited by 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]

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        JonB J 2 Replies Last reply Reply Quote 0
        • JonB
          JonB @SGaist last edited by JonB

          @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?]

          1 Reply Last reply Reply Quote 0
          • J
            jim87 @SGaist last edited by

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

            JonB 1 Reply Last reply Reply Quote 0
            • JonB
              JonB @jim87 last edited by JonB

              @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.

              J 1 Reply Last reply Reply Quote 0
              • J
                jim87 @JonB last edited by

                @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

                1 Reply Last reply Reply Quote 0
                • J
                  jim87 last edited by jim87

                  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 :)

                  1 Reply Last reply Reply Quote 1
                  • First post
                    Last post