Found this post while doing something similar for a scenegraph editor, hopefully its not too late to add more to it.
I looked into why this was, and it was due to my dropAction being set to InternalMove for my QTreeView. I thought InternalMove was what I needed, but it looks like DragDrop, does the job. The dangling pointer issue is resolved since my SceneModel no-longer removes nodes unexpectedly. My QTreeView's drag and drop performance also seems to work more fluidly. I used to have to select my node in a sweet spot to get it to work. I can also drag nodes into my the top-level hierarchy.
Actually that does not seem to be entirely accurate, I think removeRows should remove (delete scene nodes), such that you can use it for that specific purpose, say in a context menu or when pressing the delete key while a node is selected. What I found is that you should enable the DragDropOverrideMode on the view for it not to call remove on the original indices, DragDrop vs InternalMove seems not to make a difference to me.
Either way, the design seems to be missing something, models deal almost exclusively with QModelIndex objects, with row,column and internalPointer being the most important aspects of them, but then when drag and drop comes into the picture, you have to deal with mime types, with no alternate option to just have a "drop" method for indices or an index list. Furthermore, the information encoded in the default mime data is row, column and a map with what the data method returns for each role, no internalPointer which is most likely what you really need in this situation.
Here is a partial solution that overrides QTreeView::dropEvent in order to access the selected items, but I rather not have to create a new class that inherits from QTreeView just for that, so I am looking into options, so far, I guess the least intrusive option would be overriding QAbstractItemModel::itemData to include a UserRole with the item's internalPointer so I dont have to override QAbstractItemModel::mimeData which would be a different mess.
Either way you definitely need to override QAbstractItemModel::dropMimeData, the default implementation calls insertRows, and tries to fill the inserted rows with setData/setItemData, which is probably not what you or I want since my insertRows implementation calls new Node and we don't want a new node, we want the already existing one moved. So a call to moveRows would be much more appropriate, but you need to rebuild the source indexes from the mime data.