Issue
I have the next QJsonTreeItem with insertChildren() function::
class QJsonTreeItem(object):
...
def setData(self, column, value) -> None:
if column is 0:
self.key = value
if column is 1:
self.value = value
def insertChildren(self, position, rows, columns) -> bool:
if position < 0 or position > len(self._children):
return False
for row in range(rows):
data = [None for v in range(columns)]
item = QJsonTreeItem(data, self)
self._children.insert(position, item)
return True
With the next QJsonTreeModel insertRows() and setData() functions:
class QJsonTreeModel(QAbstractItemModel):
...
def insertRows(self, position: int, rows: int, parent: QModelIndex) -> bool:
parent_item = self.getItem(parent)
self.beginInsertRows(parent, position, position + rows - 1)
success = parent_item.insertChildren(position, rows, self._root_item.columnCount())
self.endInsertRows()
return success
def setData(self,
index: QModelIndex,
value: str=None,
role: Qt.ItemDataRole=Qt.EditRole
) -> bool:
if role == Qt.EditRole:
item = index.internalPointer()
item.setData(index.column(), value)
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
if role == Qt.DecorationRole:
item = index.internalPointer()
item.setData(0, value)
item.setData(1, "[No string value]")
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
if role == Qt.ToolTipRole:
item = index.internalPointer()
item.setData(0, value)
item.setData(1, int(1))
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
if role == Qt.StatusTipRole:
item = index.internalPointer()
item.setData(0, value)
item.setData(1, False)
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
if role == Qt.WhatsThisRole:
item = index.internalPointer()
item.setData(0, "[No dict() name]")
item.setData(1, dict())
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
if role == Qt.SizeHintRole:
item = index.internalPointer()
item.setData(0, "[No list() name]")
item.setData(1, list())
self.dataChanged.emit(index, index, [Qt.EditRole])
return True
return False
In my MainWindow file I insert data like this:
def tree_add_item(self, role: Qt.ItemDataRole) -> None:
index = self.tree_view.selectionModel().currentIndex()
parent = index.parent()
if self.model.data(parent, Qt.EditRole) is None:
if not self.model.insertRow(index.row() + 1, parent):
return
for column in range(self.model.columnCount(parent)):
child = self.model.index(index.row() + 1, column, parent)
if role == Qt.DecorationRole:
self.model.setData(
index=child,
value="[No string key]",
role=role)
return
elif role == Qt.ToolTipRole:
self.model.setData(
index=child,
value="[No int data]",
role=role)
return
elif role == Qt.StatusTipRole:
self.model.setData(
index=child,
value="[No bool data]",
role=role)
return
elif role == Qt.WhatsThisRole or Qt.SizeHintRole:
self.model.setData(index=child, value=None, role=role)
# self.action_save_json_file()
# self.action_refresh_json_file()
return
else:
return
def tree_add_item_child(self, role: Qt.ItemDataRole) -> None:
index = self.tree_view.selectionModel().currentIndex()
parent = index
if not self.model.insertRow(0, parent):
return
for column in range(self.model.columnCount(parent)):
child = self.model.index(0, column, parent)
if role == Qt.DecorationRole:
self.model.setData(
index=child,
value="[No string key]",
role=role)
elif role == Qt.ToolTipRole:
self.model.setData(
index=child,
value="[No int data]",
role=role)
elif role == Qt.StatusTipRole:
self.model.setData(
index=child,
value="[No bool data]",
role=role)
elif role == Qt.WhatsThisRole or Qt.SizeHintRole:
self.model.setData(
index=child,
value=None,
role=role)
# self.action_save_json_file()
# self.action_refresh_json_file()
The problem is it successfuly adds new dict() or list() to the QTreeView like this
I want to add new child items, which my programm successfully adds
But when I`m saving back model to the file there is no recently added child string
Am I doing something wrong or it should work like this? At the moment my solution is to save back to the .json file new added dict() or list() and then load it againg to the QTreeView (commented lines: self.action_save_json_file() and self.action_refresh_json_file()). It`s working but it seems like a bad idea since not every user want to save immediately new added dict() or list(). Where am I wrong and how to solve this problem?
Update: My method for getting json from tree is this. It generates dict() from tree which I`m saving to some file.
Small clarification: after saving json to file and loading it back to QTreeView I`m able to add child elements to recently added dict() or list() and they can be edited or removed
def get_json_from_tree(self, root: QJsonTreeItem=None) -> dict:
root = root or self._root_item
return self.generate_json_from_free(root)
def generate_json_from_free(self, item) -> dict:
amount_of_child = item.childCount()
if item.type is dict:
document = {}
for i in range(amount_of_child):
child = item.child(i)
document[child.key] = self.generate_json_from_free(child)
return document
elif item.type == list:
document = []
for i in range(amount_of_child):
child = item.child(i)
document.append(self.generate_json_from_free(child))
return document
else:
return item.value
Solution
The actual problem was that my generate_json_from_free()
function did not catch QJsonTreeItem.type
of newly added dictionary or list. item.type
returned None
and iti s simply did not enter to the if
section.
The solution is to set type of the QJsonTreeItem when user wants to add dict() or list() like this:
self.model.getItem(child).type = dict
for dict() and for list() is this:
self.model.getItem(child).type = list
The complete code is this:
def tree_add_item(self, role: Qt.ItemDataRole) -> None:
if self.model.data(parent, Qt.EditRole) is None:
if not self.model.insertRow(index.row() + 1, parent):
return
for column in range(self.model.columnCount(parent)):
child = self.model.index(index.row() + 1, column, parent)
if role == Qt.DecorationRole:
self.model.setData(
index=child,
value="[No string key]",
role=role)
return
elif role == Qt.ToolTipRole:
self.model.setData(
index=child,
value="[No int data]",
role=role)
return
elif role == Qt.StatusTipRole:
self.model.setData(
index=child,
value="[No bool data]",
role=role)
return
elif role == Qt.WhatsThisRole:
self.model.setData(index=child, value=None, role=role)
self.model.getItem(child).type = dict
return
elif role == Qt.SizeHintRole:
self.model.setData(index=child, value=None, role=role)
self.model.getItem(child).type = list
return
else:
return
Answered By - Leonid
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.