PDA

View Full Version : Dropping onto a QSqlQueryModel



kroenecker
6th July 2006, 05:09
I want to be able to drop an object onto a QSqlQueryModel, which is contained in a QListView. Now, in order for the drop action to work, do I need to reimplement dropMimeData?

Big Duck
6th July 2006, 10:09
Hi,
I have been doing some drag and drop within a treeView here:
http://www.qtcentre.org/forum/f-newbie-4/t-drag-and-drop-revisited-2829.html

Your drop will work, without dropMimeData but, you may need it to make the drop work as you wanted.

You could do functionality in : MyTreeView::dropEvent(QDropEvent *event)
but it is probably not what you want.

I have not used dropMimeData yet but to make the model use the QSqlQueryModel it is probably a good idea.

Hope this helps,

kroenecker
6th July 2006, 14:14
I have reimplemented dropEvent() in my new class, but for some reason the action of dropping doesn't call dropEvent(). I'm not sure what I'm doing wrong quite yet :P

Big Duck
6th July 2006, 16:20
Mybe I could help if you post some code.

kroenecker
6th July 2006, 16:45
MyListView::MyListView(QWidget *parent)
:QListView(parent)
{
setAcceptDrops(true);
}

void MyListView::dragEnterEvent(QDragEnterEvent * event)
{
if(event->mimeData()->hasFormat("text/uri-list"))
{
std::cout << "OK" << std::endl;
event->accept();

}
std::cout << "drag" << std::endl;
}

void MyListView::dropEvent(QDropEvent * event)
{
std::cout << "Drop" << std::endl;
event->acceptProposedAction();
}

Now when I drag something into the mylistview widget, dragEnterEvent fires and the mimeData format is correctly interpreted, but dropping doesn't do anything.

In fact when I drag something over the widget, the cursor doesn't turn into a drop cursor. It turns into what I would describe as an action denied cursor.

Please note that I haven't written any code for the model that this listview uses. I'm using a generic QSqlQueryModel.

Big Duck
6th July 2006, 17:42
Yeah thats the problem I think,
You will have to subclass the Model and implement :



QStringList MyModel::mimeTypes () const
{
QStringList list;
list << ""text/uri-list"";
return list;
}


This should stop the action denied cursor from appearing

kroenecker
6th July 2006, 18:42
Big Duck you rock. How in the world did you figure that out? I need to look over that particular virtual function I guess.

kroenecker
6th July 2006, 22:34
Now I am trying to figure out my next step. Again, I want to drag an item into the field (done and works). Then I want to check the items type (this is easy because dropped items return a mimetype of text/uri-list in windows).

My question is: after dropping something, how do I let the model know that I want it to act on the data? I cannot just perform actions in MyListView::dropEvent() because, to complicate matters, I want to be able to check:

1) that if I drop an object that is already present in the itemlist, it is ignored (for now).
2) if it isn't in the list then it is copied to a specified location and that location is then added to my database as an absolute path.

Admittedly, I'm a bit slow on the uptake as to how this all works, but I really appreciate your suggestions.

kroenecker
6th July 2006, 22:51
I almost feel like I need to use createIndex() somehow because dropMimeData seems to require that I drop on an already existsing item. Am I reading that correctly? Anyway here is some more code:


bool MyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
std::cout << "MyModel" << std::endl;
if(action == Qt::IgnoreAction)
return true;

if(!data->hasFormat("text/uri-list"))
return false;

if(column > 0)
return false;

if(action == Qt::CopyAction)
{
std::cout << "copyaction" << std::endl;
return true;
}
return false;
}

QStringList MyModel::mimeTypes() const
{
QStringList list;
list << "text/uri-list";
return list;
}

To say the least dropMimeData(...) isn't being called when I drop something into the model.

kroenecker
7th July 2006, 05:35
Do I need to reimplement insertRow() possibly?

Big Duck
7th July 2006, 11:28
I havent used dropMimeData data so I cant help more, but would like to know how you get it to work when you do ;)

You could try some of the following:

Qt:: DropActions supportedDropActions () const;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const

These docs may help too:
http://doc.trolltech.com/4.1/model-view-dnd.html
http://doc.trolltech.com/4.1/model-view-model-subclassing.html#drag-and-drop-support-and-mime-type-handling

kroenecker
7th July 2006, 14:41
No problem B D(awg). You have been a big help. Hopefully the weekend will offer enough free time for me to figure this out.

kroenecker
16th July 2006, 08:00
I'm finding this to be really difficult. If someone has an example that I could use, I'd appreciate it.

wysota
16th July 2006, 09:26
If you want to use dropMimeData (which you should), you can't reimplement events connected with dropping. You shouldn't reimplement them at all, because this way you act on the view and not on the model.

You should reimplement three methods from the model -- dropMimeData, mimeTypes and possibly mimeData (the latter only in case you want to drag items from the model and not only drop on them). mimeTypes should return a list of mime types which describe items in the model. If you don't want to drag items from the model it is possible you don't need to do anything here, although I'm not sure about it. dropMimeData should be reimplemented to take an action when an actual drop occurs. Remember that new items are dropped onto existing ones and corresponding indexes should already be created by the model there, so you should only fill the data of the item.

Remember to reimplement flags() too to make sure items are DropEnabled.

Your problem may lie elsewhere -- QSqlQueryModel is a read-only model, so you may not add any data to it. You either have to use another model (like QSqlTableModel) or make some smart reimplementation (the word smart is crucial here) to make QSqlQueryModel write enabled.

kroenecker
16th November 2006, 19:20
This is a sort of "note to self" post:

After upgrading to 4.2 I had problems with drag and drop again so I reimplemented the flags returned as below:


Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QSqlQueryModel::flags(index);
return Qt::ItemIsDropEnabled | defaultFlags;
}

This fixed everything.

Note: MyModel derives from SqlQueryModel, which can't be edited by design, so I had to return ItemIsDropEnabled in order to get my code to work again.