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
Forum Updated to NodeBB v4.3 + New Features

Changing Font and background color of individual item in editable Treeview

Scheduled Pinned Locked Moved Solved Qt for Python
21 Posts 4 Posters 4.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.
  • SGaistS SGaist

    Hi,

    The most straightforward would be to modify your first if and expand its check, the rest is the same.

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

    Thanks @SGaist for helping out!

    That doesn't seem to work. If use

        model.setData(current_index, 'QWidget { font: bold italic large "Times New Roman"; font-size: 10pt }', role=Qt.FontRole)
    

    inside the update_actions function of mainwindow.py, together with

        if (role != Qt.EditRole) and (role != Qt.FontRole):
    

    inside the setData function of treemodel.py, what happens is that it just replaces the text of the item by

    'QWidget { font: bold italic large "Times New Roman"; font-size: 10pt }'
    

    as if that was a normal edit action. I think this is because the editable tree version has a whole wrapper of the data itself around it...

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

      It looks like you are trying to set a style sheet in the font role.

      The FontRole takes a QFont object.

      You can see here more information about the roles and what they expect.

      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

        It looks like you are trying to set a style sheet in the font role.

        The FontRole takes a QFont object.

        You can see here more information about the roles and what they expect.

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

        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 M 2 Replies Last reply
        0
        • 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