PDA

View Full Version : drag and drop with item views



castorvert
24th March 2006, 07:23
Hello,

Do you know when an item view uses the mimeTypes() , mimeData and dropMimeData functions ?

I've done sth really strange ::confused:
in my item view, in the function "mouseMoveEvent",
I create an new QDrag and the mimeData is the following :
code:


QMimeData* m=model()->mimeData(selectedIndexes())

Don't you think it's done automatically ?

Moreover, in the example "puzzle with item views", the function "dropMimeData" is defined in the model but it doesn't seem to be used. The same for mimeTypes().
I thought it was called by the view.

And last question : assume that I select several items, which are not following each others, can I use the function insertRows ? I can't use "insertRow" because it isn't virtual and I subclassed the model.

Thanks,:)

zlatko
24th March 2006, 09:14
Don't you think it's done automatically ?


Yes you dont must do it manually :)



Moreover, in the example "puzzle with item views", the function "dropMimeData" is defined in the model but it doesn't seem to be used. The same for mimeTypes().
I thought it was called by the view.


Yes it called by view :)

p.s.
last questions i'm not understand

castorvert
24th March 2006, 12:51
So, is it necessary to create a QDrag object in the function "mouseMoveEvent" of the view ?

My last question was that, in my opinion, removeRows only delete rows who are following each others, and it might be not possible to use it when they are not following each others.

wysota
24th March 2006, 14:08
Do you know when an item view uses the mimeTypes() , mimeData and dropMimeData functions ?

Sure. During drag & drop :) mimeTypes() returns a list of supported MIME types for the model (I assume they are the ones which may be dropped onto a view supporting this model), mimeData() returns a QMimeData pointer to an object containing item representation in different MIME formats and dropMimeData() handles a drop on the model level. You should reimplement mimeData() if you want to enable dragging from the model and the other two to enable dropping on the model.



I've done sth really strange ::confused:
in my item view, in the function "mouseMoveEvent",
I create an new QDrag and the mimeData is the following :
code:


QMimeData* m=model()->mimeData(selectedIndexes())

Don't you think it's done automatically ?

Do you use one of the default views? If so, you don't have to do anything with above methods to make D&D work. It should be enough to enable dragging and dropping in respective widgets and make sure the model returns correct data for those three methods you mentioned in the beginning.


Moreover, in the example "puzzle with item views", the function "dropMimeData" is defined in the model but it doesn't seem to be used. The same for mimeTypes().
I thought it was called by the view.

mimeTypes() should be called when you drag an item and hold it over a view. The view then asks the model if it should accept the drag or not (if it should show the "stop" sign or not). dropMimeData() should be called when an actual drop is made. As far as I understand it should perform operations on the model to set the desired data from the drag.


And last question : assume that I select several items, which are not following each others, can I use the function insertRows ? I can't use "insertRow" because it isn't virtual and I subclassed the model.

insertRow() calls insertRows() internally. You should reimplement insertRows() according to its parameters and let the model and view abstractions handle the rest. They will call your methods properly.

castorvert
24th March 2006, 18:49
Do you use one of the default views?
In fact, I subclassed QListView and also QTreeView (so I have 2 models).

wysota
24th March 2006, 18:56
Models? Or views? QTreeView and QListView are views not models... And are you sure you need to subclass them? It is rarely needed...

castorvert
25th March 2006, 08:47
I meant I had 2 models associated with my 2 views. I'll try not to subclass my views but to use the original ones. In fact, I thought I had to define custom functions for drag and drop in my views, that's why I subclassed the Qt views.

castorvert
25th March 2006, 08:51
Well, I thought about it, and in my opinion, even if I don't define custom functions, it's better to subclass the view because when I create my object, I can define the delegate, the colour, the setDropEnabled ...

castorvert
25th March 2006, 09:25
I found sth strange : when I subclass QAbstractListModel, I have to subclass flags() to have Drag and drop enabled. In QAbstractItemModel, there is only :


Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;

return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
}

wysota
25th March 2006, 09:50
Well, I thought about it, and in my opinion, even if I don't define custom functions, it's better to subclass the view because when I create my object, I can define the delegate, the colour, the setDropEnabled ...
You don't have to subclass to do that. You use that view only once, so there is no point is subclassing.


I found sth strange : when I subclass QAbstractListModel, I have to subclass flags() to have Drag and drop enabled.

There is nothing strange in it. flags() from abstract item model just implements the most common behaviour. If you want to have a more complicated model, you have to reimplement flags() along with other modelling methods.

castorvert
25th March 2006, 10:53
Thank you, i've finally understood what mimeTypes() is.
I have another question, if you please.

Let's take an example :

-I defined supportedDropActions() in a model as following :

Qt::DropActions ModeleDispos::supportedDropActions() const{
return Qt::MoveAction;
}
-I defined removeRows too.
-In "QAbstractItemView", it seems that "startDrag" and "dropEvent" use "supportedDropActions" so I think it's possible to move an item into the same view.
-the mimeTypes and mimeData are of the same Type.
but I couldn't move an item into the model.

It worked when I did :

Qt::DropActions ModeleDispos::supportedDropActions() const{
return Qt::MoveAction|Qt::CopyAction;
}

Do you know what could explain that ?

wysota
25th March 2006, 13:28
If you just drag an item, it is considered a copy action. To make a move action one has to hold some meta key -- control, alt or shift (I don't remember which) while performing the operation. I think it's possible to force some action but I don't know if it can be done without subclassing the view. Probably it would be easier to emulate a move within one view as a copy and handle it in dropMimeData().

castorvert
27th March 2006, 08:29
My solution was the following (I subclassed views) :


void viewSource::mouseMoveEvent(QMouseEvent *event)
{
QModelIndexList liste=selectedIndexes();
QMimeData *mimeData = model()->mimeData(liste);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - rect().topLeft());
Qt::DropAction dropAction = drag->start( Qt::MoveAction);
if (dropAction == Qt::MoveAction) {
model()->removeRows(liste[0].row(),liste.size(),liste[0].parent());
}
}

and :


void viewTarget::dropEvent(QDropEvent *e) //viewTarget subclassed QListView
{
QListView::dropEvent(e);
e->setDropAction(Qt::MoveAction);
e->accept();
}


I think it will remind you sth wysota

Thanks for all :D

castorvert
27th March 2006, 08:33
Well, in fact, my "removeRows" doesn't work because the selected items aren't obligatory following each others.

wysota
27th March 2006, 11:12
I think it will remind you sth wysota


Hmm... remind me what? :)