UPDATE: (SOLVED)
Thanks to eyllanesc for making me write a working example code of my problem. That made me find the problem. Here is a working code with a fixed problem:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys
import os
class ExtendedTreeWidgetItem(QTreeWidgetItem):
def __init__(self, *args, **kwargs):
super(ExtendedTreeWidgetItem, self).__init__(*args, **kwargs)
self.rescueFile = None
print("created first time")
def setRescueFile(self, rFile):
self.rescueFile = rFile
print("setting rescue file", self.rescueFile, "for item", self.text(0))
def getRescueFile(self):
return self.rescueFile
class RescueFile:
def __init__(self, path):
self.path = path
self.ischecked = True
def isChecked(self):
return self.ischecked
def setChecked(self, checked):
if isinstance(checked, bool):
self.ischecked = checked
elif isinstance(checked, Qt.CheckState):
self.ischecked = True if checked == Qt.Checked else False
def getPath(self):
return self.path
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
windowSize = (800,400)
screenSize = QDesktopWidget().availableGeometry()
self.setGeometry(screenSize.width()/2 - windowSize[0]/2, screenSize.height()/2 - windowSize[1]//2, windowSize[0], windowSize[1])
self.setWindowTitle("TreeTest")
self.buildGui()
self.show()
def buildGui(self):
wgt = QWidget()
vlayout = QVBoxLayout()
vlayout.setAlignment(Qt.AlignTop)
grid_layout = QGridLayout()
self.setupTree(grid_layout)
vlayout.addLayout(grid_layout)
wgt.setLayout(vlayout)
self.setCentralWidget(wgt)
def setupTree(self, grid_layout):
self.treeWidget = QTreeWidget()
self.treeWidget.setHeaderLabel("Results")
self.treeWidget.setColumnCount(1)
#INSERTING DATA
topItem = ExtendedTreeWidgetItem()
topItem.setText(0, "top item")
topItem.setCheckState(0, Qt.Checked)
child1 = ExtendedTreeWidgetItem(topItem)
child1.setText(0, "child 1")
child1.setCheckState(0, Qt.Checked)
topItem.addChild(child1)
deeper_child = ExtendedTreeWidgetItem(child1)
deeper_child.setText(0, "deeper child 1")
deeper_child.setCheckState(0, Qt.Checked)
r_file = RescueFile("/home/user1/Desktop")
deeper_child.setRescueFile(r_file)
child1.addChild(deeper_child)
self.treeWidget.addTopLevelItem(topItem)
self.treeWidget.expandAll()
self.treeWidget.itemChanged.connect(self.singleClickTreeWidget)
grid_layout.addWidget(self.treeWidget, 1, 1, 4, 3)
def singleClickTreeWidget(self, widgetItem, column):
parent = widgetItem.parent()
if parent and parent.checkState(0) == Qt.Unchecked:
widgetItem.setCheckState(0, Qt.Unchecked)
return
checkState = widgetItem.checkState(0)
widgetItem.setCheckState(0, checkState)
rescue_file = widgetItem.getRescueFile()
if rescue_file:
rescue_file.setChecked(checkState)
print("rescue file found, path:", rescue_file.getPath(), "checked:", rescue_file.isChecked())
self.iterateThroughChildren(widgetItem, checkState)
def iterateThroughChildren(self, item, checkState):
for i in range(item.childCount()):
child = item.child(i)
print("child:", child, ",text:", child.text(0))
child.setCheckState(0, checkState)
# HERE WAS THE MISTAKE
# -- >> rescue_file = item.getRescueFile() << --
rescue_file = child.getRescueFile() # CORRECT CODE!!
print("rescue file", rescue_file, "child", child.text(0))
if rescue_file is not None:
rescue_file.setChecked(checkState)
else:
self.iterateThroughChildren(child, checkState)
def main():
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
app.exec_()
main()
BEFORE UPDATE:
I hope I can explain my problem clearly enough.
I trying to create QTreeWidget that uses my extended QTreeWidgetItems in python 3.5.3. Here is my code for the item class:
class ExtendedTreeWidgetItem(QTreeWidgetItem):
def __init__(self, *args, **kwargs):
super(ExtendedTreeWidgetItem, self).__init__(*args, **kwargs)
self.rescueFile = None
def setRescueFile(self, rFile):
self.rescueFile = rFile
def getRescueFile(self):
return self.rescueFile
class RescueFile:
def __init__(self, path):
self.path = path
self.ischecked = True
def isChecked(self):
return self.ischecked
def setChecked(self, checked):
if isinstance(checked, bool):
self.ischecked = checked
elif isinstance(checked, Qt.CheckState):
self.ischecked = True if checked == Qt.Checked else False
print(self.path, self.ischecked)
I use this code to implement checking and unchecking the rescue file:
****
...
self.treeWidget.itemChanged.connect(self.singleClickTreeWidget)
...
****
def singleClickTreeWidget(self, widgetItem, column):
parent = widgetItem.parent()
if parent and parent.checkState(0) == Qt.Unchecked:
widgetItem.setCheckState(0, Qt.Unchecked)
return
checkState = widgetItem.checkState(0)
widgetItem.setCheckState(0, checkState)
rescue_file = widgetItem.getRescueFile()
**# I CAN GET THE RESCUE FILE OBJECT HERE FROM**
if rescue_file:
rescue_file.setChecked(checkState)
self.iterateThroughChildren(widgetItem, checkState)
def iterateThroughChildren(self, item, checkState):
for i in range(item.childCount()):
child = item.child(i)
child.setCheckState(0, checkState)
**# I CAN'T GET ANY FIND HERE ANYMORE**
rescue_file = item.getRescueFile()
if rescue_file:
rescue_file.setChecked(checkState)
else:
self.iterateThroughChildren(child, checkState)
What my code does is that it generates a checkable tree like in the picture:
What I'm trying to achieve is that when I deselect/select an item (ExtendedTreeWidgetItem) that has children, all children are also selected/deselected as well as RescueFile objects associated with items. Only files are associated with RescueFile objects. Directories are left with self.rescueFile = None
For example if I pressed to deselect 'icons' then magnifier.png should also be deselected as well as RescueFile associated with it. Deselection of a checkboxes works like a charm but RescueFile is not affected (NOT FOUND) if I press on a parent of a file. But it works if I press directly on a file, for example magnifier.png.
I have tried to trace if it is a pointer problem but it seems like all objects point to the objects they are supposed to. I don't understand where does a rescueFile disappear if I am comming to ExtendedTreeWidgetItem recursively through it's parent.