I’m working on a custom application that has a qMRMLTreeView in a scripted python module. I’m using this to view models and hierarchies and fibers.
I want to see when users enable/disable a model/hierarchy/fiber, and maybe do something with the mrmlnode.
So I’ve connected the decorationClicked(QModelIndex) signal to a signal handler.
When my signal handler fires, sometimes it generates a crash.
Most frustratingly try/except didn’t catch the exception. It appears that if I could catch the exception that would be close enough for my purposes.
Alternatively any hints on avoiding it would be great.
Here are my more specific details.
I found this crash when getting the mrml node and have now traced it back.
I can replicate the problem when the QModelIndex.data, or the QModelIndex.flags accessors are used. The exact crash is difficult for me to find due to it being buried in qt.
I can mostly reliably replicate the problem using a few models, and a few model hierarchy nodes in the core “Models” module, with slicer nightly 2018-07-12(which my project is derived from).
I don’t know how to create models/model hierarchies programmatically right now, so that part of my testing is manual.
I load up slicer, switch to the models module, and add at least three hierarchy nodes, with at least one nested in the other.
I then load up any two models into the scene, attaching at least one to the deepest hierarchy node.
The crash is most reliable when moving hierarchies around, but simply clicking on the show/hide eye will cause it also. My first thought was some sort of race condition, but adding an arbitrary pause(up to seconds) didn’t resolve the issue in my signal handler.
Models set which should crash
scene
\HierarchyA
\HierarchyB
ModelA
\HierarchyC
ModelB
I run the following code in the slicer python terminal
to find the tree view, and add the signal handler.
import re
import time
def findWidget( widget, objectRegex ):
name_reg=re.compile(objectRegex)
if name_reg.match(widget.objectName):
return widget
else:
children = []
for w in widget.children():
resulting_widget = findWidget(w, objectRegex)
if resulting_widget:
return resulting_widget
return None
# consider slicer.util.findChild of findChildren instead.
def indexDumper(index):
treeView.disconnect('decorationClicked(QModelIndex)');
try:
# printing index always works... and never crashes.
# when we crash, none of the prints make it through, have to switch to logging to see them.
print(index)
# index is both not none, and marked valid yet it still crashes on accessing data or flags
if ( index is None ):
print("error, Index is none!")
if ( index.IsValid()):
print("index is valid")
print("row"+str(index.row()))
print("col"+str(index.column()))
print("sizof"+str(index.__sizeof__()))
# Both index.data, and index.flags can generate a crash here.
# it is intermittent.
#print("flags"+str(index.flags()))
#time.sleep(0.1)
print("data"+str(index.data()))
except:
print("Exception on index access!!!")
return
print("full dump complete")
treeView.connect('decorationClicked(QModelIndex)',indexDumper)
return
mW=slicer.modules.models.widgetRepresentation()
treeView=findWidget(mW,".*[Mm]odel.*[Tt]ree.*")
t=treeView.connect('decorationClicked(QModelIndex)',indexDumper)
# now click wildly on hierarchy nodes