PDA

View Full Version : Refuse from removing row in Model after unsuccessful drop



Miga
5th July 2012, 13:37
Hello!
Win7, Qt 4.8.
I use Model/View based on QStandardItemModel and QTreeView. Some items are not allowed to get dropped items. When I try to drop into them, they don't get the dropped item (as they should), but the source item is removed after the failed drop attempt.
The same situation is described here (http://www.qtcentre.org/threads/47868-Drag-Drop-problem-with-model-views). Is it really a bug?
I tried to reimplement dropMimeData, f.e:

bool TMyModel::dropMimeData(const QMimeData * apData, Qt::DropAction aAction, int aRow, int aColumn, const QModelIndex & aParent)
{
if (/*some condition*/)
return QAbstractItemModel::dropMimeData ( apData, Qt::IgnoreAction, aRow, aColumn, aParent );
return QAbstractItemModel::dropMimeData ( apData, aAction, aRow, aColumn, aParent );
}
or so

bool TMyModel::dropMimeData(const QMimeData * apData, Qt::DropAction aAction, int aRow, int aColumn, const QModelIndex & aParent)
{
if (/*some condition*/)
return false;
return QAbstractItemModel::dropMimeData ( apData, aAction, aRow, aColumn, aParent );
}
RemoveRows is called in all cases and the dragged item disappears. Could I avoid the calling of removeRows?

Thanks for any help.

high_flyer
5th July 2012, 15:37
Can you show the implementation of your Dragging operation? (at the source object)

Miga
6th July 2012, 08:03
Thanks for reply.
Maybe the problem is here and I should reimplement some other functions? F.e., supportedDragActions? I try to reimplement only dropMimeData. (Also 'data' and 'setData' but I think they are not important here)

high_flyer
6th July 2012, 10:40
What to do with the dragged data on the source side has to be implemented on the soruce side - where the drag begins, and where the drop result returns.

Miga
6th July 2012, 13:25
It becomes a little bit clearer.
Really 'removeRows' is called in QAbstractItemView::startDrag in such a way:

if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
d->clearOrRemove();
But I can't understand how to get out of it. Should I reimplement 'startDrag' at all or is it possible to avoid calling 'clearOrRemove' by some other tricks?

high_flyer
9th July 2012, 10:02
I think you are over complicating all of this.
Simply call ignore on your dragEnter event when the mime type of your drag should be ignored.

Miga
11th July 2012, 11:53
There are no certain mime types to ignore. The necessity to ignore drop depends on the drop position. F.e., I don't want to drop items in the second column in the tree.
Well, I did the following:

TMyModel : public QStandardItemModel
public:
void setErrorFlag(bool);
bool getErrorFlag();

private:
bool ErrorFlag;


bool TMyModel::dropMimeData(const QMimeData * pData, Qt::DropAction Action, int Row, int Column, const QModelIndex & Parent)
{
if (/*some_error_condition*/)
{
setErrorFlag(true);
return false;
}
setErrorFlag(false);
return QAbstractItemModel::dropMimeData ( pData, Action, Row, Column, Parent );}


void TMyTreeView::dropEvent ( QDropEvent * pEvent )
{
QTreeView::dropEvent(aEvent);

// this cancels removeRows
TMyModel *pModel = dynamic_cast<TMyModel *>(model());
if (pModel != NULL)
{
if (pModel->getErrorFlag())
{
pEvent->setDropAction(Qt::IgnoreAction);
}
}
}

It works. But such a decision seems to be unobvious...