When you want to save custom information for each node then you must use the roles (preferably >= Qt::UserRole since the roles can be used internally by Qt). For example, in the following code 2 roles are used to store 2 types of information.
If QTreeWidget is used then you must use the setData()
method and pass it the role and value to store the information, to obtain the information you must use the data()
method by passing the role.
from enum import Enum
import uuid
from PyQt5 import QtCore, QtWidgets
TypeRole = QtCore.Qt.UserRole + 1000
IdRole = QtCore.Qt.UserRole + 1001
class TypeItem(Enum):
ROOT = 0
CHILD = 1
class Dialog(QtWidgets.QDialog):
def __init__(self, name, type_, id_, parent=None):
super().__init__(parent)
self.name_le = QtWidgets.QLineEdit(name)
type_label = QtWidgets.QLabel(str(type_))
self.id_le = QtWidgets.QLineEdit(id_)
button_box = QtWidgets.QDialogButtonBox()
button_box.setOrientation(QtCore.Qt.Horizontal)
button_box.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.name_le)
lay.addWidget(type_label)
lay.addWidget(self.id_le)
lay.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
@property
def name(self):
return self.name_le.text()
@property
def id_(self):
return self.id_le.text()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.view = QtWidgets.QTreeWidget()
self.view.itemDoubleClicked.connect(self.onItemDoubleClicked)
self.setCentralWidget(self.view)
for i in range(3):
root_it = QtWidgets.QTreeWidgetItem(["tlv-{}".format(i)])
root_it.setData(0, TypeRole, TypeItem.ROOT)
root_it.setData(0, IdRole, uuid.uuid4().hex)
self.view.addTopLevelItem(root_it)
for j in range(3):
child_it = QtWidgets.QTreeWidgetItem(["it-{}{}".format(i, j)])
child_it.setData(0, TypeRole, TypeItem.CHILD)
child_it.setData(0, IdRole, uuid.uuid4().hex)
root_it.addChild(child_it)
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, int)
def onItemDoubleClicked(self, item, column):
name = item.text(column)
type_ = item.data(column, TypeRole)
id_ = item.data(column, IdRole)
d = Dialog(name, type_, id_)
if d.exec_() == QtWidgets.QDialog.Accepted:
item.setText(column, d.name)
item.setData(column, IdRole, d.id_)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
If you use QTreeView then the handling of that role must be implemented in the model, for the following example, QStandardItemModel is used where each QStandardItem has the setData() method and data() to store and retrieve the information.
from enum import Enum
import uuid
from PyQt5 import QtCore, QtGui, QtWidgets
TypeRole = QtCore.Qt.UserRole + 1000
IdRole = QtCore.Qt.UserRole + 1001
class TypeItem(Enum):
ROOT = 0
CHILD = 1
class Dialog(QtWidgets.QDialog):
def __init__(self, name, type_, id_, parent=None):
super().__init__(parent)
self.name_le = QtWidgets.QLineEdit(name)
type_label = QtWidgets.QLabel(str(type_))
self.id_le = QtWidgets.QLineEdit(id_)
button_box = QtWidgets.QDialogButtonBox()
button_box.setOrientation(QtCore.Qt.Horizontal)
button_box.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.name_le)
lay.addWidget(type_label)
lay.addWidget(self.id_le)
lay.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
@property
def name(self):
return self.name_le.text()
@property
def id_(self):
return self.id_le.text()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.model = QtGui.QStandardItemModel(self)
self.view = QtWidgets.QTreeView()
self.view.setModel(self.model)
self.view.doubleClicked.connect(self.onDoubleClicked)
self.setCentralWidget(self.view)
for i in range(3):
root_it = QtGui.QStandardItem("tlv-{}".format(i))
root_it.setData(TypeItem.ROOT, TypeRole)
root_it.setData(uuid.uuid4().hex, IdRole)
self.model.appendRow(root_it)
for j in range(3):
child_it = QtGui.QStandardItem("it-{}{}".format(i, j))
child_it.setData(TypeItem.CHILD, TypeRole)
child_it.setData(uuid.uuid4().hex, IdRole)
root_it.appendRow(child_it)
@QtCore.pyqtSlot(QtCore.QModelIndex)
def onDoubleClicked(self, index):
item = self.model.itemFromIndex(index)
name = item.text()
type_ = item.data(TypeRole)
id_ = item.data(IdRole)
d = Dialog(name, type_, id_)
if d.exec_() == QtWidgets.QDialog.Accepted:
item.setText(d.name)
item.setData(d.id_, IdRole)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())