Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Recursion while using QTreeWidgetItem.__lt__
QtWS25 Last Chance

Recursion while using QTreeWidgetItem.__lt__

Scheduled Pinned Locked Moved Solved Qt for Python
5 Posts 4 Posters 624 Views
  • 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.
  • Bluebird75B Offline
    Bluebird75B Offline
    Bluebird75
    wrote on last edited by
    #1

    Hi,

    I want to provide a custom sort order for QTreeWidgetItems withing the QTreeWidget.

    According to documentation, I can use the lt method: https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QListWidgetItem.html#PySide2.QtWidgets.PySide2.QtWidgets.QListWidgetItem.lt

    However, in practice, this gets a bit more complicated than this:

    Here is my code :

    class RepoBranchInfoTreeItem(QTreeWidgetItem):
    
        def __lt__(self, other: 'QTreeWidgetItem') -> bool:
            col = self.treeWidget().sortColumn()
            if col != 1:
                # regular sorting
                return bool( QTreeWidgetItem.__lt__(self, other) )
    
            colTextSelf = self.text(col)
            colTextOther = other.text(col)
            if len(colTextSelf) and len(colTextOther) and colTextSelf[0].isdigit() and colTextOther[0].isdigit():
                # natural number sorting if we can
                return extractInt(colTextSelf) < extractInt(colTextOther)
    
            # regular sort strategy will compare strings and place all number starting strings before others
            return bool( super().__lt__(other) )
    

    It's pretty simple, the idea is to use a natural sort order on column 1, if column 1 content is only made of digits.

    The issue I have is the following :

    Traceback (most recent call last):
      File "C:\work\Multigit\Dev\src\mg_dialog_git_switch_delete_branch.py", line 111, in __lt__
        def __lt__(self, other: 'QTreeWidgetItem') -> bool:
    RecursionError: maximum recursion depth exceeded while calling a Python object
    

    It seems that eventhough I call super().lt(self, other) or QTreeWidgetitem.lt(self, other), instead of calling the lt of QTreeWidgetItem , I end up calling my own method.

    So, virtual method override seems to be broken, I can no longer call the parent method. Or rather, i call it but it eventually calls my own implementation.

    Does anybody knows a way around this ?

    By the way, it works in PyQt5

    JonBJ 1 Reply Last reply
    0
    • Bluebird75B Bluebird75

      Hi,

      I want to provide a custom sort order for QTreeWidgetItems withing the QTreeWidget.

      According to documentation, I can use the lt method: https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QListWidgetItem.html#PySide2.QtWidgets.PySide2.QtWidgets.QListWidgetItem.lt

      However, in practice, this gets a bit more complicated than this:

      Here is my code :

      class RepoBranchInfoTreeItem(QTreeWidgetItem):
      
          def __lt__(self, other: 'QTreeWidgetItem') -> bool:
              col = self.treeWidget().sortColumn()
              if col != 1:
                  # regular sorting
                  return bool( QTreeWidgetItem.__lt__(self, other) )
      
              colTextSelf = self.text(col)
              colTextOther = other.text(col)
              if len(colTextSelf) and len(colTextOther) and colTextSelf[0].isdigit() and colTextOther[0].isdigit():
                  # natural number sorting if we can
                  return extractInt(colTextSelf) < extractInt(colTextOther)
      
              # regular sort strategy will compare strings and place all number starting strings before others
              return bool( super().__lt__(other) )
      

      It's pretty simple, the idea is to use a natural sort order on column 1, if column 1 content is only made of digits.

      The issue I have is the following :

      Traceback (most recent call last):
        File "C:\work\Multigit\Dev\src\mg_dialog_git_switch_delete_branch.py", line 111, in __lt__
          def __lt__(self, other: 'QTreeWidgetItem') -> bool:
      RecursionError: maximum recursion depth exceeded while calling a Python object
      

      It seems that eventhough I call super().lt(self, other) or QTreeWidgetitem.lt(self, other), instead of calling the lt of QTreeWidgetItem , I end up calling my own method.

      So, virtual method override seems to be broken, I can no longer call the parent method. Or rather, i call it but it eventually calls my own implementation.

      Does anybody knows a way around this ?

      By the way, it works in PyQt5

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Bluebird75
      I would use either one of QTreeWidgetItem.__lt__(self, other) or super().__lt__(other), not both mixed. Maybe to rule out super() just QTreeWidgetItem.__lt__(self, other).

      If what you say is so, surely you can remove most of your code and try one or other of:

          def __lt__(self, other: 'QTreeWidgetItem') -> bool:
              return bool( QTreeWidgetItem.__lt__(self, other) )
              # or next line
              # return bool( super().__lt__(other) )
      

      and reproduce the problem.

      By the way, it works in PyQt5

      If code works in PyQt5 but not in PySide2 you can report it as a bug.

      1 Reply Last reply
      0
      • Bluebird75B Offline
        Bluebird75B Offline
        Bluebird75
        wrote on last edited by
        #3

        I tried to use either super().__lt__ or QTreeWidgetItem.__lt__ with equivalent results. I suppose it is something due to the virtual overloading machineray that always picks up the python method in every case.

        I got around it by simply not relying on the QTreeWidgetItem.__lt__ at all. I just do a regular string comparison and it works fine.

        Final code looks like :

        class RepoBranchInfoTreeItem(QTreeWidgetItem):
            
                def __lt__(self, other: 'QTreeWidgetItem') -> bool:
                    col = self.treeWidget().sortColumn()
                    if col != 1:
                        # regular sorting
                        return istrcmp(self.text(col), other.text(col))
            
                    colTextSelf = self.text(col)
                    colTextOther = other.text(col)
                    if len(colTextSelf) and len(colTextOther) and colTextSelf[0].isdigit() and colTextOther[0].isdigit():
                        # natural number sorting if we can
                        return extractInt(colTextSelf) < extractInt(colTextOther)
            
                    # regular sort strategy will compare strings and place all number starting strings before others
                    return istrcmp(self.text(col), other.text(col))
        
        
        def istrcmp(s1: str, s2: str) -> bool:
            '''Case-insensitive string compare'''
            return s1.lower() < s2.lower()
        
            ```
        1 Reply Last reply
        0
        • C Offline
          C Offline
          ctismer
          wrote on last edited by
          #4

          Weird that this works with PyQt5. So we must try harder :^)

          1 Reply Last reply
          0
          • F Offline
            F Offline
            friedemannkleint
            wrote on last edited by
            #5

            See PYSIDE-1951

            1 Reply Last reply
            1

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved