Hi people... there is a certain eeem.... "behaviour" I stumbled upon in QAbstractItemView (and subclasses).

When I enable "InternalMove" semantics for D&D I would expect the view to move entire rows when dragging if "SelectRows" is chosen. But (!) regardless of how many columns you have in your model if any of them is hidden in the view (imagine what happens when you use QListView that has only one column) it is not being moved during InternalMove effectively breaking up your model.

Do you think it is a proper behaviour for this mechanism?

It is all called because QAbstractItemView::startDrag() calls QAbstractItemView::selectedIndexes() instead of going through the selection model. The latter returns all selected indexes while the former returns all selected indexes that are not hidden... Cool...

Of course there are numerous ways to overcome it but all require you to subclass the particular view class.

Solution:
  • Subclass Q{Tree,Table,List}View and reimplement one of the following methods: startDrag(), selectedIndexes(). Preferred would be to go through startDrag() because it is hard to say if reimplementing selectedIndexes() to return also the hidden columns wouldn't break some other functionality.
  • Reimplement mimeData() for your model and craft a new index list (containing all the columns) before calling the base class implementation. Hard luck if you'd like to be able to sometimes drag only complete rows and sometimes also fragments of them - if you go this way, it's either this or that.
  • Reimplement mimeTypes(), mimeData() and dropMimeData() for your model and implement your own InternalMove (i.e. by setting a 'very custom' mime type to mark a possible internal move and another mime-type for regular drags that may happen between different widgets).


Three hours wasted... Well, almost... at least I found out why some of my model columns had bogus values after doing InternalMove.