[PyQt] QTreeView + sort + delete = crash

John F Sturtz john at sturtz.org
Fri May 3 04:25:38 BST 2019


Hi again.  I usually try to keep banging on problems like this until I solve them, but this one has me stumped.  I'm hoping someone has enough familiarity with what's at play here to suggest a way out.

I have a QTreeView with an underlying node tree structure and data model, which displays a list of categories and subcategories.

There is also a dialog box (defined in the attached QtDesigner .ui file) which displays the items in the QTreeView and supports the following operations:
* Add items to the tree (the Main and Sub buttons add a main category or subcategory, respectively)
* Delete items from the tree (the Delete button)
* Change the description of an item in the tree (double-click an item, and it is editable via a delegate with a QLineEdit-based editor widget)
Code is attached.  Sorry it's a bit long; I distilled it down as much as I could.

The problem seems to occur due to a combination of sorting and item deletion.  Because I want the items to remain in alphabetical order, the setData() method in the model sorts the items at the affected level when there is either an insertion or a description is changed (line #218).  I am emitting the layoutAboutToBeChanged and layoutChanged signals before and after the sort, as I understand one should.  (I probably could accomplish this with a QSortFilterProxyModel, but just using sort directly seemed simple enough, so I went with it).

It seems that if I make a change that effects a sort lower in the tree, and then delete an item from further up in the tree, the code crashes.  The specific sequence I've been using (though I suspect there are others) is this:
* Start the app (guess that would have been self-evident)
* Expand the Pet Expenses item
* Double-Click Chow, and change it to anything that occurs alphabetically after 'Miscellaneous'.  When the editor is closed, the sort should position the item at the end of the Pet Expenses subcategory list.
* Now delete the item you just edited (it should be the current item).
* Next, select Dining and click the Delete button to delete that item.
On my machine, this consistently causes the app to crash.

I've think I've narrowed the problem down to the model's parent() method.  Specifically, it crashes on the index.internalPointer() call on line #192 (at the time of the crash, the print() statement on line #191 will display, but the one on line #193 will not).  The row number it is trying to get internalPointer() for is 1 when it crashes.

I'm guessing this is caused by trying to access a deleted item (I'd have thought the if not index.isValid() statement on line #188 would have prevented that).  I also suspect it is the sorting that is causing the confusion, because if I comment out the sort line, it doesn't crash.  (But I'd have thought the layoutAboutToBeChanged and layoutChanged signals would have taken care of that).

Any help or insight would surely be appreciated.

Thanks again.

/John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190502/a3b1589b/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dlg.ui
Type: text/xml
Size: 4323 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190502/a3b1589b/attachment-0001.xml>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: cat.py
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190502/a3b1589b/attachment-0001.ksh>


More information about the PyQt mailing list