How to correctly use "application/x-qabstractitemmodeldatalist" mime type in derived model/view classes drag and drop operations?
-
Hi, all,
I'm building an application using QAbstractItemModel for custom types of items in a QListView and in a QTreeView. Those items have to be dragged/dropped inside the QTreeView - both copy and move - and dragged from the QListView and dropped to the QTreeView.
Although much of the functionality is already working, on the tree model class, in the "dropMimeData" method, I don't get the "row" and "column" the data was dropped to, they always come as -1. Also, the "parent" comes as the header item.
I know the problem is that I have derived QAbstractItemModel for a model view of a QTreeView and also derived the QTreeView, adding my own mouse event handlers to generate a QDrag object, carrying the needed information to move/create new items in the QTreeView, and it only started to work when I switched to "application/x-qabstractitemmodeldatalist" mime type, encoding and decoding my data to it.
Although many sample code found here and there suggests that this mime type would also carry a location, I also could not manage to recover it, as far as I did not encoded it at first, but I don't think this is what I am looking for.
-
[quote author="frares" date="1342010749"]
Although much of the functionality is already working, on the tree model class, in the "dropMimeData" method, I don't get the "row" and "column" the data was dropped to, they always come as -1. Also, the "parent" comes as the header item.
[/quote]Do you set the Qt::ItemIsDropEnabled-flag in the flags()-method of your model for all Items that can be a drop target? If not, this may be the reason why you don't get row and column...
-
Thanks for your repply.
Yes, there is a Qt::ItemIsDropEnabled-flag in the flags()-method, there is the code:
@Qt::ItemFlags CTreeModel::flags(const QModelIndex & index) const {
if (index.isValid()) {
if (index.column() == 0) {
return Qt::ItemIsEditable |
Qt::ItemIsSelectable |
Qt::ItemIsEnabled |
Qt::ItemIsDragEnabled |
Qt::ItemIsDropEnabled ;
} else {
return Qt::ItemIsSelectable |
Qt::ItemIsEnabled |
Qt::ItemIsDragEnabled |
Qt::ItemIsDropEnabled ;
}
} else {
return Qt::ItemIsSelectable |
Qt::ItemIsEnabled |
Qt::ItemIsDropEnabled ;
}
}
@ -
Thanks again for your repply, here goes the code:
This goes in a custom QTreeView class:
@
void CTreeView::mousePressEvent ( QMouseEvent *event ) {
if (event->button() == Qt::LeftButton)
mDragStartPos = event->pos();
// event->accept();
// QTreeView::mousePressEvent(event);
}void CTreeView::mouseMoveEvent ( QMouseEvent * event ) {
if (event->buttons() == Qt::LeftButton &&
(mDragStartPos - event->pos()).manhattanLength() >=
QApplication::startDragDistance()) {
clearSelection();
QDrag * drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;QModelIndex index = indexAt(mDragStartPos);
CTreeItem * item = static_cast<CTreeItem*>(index.internalPointer());
if (item) {
qint8 toolType = item->data(5).toInt();
QString toolCode = item->data(8).toString();
QString toolIcon = item->data(4).toString();QByteArray mdata;
QDataStream stream(&mdata, QIODevice::WriteOnly);
QMap<int, QVariant> roleDataMap;
roleDataMap[0] = QVariant(toolType);
roleDataMap[1] = QVariant(toolCode);
stream << roleDataMap;
mimeData->setData(QString("application/x-qabstractitemmodeldatalist"),
mdata);drag->setPixmap(toolIcon);
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction | Qt::MoveAction | Qt::IgnoreAction,
Qt::MoveAction);
}
}
// event->accept();
// QTreeView::mouseMoveEvent(event);
}
@As you can see, I have tried to keep the QTreeView event processing for both cases. Also tried to ignore and to accept the events, with no noticeable effect.
This goes in a custom QAbstractItemModel, which is set as the model/view class of the previous one:
@
Qt::DropActions CTreeModel::supportedDropActions () const {
return Qt::CopyAction | Qt::MoveAction;
}bool CTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent) {if ( data->hasFormat("application/x-qabstractitemmodeldatalist") &&
( (action == Qt::MoveAction) || (action == Qt::CopyAction) ) ) {QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&encoded, QIODevice::ReadOnly);QMap<int, QVariant> roleDataMap;
while (!stream.atEnd()) {
stream >> roleDataMap;
}
mDroppedCode = roleDataMap[1].toString();if (parent.isValid()) {
QModelIndex index = this->index(row, column, parent);
CTreeItem * it = item(index);
int i = it->childCount();
i++;
}
return true;
} else {
return false;
}
}
@Thanks again.
Francisco