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. Changing Font and background color of individual item in editable Treeview

Changing Font and background color of individual item in editable Treeview

Scheduled Pinned Locked Moved Solved Qt for Python
21 Posts 4 Posters 5.6k Views 3 Watching
  • 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.
  • S Stan Pamela

    Ah. good point. But it still does the same. If I use

        newFont = QFont("Helvetica")
        model.setData(current_index, newFont, role=Qt.FontRole)
    

    It just replaces the content of the item with the text "Helvetica"...

    SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #8

    @Stan-Pamela do you also have a custom data function ?

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

    S 1 Reply Last reply
    1
    • S Stan Pamela

      Ah. good point. But it still does the same. If I use

          newFont = QFont("Helvetica")
          model.setData(current_index, newFont, role=Qt.FontRole)
      

      It just replaces the content of the item with the text "Helvetica"...

      M Offline
      M Offline
      mpergand
      wrote on last edited by mpergand
      #9

      @Stan-Pamela
      You need to return the right data for the roles in data() not setData()

      1 Reply Last reply
      0
      • SGaistS SGaist

        @Stan-Pamela do you also have a custom data function ?

        S Offline
        S Offline
        Stan Pamela
        wrote on last edited by Stan Pamela
        #10

        @SGaist yes, it's

        def data(self, index: QModelIndex, role: int = None):
            if not index.isValid():
                return None
        
            #if role == Qt.FontRole: # sorry please ignore! that was confusing...
            #   return item.data(index.column())
        
            if role != Qt.DisplayRole and role != Qt.EditRole:
                return None
        
            item: TreeItem = self.get_item(index)
        
            return item.data(index.column())
        

        which then goes to treeitem.py -> data

        def data(self, column: int):
            if column < 0 or column >= len(self.item_data):
                return None
            return self.item_data[column]
        

        in other words, it's wrapping a TreeItem to get item_data[column]. What would I need to target to return the font? or the style or background?

        SGaistS 1 Reply Last reply
        0
        • S Stan Pamela

          @SGaist yes, it's

          def data(self, index: QModelIndex, role: int = None):
              if not index.isValid():
                  return None
          
              #if role == Qt.FontRole: # sorry please ignore! that was confusing...
              #   return item.data(index.column())
          
              if role != Qt.DisplayRole and role != Qt.EditRole:
                  return None
          
              item: TreeItem = self.get_item(index)
          
              return item.data(index.column())
          

          which then goes to treeitem.py -> data

          def data(self, column: int):
              if column < 0 or column >= len(self.item_data):
                  return None
              return self.item_data[column]
          

          in other words, it's wrapping a TreeItem to get item_data[column]. What would I need to target to return the font? or the style or background?

          SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #11

          @Stan-Pamela you are not passing the role down to your item data call.

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

          S 1 Reply Last reply
          0
          • SGaistS SGaist

            @Stan-Pamela you are not passing the role down to your item data call.

            S Offline
            S Offline
            Stan Pamela
            wrote on last edited by
            #12

            @SGaist
            :)
            I can only reply every 600sec apparently because I'm a new user. I think you need to give me a "reputation" to be able to interact faster? :)

            Anyway, really sorry about last post, that was confusing, I was trying to edit the data function and copy pasted something that wasn't working...

            Still, these are the two functions that wrap around item_data

            def setData(self, index: QModelIndex, value, role: int) -> bool:
                if (role != Qt.EditRole) and (role != Qt.FontRole):
                    return False
            
                item: TreeItem = self.get_item(index)
                result: bool = item.set_data(index.column(), value)
            
                if result:
                    self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole, Qt.FontRole])
            
                return result
            

            and

            def set_data(self, column: int, value):
                if column < 0 or column >= len(self.item_data):
                    return False
            
                self.item_data[column] = value
                return True
            
            SGaistS 1 Reply Last reply
            0
            • S Stan Pamela

              @SGaist
              :)
              I can only reply every 600sec apparently because I'm a new user. I think you need to give me a "reputation" to be able to interact faster? :)

              Anyway, really sorry about last post, that was confusing, I was trying to edit the data function and copy pasted something that wasn't working...

              Still, these are the two functions that wrap around item_data

              def setData(self, index: QModelIndex, value, role: int) -> bool:
                  if (role != Qt.EditRole) and (role != Qt.FontRole):
                      return False
              
                  item: TreeItem = self.get_item(index)
                  result: bool = item.set_data(index.column(), value)
              
                  if result:
                      self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole, Qt.FontRole])
              
                  return result
              

              and

              def set_data(self, column: int, value):
                  if column < 0 or column >= len(self.item_data):
                      return False
              
                  self.item_data[column] = value
                  return True
              
              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #13

              @Stan-Pamela that's another issue: you don't handle the role in your wrapper just the value.

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

              S 1 Reply Last reply
              1
              • SGaistS SGaist

                @Stan-Pamela that's another issue: you don't handle the role in your wrapper just the value.

                S Offline
                S Offline
                Stan Pamela
                wrote on last edited by
                #14

                @SGaist OK, how do I handle the role?
                Really sorry, I know this is probably so obvious to you all, but I just can't figure it out. It seems this treeview example is a corner case with all the wrappers, isn't it? Or it's just me?

                Still can't write more than every 600sec :( maybe just as well, ahah!

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #15

                  Ok, I see the issue. The example works well for just handling "data".

                  You need to modify your custom TreeItem to handle the role in addition to the value. As a basic version, you can use a dictionary where the key is the role and the item the value. Add a role parameter to the set_data and data methods so that you can properly set and retrieve these values.

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

                  S 1 Reply Last reply
                  0
                  • SGaistS SGaist

                    Ok, I see the issue. The example works well for just handling "data".

                    You need to modify your custom TreeItem to handle the role in addition to the value. As a basic version, you can use a dictionary where the key is the role and the item the value. Add a role parameter to the set_data and data methods so that you can properly set and retrieve these values.

                    S Offline
                    S Offline
                    Stan Pamela
                    wrote on last edited by
                    #16

                    @SGaist

                    Thanks again. I'm still not sure how to do that...
                    Even for the "value" itself, could you explain how/where the final target TreeItem->item_data is set? This doesn't seem to be a standard Qt class/variable... I'm confused...

                    At the very end of treeitem.py, in this editable tree example, there is this recursive function:

                    def set_data(self, column: int, value):
                        if column < 0 or column >= len(self.item_data):
                            return False
                    
                        self.item_data[column] = value
                        return True
                    
                    def __repr__(self) -> str:
                        result = f"<treeitem.TreeItem at 0x{id(self):x}"
                        for d in self.item_data:
                            result += f' "{d}"' if d else " <None>"
                        result += f", {len(self.child_items)} children>"
                        return result
                    

                    Is it this repr function that's used internally, in the backend of the Qt library, to display the text manually? Do I need to use a similar backend function for the role?

                    SGaistS 1 Reply Last reply
                    0
                    • S Stan Pamela

                      @SGaist

                      Thanks again. I'm still not sure how to do that...
                      Even for the "value" itself, could you explain how/where the final target TreeItem->item_data is set? This doesn't seem to be a standard Qt class/variable... I'm confused...

                      At the very end of treeitem.py, in this editable tree example, there is this recursive function:

                      def set_data(self, column: int, value):
                          if column < 0 or column >= len(self.item_data):
                              return False
                      
                          self.item_data[column] = value
                          return True
                      
                      def __repr__(self) -> str:
                          result = f"<treeitem.TreeItem at 0x{id(self):x}"
                          for d in self.item_data:
                              result += f' "{d}"' if d else " <None>"
                          result += f", {len(self.child_items)} children>"
                          return result
                      

                      Is it this repr function that's used internally, in the backend of the Qt library, to display the text manually? Do I need to use a similar backend function for the role?

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #17

                      Basically:

                           def set_data(self, column: int, value, role):
                               if column < 0 or column >= len(self.item_data):
                                   return False
                       
                               if column not in self.item_data.keys():
                                   self.item_data[column] = {}
                               self.item_data[column][role] = value
                               return True
                      

                      Don't forget to handle the EditRole and Display role properly.

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

                      S 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        Basically:

                             def set_data(self, column: int, value, role):
                                 if column < 0 or column >= len(self.item_data):
                                     return False
                         
                                 if column not in self.item_data.keys():
                                     self.item_data[column] = {}
                                 self.item_data[column][role] = value
                                 return True
                        

                        Don't forget to handle the EditRole and Display role properly.

                        S Offline
                        S Offline
                        Stan Pamela
                        wrote on last edited by
                        #18

                        That doesn't work either. Or I'm not doing it properly(?)
                        Even ignoring the font role, and just trying to do the simplest thing possible: to use a dict like this for the text edit alone, and replace the original functionality, it doesn't work:

                        def set_data(self, column: int, value):
                            if column < 0 or column >= len(self.item_data):
                                return False
                        
                            #self.item_data[column] = value
                            self.item_data[column] = {Qt.EditRole: value}
                        
                        SGaistS 1 Reply Last reply
                        0
                        • S Stan Pamela

                          That doesn't work either. Or I'm not doing it properly(?)
                          Even ignoring the font role, and just trying to do the simplest thing possible: to use a dict like this for the text edit alone, and replace the original functionality, it doesn't work:

                          def set_data(self, column: int, value):
                              if column < 0 or column >= len(self.item_data):
                                  return False
                          
                              #self.item_data[column] = value
                              self.item_data[column] = {Qt.EditRole: value}
                          
                          SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #19

                          @Stan-Pamela did you adapt the data function in a similar fashion ?

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

                          S 1 Reply Last reply
                          0
                          • SGaistS SGaist

                            @Stan-Pamela did you adapt the data function in a similar fashion ?

                            S Offline
                            S Offline
                            Stan Pamela
                            wrote on last edited by
                            #20

                            @SGaist, got it!
                            Thanks so much and sorry it took me so long to understand the trail of wrappers and how that feeds back into the main model. Awesome. I did it in a dirty way for now, but shall I clean up and post a zip of the code for consistency and closure of this forum thread?

                            Screenshot 2024-01-24 at 22.19.29.png

                            S 1 Reply Last reply
                            0
                            • S Stan Pamela

                              @SGaist, got it!
                              Thanks so much and sorry it took me so long to understand the trail of wrappers and how that feeds back into the main model. Awesome. I did it in a dirty way for now, but shall I clean up and post a zip of the code for consistency and closure of this forum thread?

                              Screenshot 2024-01-24 at 22.19.29.png

                              S Offline
                              S Offline
                              Stan Pamela
                              wrote on last edited by
                              #21

                              Thanks again so much @SGaist , @friedemannkleint and @mpergand for the help and patience. Just for the record, here are the details for a working example, based on the original https://doc.qt.io/qtforpython-6/examples/example_widgets_itemviews_editabletreemodel.html

                              ======================
                              mainwindow.py:

                              # Copyright (C) 2022 The Qt Company Ltd.
                              # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
                              
                              import sys
                              from pathlib import Path
                              
                              from PySide6.QtCore import (QAbstractItemModel, QItemSelectionModel,
                                                          QModelIndex, Qt, Slot)
                              from PySide6.QtWidgets import (QAbstractItemView, QMainWindow, QTreeView,
                                                             QWidget)
                              from PySide6.QtGui import QFont
                              from PySide6.QtTest import QAbstractItemModelTester
                              
                              from treemodel import TreeModel
                              
                              
                              class MainWindow(QMainWindow):
                                  def __init__(self, parent: QWidget = None):
                                      super().__init__(parent)
                                      self.resize(573, 468)
                              
                                      self.view = QTreeView()
                                      self.view.setAlternatingRowColors(True)
                                      self.view.setSelectionBehavior(QAbstractItemView.SelectItems)
                                      self.view.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
                                      self.view.setAnimated(False)
                                      self.view.setAllColumnsShowFocus(True)
                                      self.setCentralWidget(self.view)
                              
                                      menubar = self.menuBar()
                                      file_menu = menubar.addMenu("&File")
                                      self.exit_action = file_menu.addAction("E&xit")
                                      self.exit_action.setShortcut("Ctrl+Q")
                                      self.exit_action.triggered.connect(self.close)
                              
                                      actions_menu = menubar.addMenu("&Actions")
                                      actions_menu.triggered.connect(self.update_actions)
                                      self.insert_row_action = actions_menu.addAction("Insert Row")
                                      self.insert_row_action.setShortcut("Ctrl+I, R")
                                      self.insert_row_action.triggered.connect(self.insert_row)
                                      self.insert_column_action = actions_menu.addAction("Insert Column")
                                      self.insert_column_action.setShortcut("Ctrl+I, C")
                                      self.insert_column_action.triggered.connect(self.insert_column)
                                      actions_menu.addSeparator()
                                      self.remove_row_action = actions_menu.addAction("Remove Row")
                                      self.remove_row_action.setShortcut("Ctrl+R, R")
                                      self.remove_row_action.triggered.connect(self.remove_row)
                                      self.remove_column_action = actions_menu.addAction("Remove Column")
                                      self.remove_column_action.setShortcut("Ctrl+R, C")
                                      self.remove_column_action.triggered.connect(self.remove_column)
                                      actions_menu.addSeparator()
                                      self.insert_child_action = actions_menu.addAction("Insert Child")
                                      self.insert_child_action.setShortcut("Ctrl+N")
                                      self.insert_child_action.triggered.connect(self.insert_child)
                                      help_menu = menubar.addMenu("&Help")
                                      about_qt_action = help_menu.addAction("About Qt", qApp.aboutQt)
                                      about_qt_action.setShortcut("F1")
                              
                                      self.setWindowTitle("Editable Tree Model")
                              
                                      headers = ["Title", "Description"]
                              
                                      file = Path(__file__).parent / "default.txt"
                                      self.model = TreeModel(headers, file.read_text(), self)
                              
                                      if "-t" in sys.argv:
                                          QAbstractItemModelTester(self.model, self)
                                      self.view.setModel(self.model)
                                      self.view.expandAll()
                              
                                      for column in range(self.model.columnCount()):
                                          self.view.resizeColumnToContents(column)
                              
                                      selection_model = self.view.selectionModel()
                                      selection_model.selectionChanged.connect(self.update_actions)
                              
                                      self.update_actions()
                              
                                  @Slot()
                                  def insert_child(self) -> None:
                                      selection_model = self.view.selectionModel()
                                      index: QModelIndex = selection_model.currentIndex()
                                      model: QAbstractItemModel = self.view.model()
                              
                                      if model.columnCount(index) == 0:
                                          if not model.insertColumn(0, index):
                                              return
                              
                                      if not model.insertRow(0, index):
                                          return
                              
                                      for column in range(model.columnCount(index)):
                                          child: QModelIndex = model.index(0, column, index)
                                          model.setData(child, "[No data]", Qt.EditRole)
                                          if not model.headerData(column, Qt.Horizontal):
                                              model.setHeaderData(column, Qt.Horizontal, "[No header]",
                                                                  Qt.EditRole)
                              
                                      selection_model.setCurrentIndex(
                                          model.index(0, 0, index), QItemSelectionModel.ClearAndSelect
                                      )
                                      self.update_actions()
                              
                                  @Slot()
                                  def insert_column(self) -> None:
                                      model: QAbstractItemModel = self.view.model()
                                      column: int = self.view.selectionModel().currentIndex().column()
                              
                                      changed: bool = model.insertColumn(column + 1)
                                      if changed:
                                          model.setHeaderData(column + 1, Qt.Horizontal, "[No header]",
                                                              Qt.EditRole)
                              
                                      self.update_actions()
                              
                                  @Slot()
                                  def insert_row(self) -> None:
                                      index: QModelIndex = self.view.selectionModel().currentIndex()
                                      model: QAbstractItemModel = self.view.model()
                                      parent: QModelIndex = index.parent()
                              
                                      if not model.insertRow(index.row() + 1, parent):
                                          return
                              
                                      self.update_actions()
                              
                                      for column in range(model.columnCount(parent)):
                                          child: QModelIndex = model.index(index.row() + 1, column, parent)
                                          model.setData(child, "[No data]", Qt.EditRole)
                              
                                  @Slot()
                                  def remove_column(self) -> None:
                                      model: QAbstractItemModel = self.view.model()
                                      column: int = self.view.selectionModel().currentIndex().column()
                              
                                      if model.removeColumn(column):
                                          self.update_actions()
                              
                                  @Slot()
                                  def remove_row(self) -> None:
                                      index: QModelIndex = self.view.selectionModel().currentIndex()
                                      model: QAbstractItemModel = self.view.model()
                              
                                      if model.removeRow(index.row(), index.parent()):
                                          self.update_actions()
                              
                                  @Slot()
                                  def update_actions(self) -> None:
                                      selection_model = self.view.selectionModel()
                                      has_selection: bool = not selection_model.selection().isEmpty()
                                      self.remove_row_action.setEnabled(has_selection)
                                      self.remove_column_action.setEnabled(has_selection)
                              
                                      current_index = selection_model.currentIndex()
                                      has_current: bool = current_index.isValid()
                                      self.insert_row_action.setEnabled(has_current)
                                      self.insert_column_action.setEnabled(has_current)
                              
                                      model: QAbstractItemModel = self.view.model()
                                      newFont = QFont("Times New Roman", 20, QFont.Bold)
                                      newFont.setItalic(True)
                                      model.setData(current_index, newFont, role=Qt.FontRole)
                              
                                      if has_current:
                                          self.view.closePersistentEditor(current_index)
                                          msg = f"Position: ({current_index.row()},{current_index.column()})"
                                          if not current_index.parent().isValid():
                                              msg += " in top level"
                                          self.statusBar().showMessage(msg)
                              

                              ======================
                              treeitem.py:

                              # Copyright (C) 2022 The Qt Company Ltd.
                              # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
                              
                              
                              class TreeItem:
                                  def __init__(self, data: list, parent: 'TreeItem' = None):
                                      self.item_data = data
                                      self.item_font = [None] * len(data)
                                      self.parent_item = parent
                                      self.child_items = []
                              
                                  def child(self, number: int) -> 'TreeItem':
                                      if number < 0 or number >= len(self.child_items):
                                          return None
                                      return self.child_items[number]
                              
                                  def last_child(self):
                                      return self.child_items[-1] if self.child_items else None
                              
                                  def child_count(self) -> int:
                                      return len(self.child_items)
                              
                                  def child_number(self) -> int:
                                      if self.parent_item:
                                          return self.parent_item.child_items.index(self)
                                      return 0
                              
                                  def column_count(self) -> int:
                                      return len(self.item_data)
                              
                                  def font(self, column: int):
                                      if column < 0 or column >= len(self.item_data):
                                          return None
                                      return self.item_font[column]
                              
                                  def data(self, column: int):
                                      if column < 0 or column >= len(self.item_data):
                                          return None
                                      return self.item_data[column]
                              
                                  def insert_children(self, position: int, count: int, columns: int) -> bool:
                                      if position < 0 or position > len(self.child_items):
                                          return False
                              
                                      for row in range(count):
                                          data = [None] * columns
                                          item = TreeItem(data.copy(), self)
                                          self.child_items.insert(position, item)
                              
                                      return True
                              
                                  def insert_columns(self, position: int, columns: int) -> bool:
                                      if position < 0 or position > len(self.item_data):
                                          return False
                              
                                      for column in range(columns):
                                          self.item_data.insert(position, None)
                              
                                      for child in self.child_items:
                                          child.insert_columns(position, columns)
                              
                                      return True
                              
                                  def parent(self):
                                      return self.parent_item
                              
                                  def remove_children(self, position: int, count: int) -> bool:
                                      if position < 0 or position + count > len(self.child_items):
                                          return False
                              
                                      for row in range(count):
                                          self.child_items.pop(position)
                              
                                      return True
                              
                                  def remove_columns(self, position: int, columns: int) -> bool:
                                      if position < 0 or position + columns > len(self.item_data):
                                          return False
                              
                                      for column in range(columns):
                                          self.item_data.pop(position)
                              
                                      for child in self.child_items:
                                          child.remove_columns(position, columns)
                              
                                      return True
                              
                                  def set_font(self, column: int, value):
                                      if column < 0 or column >= len(self.item_data):
                                          return False
                              
                                      self.item_font[column] = value
                                      return True
                              
                                  def set_data(self, column: int, value):
                                      if column < 0 or column >= len(self.item_data):
                                          return False
                              
                                      self.item_data[column] = value
                                      return True
                              
                                  def __repr__(self) -> str:
                                      result = f"<treeitem.TreeItem at 0x{id(self):x}"
                                      for d in self.item_data:
                                          result += f' "{d}"' if d else " <None>"
                                      result += f", {len(self.child_items)} children>"
                                      return result
                              

                              ======================
                              treemodel.py:

                              # Copyright (C) 2022 The Qt Company Ltd.
                              # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
                              
                              
                              from PySide6.QtCore import QModelIndex, Qt, QAbstractItemModel
                              from treeitem import TreeItem
                              
                              
                              class TreeModel(QAbstractItemModel):
                              
                                  def __init__(self, headers: list, data: str, parent=None):
                                      super().__init__(parent)
                              
                                      self.root_data = headers
                                      self.root_item = TreeItem(self.root_data.copy())
                                      self.setup_model_data(data.split("\n"), self.root_item)
                              
                                  def columnCount(self, parent: QModelIndex = None) -> int:
                                      return self.root_item.column_count()
                              
                                  def data(self, index: QModelIndex, role: int = None):
                                      if not index.isValid():
                                          return None
                              
                                      if role != Qt.DisplayRole and role != Qt.EditRole and role != Qt.FontRole:
                                          return None
                              
                                      item: TreeItem = self.get_item(index)
                              
                                      if role == Qt.FontRole:
                                          return item.font(index.column())
                              
                                      return item.data(index.column())
                              
                                  def flags(self, index: QModelIndex) -> Qt.ItemFlags:
                                      if not index.isValid():
                                          return Qt.NoItemFlags
                              
                                      return Qt.ItemIsEditable | QAbstractItemModel.flags(self, index)
                              
                                  def get_item(self, index: QModelIndex = QModelIndex()) -> TreeItem:
                                      if index.isValid():
                                          item: TreeItem = index.internalPointer()
                                          if item:
                                              return item
                              
                                      return self.root_item
                              
                                  def headerData(self, section: int, orientation: Qt.Orientation,
                                                 role: int = Qt.DisplayRole):
                                      if orientation == Qt.Horizontal and role == Qt.DisplayRole:
                                          return self.root_item.data(section)
                              
                                      return None
                              
                                  def index(self, row: int, column: int, parent: QModelIndex = QModelIndex()) -> QModelIndex:
                                      if parent.isValid() and parent.column() != 0:
                                          return QModelIndex()
                              
                                      parent_item: TreeItem = self.get_item(parent)
                                      if not parent_item:
                                          return QModelIndex()
                              
                                      child_item: TreeItem = parent_item.child(row)
                                      if child_item:
                                          return self.createIndex(row, column, child_item)
                                      return QModelIndex()
                              
                                  def insertColumns(self, position: int, columns: int,
                                                    parent: QModelIndex = QModelIndex()) -> bool:
                                      self.beginInsertColumns(parent, position, position + columns - 1)
                                      success: bool = self.root_item.insert_columns(position, columns)
                                      self.endInsertColumns()
                              
                                      return success
                              
                                  def insertRows(self, position: int, rows: int,
                                                 parent: QModelIndex = QModelIndex()) -> bool:
                                      parent_item: TreeItem = self.get_item(parent)
                                      if not parent_item:
                                          return False
                              
                                      self.beginInsertRows(parent, position, position + rows - 1)
                                      column_count = self.root_item.column_count()
                                      success: bool = parent_item.insert_children(position, rows, column_count)
                                      self.endInsertRows()
                              
                                      return success
                              
                                  def parent(self, index: QModelIndex = QModelIndex()) -> QModelIndex:
                                      if not index.isValid():
                                          return QModelIndex()
                              
                                      child_item: TreeItem = self.get_item(index)
                                      if child_item:
                                          parent_item: TreeItem = child_item.parent()
                                      else:
                                          parent_item = None
                              
                                      if parent_item == self.root_item or not parent_item:
                                          return QModelIndex()
                              
                                      return self.createIndex(parent_item.child_number(), 0, parent_item)
                              
                                  def removeColumns(self, position: int, columns: int,
                                                    parent: QModelIndex = QModelIndex()) -> bool:
                                      self.beginRemoveColumns(parent, position, position + columns - 1)
                                      success: bool = self.root_item.remove_columns(position, columns)
                                      self.endRemoveColumns()
                              
                                      if self.root_item.column_count() == 0:
                                          self.removeRows(0, self.rowCount())
                              
                                      return success
                              
                                  def removeRows(self, position: int, rows: int,
                                                 parent: QModelIndex = QModelIndex()) -> bool:
                                      parent_item: TreeItem = self.get_item(parent)
                                      if not parent_item:
                                          return False
                              
                                      self.beginRemoveRows(parent, position, position + rows - 1)
                                      success: bool = parent_item.remove_children(position, rows)
                                      self.endRemoveRows()
                              
                                      return success
                              
                                  def rowCount(self, parent: QModelIndex = QModelIndex()) -> int:
                                      if parent.isValid() and parent.column() > 0:
                                          return 0
                              
                                      parent_item: TreeItem = self.get_item(parent)
                                      if not parent_item:
                                          return 0
                                      return parent_item.child_count()
                              
                                  def setData(self, index: QModelIndex, value, role: int) -> bool:
                                      if (role != Qt.EditRole) and (role != Qt.FontRole):
                                          return False
                              
                                      item: TreeItem = self.get_item(index)
                                      if role == Qt.FontRole:
                                          result: bool = item.set_font(index.column(), value)
                                      else:
                                          result: bool = item.set_data(index.column(), value)
                              
                                      if result:
                                          self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole, Qt.FontRole])
                              
                                      return result
                              
                                  def setHeaderData(self, section: int, orientation: Qt.Orientation, value,
                                                    role: int = None) -> bool:
                                      if role != Qt.EditRole or orientation != Qt.Horizontal:
                                          return False
                              
                                      result: bool = self.root_item.set_data(section, value)
                              
                                      if result:
                                          self.headerDataChanged.emit(orientation, section, section)
                              
                                      return result
                              
                                  def setup_model_data(self, lines: list, parent: TreeItem):
                                      parents = [parent]
                                      indentations = [0]
                              
                                      for line in lines:
                                          line = line.rstrip()
                                          if line and "\t" in line:
                              
                                              position = 0
                                              while position < len(line):
                                                  if line[position] != " ":
                                                      break
                                                  position += 1
                              
                                              column_data = line[position:].split("\t")
                                              column_data = [string for string in column_data if string]
                              
                                              if position > indentations[-1]:
                                                  if parents[-1].child_count() > 0:
                                                      parents.append(parents[-1].last_child())
                                                      indentations.append(position)
                                              else:
                                                  while position < indentations[-1] and parents:
                                                      parents.pop()
                                                      indentations.pop()
                              
                                              parent: TreeItem = parents[-1]
                                              col_count = self.root_item.column_count()
                                              parent.insert_children(parent.child_count(), 1, col_count)
                              
                                              for column in range(len(column_data)):
                                                  child = parent.last_child()
                                                  child.set_data(column, column_data[column])
                              
                                  def _repr_recursion(self, item: TreeItem, indent: int = 0) -> str:
                                      result = " " * indent + repr(item) + "\n"
                                      for child in item.child_items:
                                          result += self._repr_recursion(child, indent + 2)
                                      return result
                              
                                  def __repr__(self) -> str:
                                      return self._repr_recursion(self.root_item)
                              
                              1 Reply Last reply
                              0
                              • S Stan Pamela has marked this topic as solved on

                              • Login

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