View Full Version : List-centred table view: How to implement DND and moving rows.

24th October 2009, 02:51
I want to implement some sort of playlist for a media player and ran into a few problems there. So, I’ve got several media items and number of properties like the name and length and so on for them. The media items should be structured in rows and the properties should be in the columns. Sorting by columns should be possible as well as moving the media items around by mouse dragging and dropping. I guess you know, what I’m talking about.

So, first of all, I’m unsure, how to implement all of this. I settled with QAbstractTableModel and QTableView but since my data is not really organised in a table but in a list of rows with certain properties, I do not know, if this approach is correct or if I should have used some other classes in the first place.

Now, concerning the dragging of items, I use the approach of having a Qt::UserRole set which will copy an internal serialisable data structure with the complete data of one row each time a drag is performed.

The problem is, when I set the flags to

Qt::ItemFlags flags(const QModelIndex &index) const {
Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
if (index.isValid())
return Qt::ItemIsDragEnabled | defaultFlags;
return Qt::ItemIsDropEnabled | defaultFlags;

the code is copied as many times as the current column number is.
When I include a

if (index.column() != 0) return defaultFlags; however, it looks as if I’m only dragging the first cell in the row.
Also, on some occasions, the row will be lost, when I drag the mouse to the wrong corner. What can I do about that?

I have given the rest of the code in an attachment, so if anyone could give me some advice on how to do this the right way, I’d be very glad.


25th October 2009, 10:37
Change the "selectionBehavior" property of the view to "SelectRows". Then you will always be dragging complete rows, if you need it. But on the other hand you don't have to do that. You are the one who decides what the drag contains by reimplementing appropriate methods in the model so you can fit data from all columns into a single drag.

26th October 2009, 21:35
Yes, this is what I have done already. But the thing is, that it will copy the row several times and not just move it. How do I turn this off, then?

26th October 2009, 22:09
Hmm. Ok, I have found a way to avoid the duplication. In my model, I added:

bool dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent) {
return QAbstractTableModel::dropMimeData(data, action,
row, 0, parent);

Doesn’t look to smart to me, but it keeps the rows ‘aligned’ when dragging and dropping.

26th October 2009, 23:25
It basically depends on the drop action you perform. If the action is DropMove, you should remove the old item after the drop.