TreeView Example
from DevMachines import __pyside2__, __pyside6__
if __pyside2__:
from PySide2 import QtCore
from PySide2.QtCore import Qt, QAbstractItemModel, QModelIndex
if __pyside6__:
from PySide6 import QtCore
from PySide6.QtCore import Qt, QAbstractItemModel, QModelIndex
class TreeItem():
def __init__(self, data, parent = None):
self.childItems = list()
self.itemData = data
self.parentItem = parent
def child(self, number):
if number < 0 or number >= len(self.childItems):
return None;
return self.childItems[number]
def childCount(self):
return len(self.childItems)
def childNumber(self):
if self.parentItem != None:
return self.parentItem.childItems.index(self)
return 0;
def columnCount(self):
return len(self.itemData)
def data(self, column):
if column < 0 or column >= len(self.itemData):
return None
return self.itemData[column]
def insertChildren(self, position, count, columns):
if position < 0 or position > len(self.childItems):
return False
for row in range(count):
data = [None] * (columns)
item = TreeItem(data, self)
self.childItems.insert(position, item)
return True
def insertColumns(self, position, columns):
if position < 0 or position > len(self.itemData):
return False
for column in range(columns):
self.itemData.insert(position, None)
for i in range(len(self.childItems)):
self.childItems[i].insertColumns(position, columns)
return True
def parent(self):
return self.parentItem
def removeChildren(self, position, count):
if position < 0 or position + count > len(self.childItems):
return False
for row in range(count):
self.childItems.pop(position)
return True
def removeColumns(self, position, columns):
if position < 0 or position + columns > len(self.itemData):
return False
for column in range(columns):
self.itemData.pop(position)
for i in range(len(self.childItems)):
self.childItems[i].removeColumns(position, columns)
return True
def setData(self, column, value):
if column < 0 or column >= len(self.itemData):
return False
self.itemData[column] = value
return True
class TreeModel(QAbstractItemModel):
def __init__(self, headers, data, parent = None):
QAbstractItemModel.__init__(self, parent)
rootData = list()
for header in headers:
rootData.append(header)
self.rootItem = TreeItem(rootData)
self.setupModelData(data.split('\n'), self.rootItem)
def columnCount(self, parent):
return self.rootItem.columnCount()
def data(self, index, role):
if not index.isValid():
return None
if role != Qt.DisplayRole and role != Qt.EditRole:
return None
item = self.getItem(index)
return item.data(index.column())
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
return Qt.ItemIsEditable ^ QAbstractItemModel.flags(self, index)
def getItem(self, index):
if index.isValid():
item = index.internalPointer()
if item != None:
return item
return self.rootItem
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.rootItem.data(section)
return None
def index(self, row, column, parent):
if parent.isValid() and parent.column() != 0:
return QModelIndex()
parentItem = self.getItem(parent)
if parentItem == None:
return QModelIndex();
childItem = parentItem.child(row)
if childItem != None:
return self.createIndex(row, column, childItem)
return QModelIndex()
def insertColumns(self, position, columns, parent):
self.beginInsertColumns(parent, position, position + columns - 1)
success = self.rootItem.insertColumns(position, columns)
self.endInsertColumns()
return success
def insertRows(self, position, rows, parent):
parentItem = getItem(parent)
if parentItem == None:
return False
self.beginInsertRows(parent, position, position + rows - 1);
success = parentItem.insertChildren(position, rows, self.rootItem.columnCount())
self.endInsertRows()
return success
def parent(self, index):
if not index.isValid():
return QModelIndex()
childItem = self.getItem(index);
parentItem = None
if childItem != None:
parentItem = childItem.parent()
if parentItem == self.rootItem or parentItem == None:
return QModelIndex()
return self.createIndex(parentItem.childNumber(), 0, parentItem)
def removeColumns(self, position, columns, parent):
self.beginRemoveColumns(parent, position, position + columns - 1)
success = self.rootItem.removeColumns(position, columns)
self.endRemoveColumns()
if self.rootItem.columnCount() == 0:
self.removeRows(0, self.rowCount())
return success
def removeRows(self, position, rows, parent):
parentItem = self.getItem(parent)
if parentItem == None:
return False
self.beginRemoveRows(parent, position, position + rows - 1)
success = parentItem.removeChildren(position, rows)
self.endRemoveRows()
return success
def rowCount(self, parent):
parentItem = self.getItem(parent)
if parentItem == None:
return 0
return parentItem.childCount()
def setData(self, index, value, role):
if role != Qt.EditRole:
return False
item = self.getItem(index)
result = item.setData(index.column(), value)
if result:
self.dataChanged(index, index, [Qt.DisplayRole, Qt.EditRole])
return result
def setHeaderData(self, section, orientation, value, role):
if role != Qt.EditRole or orientation != Qt.Horizontal:
return False
result = self.rootItem.setData(section, value)
if result:
self.headerDataChanged(orientation, section, section)
return result
def setupModelData(self, lines, parent):
parents = list();
indentations = list();
parents.append(parent)
indentations.append(0)
number = 0
for number in range(len(lines)):
position = 0
while position < len(lines[number]):
if str(lines[number][position], 'utf-8') != ' ':
break
position += 1
lineData = str(lines[number][position:].trimmed(), 'utf-8')
if lineData:
# Read the column data from the rest of the line.
columnStrings = lineData.split('\t')
columnData = list()
for columnString in columnStrings:
if columnString:
columnData.append(columnString)
if (position > indentations[-1]):
# The last child of the current parent is now the new parent
# unless the current parent has no children.
if parents[-1].childCount() > 0:
parents.append(parents[-1].child(parents[-1].childCount() - 1))
indentations.append(position)
else:
while position < indentations[-1] and len(parents) > 0:
parents.pop()
indentations.pop()
# Append a new item to the current parent's list of children.
p = parents[-1]
p.insertChildren(p.childCount(), 1, self.rootItem.columnCount())
for column in range(len(columnData)):
p.child(p.childCount() - 1).setData(column, columnData[column])