7

I'm using a QTableView with a QAbstractTableModel and a QSortFilterProxyModel so that I can sort the items by clicking on the table headers. I'd like to add the option for the user to sort the rows in the view manually, by dragging them. I don't need to be able to do drag and drop from/to any external application, just to change the order in the list. I also don't need to change the data in the model, I only want the order to be different in the view.

I've been looking through the documentation, and it seems like I have to implement mimeTypes, mimeData, and dropMimeData, but this gets very complicated fast! Some of the data in my model is not actually displayed in the view, and like I said I don't want to change the order of data in the model. Is there a way to simply drag items to change their sorting (just like the headers are already able to do) without a huge amount of coding?

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
  • Are you still having the problem? I could try to give you an answer how to do the drag-drop easily. However, from my experience, it is not possible to insert to a specific line into a *sorted* model: If you have an entry "a", and you tell it to insert "b" in any row, it will always be inserted below "a". – Johannes Sep 23 '12 at 06:04

1 Answers1

11

Updated for QT5 to remove deprecated methods

If you are using PyQT All you need to do for your requirements is this:

your_tableview.verticalHeader().setSectionsMovable(True)
your_tableview.verticalHeader().setDragEnabled(True)
your_tableview.verticalHeader().setDragDropMode(QAbstractItemView.InternalMove)

Then rinse and repeat with horizontalHeader if you want those rearrange-able too.

You are absolutely right, you shouldn't need to touch or even know what the model is for this functionality. This is further demonstrated by your proper use of the QSortFilterProxyModel decorator over the model itself.

The stuff you saw about mimeTypes and all of that stuff is for drag-and-drop of actual objects of varying sources from other windows/applications/desktop/etc and isn't needed for what you are trying to accomplish currently.

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
  • QHeaderView inherits from QAbstractItemView.... so it ALSO belongs to QHeaderView. I never said that it didn't. What's your point? Perhaps you should think about why based on OP's requirements I deliberately DIDN'T modify the entire tableview.. – UpAndAdam Sep 18 '15 at 18:20
  • Upon reading further it seems like there might also be an option to use setSectionsMovable – UpAndAdam Sep 18 '15 at 18:23
  • 1
    sorry for the noise, didn't pay attention. Deleted my comment to not create misguidance – Sergio Martins Sep 19 '15 at 12:34
  • Cant imagine that this will work. QAbstractTableModel has no clue of the data. There has to be some sort of reimplementation. – ManuelSchneid3r Oct 11 '15 at 10:04
  • Not really, the entire point of MVC & MV/C is that view doesn't know about the data. The view is responsible for mapping a request for a given 'row' or 'column' of data from a visual row to a logical row of the data. Imagine the model is big and shared by different views. Only changes to the model should be communicated to the other views. "How?" View knows initially that logical row/column equal visual row/column. If view rearranges them it simply must map the new relationship to logical/visual R/C. That's why the interface has functions capable of doing this. Don't imagine, try it. – UpAndAdam Oct 12 '15 at 14:40
  • And how is it in Qt5? – ManuelSchneid3r Oct 12 '15 at 21:12
  • Read the release notes. seeing as i did this in qt5 i dont think there's a difference. but if you think anything more than the function names is going to change; I think you are sadly mistaken. – UpAndAdam Oct 13 '15 at 22:51
  • 3
    The original post asks about moving rows; it's verticalHeader for that, not horizontalHeader as the answer states. Also, setMovable is obsolete and should now be setSectionsMovable. The docs say that setMovable is still present, but in Qt 5.5.1 in Qt Creator, it wouldn't compile for me. – goug Nov 29 '16 at 23:25
  • @goug good point about the vertical / horizontal bit; surprising however is that the OP liked the answer. You are correct setMovable is deprecated and setSectionMovable is now preferred; i'm updating the answer to avoid confusion as most folks are now on QT5 now. That said you should check out http://stackoverflow.com/questions/25622952/how-enable-deprecated-functions-in-qt5 which answers how to make use of QT deprecated functions in C++. My answer was done through PYQT where at least in the implementation I used it wasn't an issue. – UpAndAdam Dec 05 '16 at 21:45
  • Ah, good to know. I wasn't aware of that macro. Fortunately, in our projects, we haven't had a big issue with deprecated functions, but glad to have that tip in my tool box. Thank you. – goug Dec 05 '16 at 22:11
  • Does anyone know how to set things up so that you can drag the row by clicking anywhere on it (and not just on the vertical header)? – user118967 Mar 24 '21 at 07:22