ItemViews: don't delete dragged items when a subclass accepted the move
Amends 0f1008a593
, which introduced the
dropEventMoved private data member through which the drop-site itemview
can notify the drag-site that the drop handler has taken care of the move
operation.
However, if a subclass of an item view overrides dropEvent to move and
accept the event before calling the default implementation, then the flag
would not be set, as the dropOn helper would return false.
So QAbstractItemView still removed the item, resulting in two items
being removed when one was move-dropped.
Set the dropEventMoved member also when the QTreeWidget::dropEvent
handler is called by a subclass override and the event is already accepted.
This way, overrides don't have to artifically set the accepted action to
"IgnoreAction" to disable the handling in drag site.
[ChangeLog][QtWidgets][QAbstractItemView] Classes overriding dropEvent
for MoveAction events to move data can call accept() on the event before
calling the superclass to prevent QAbstractItemView from deleting the
source item.
Task-number: QTBUG-87057
Task-number: QTBUG-77427
Pick-to: 6.1
Change-Id: Ibe75fc1b2ca60627c825ad9b9b6d48953577edec
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
b3f9c2b3d1
commit
808a6dedcb
@ -921,7 +921,8 @@ void QListView::dropEvent(QDropEvent *event)
|
||||
bool topIndexDropped = false;
|
||||
int col = -1;
|
||||
int row = -1;
|
||||
if (d->dropOn(event, &row, &col, &topIndex)) {
|
||||
// check whether a subclass has already accepted the event, ie. moved the data
|
||||
if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
|
||||
const QList<QModelIndex> selIndexes = selectedIndexes();
|
||||
QList<QPersistentModelIndex> persIndexes;
|
||||
persIndexes.reserve(selIndexes.count());
|
||||
@ -940,23 +941,29 @@ void QListView::dropEvent(QDropEvent *event)
|
||||
QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
|
||||
|
||||
int r = row == -1 ? model()->rowCount() : (dropRow.row() >= 0 ? dropRow.row() : row);
|
||||
bool dataMoved = false;
|
||||
for (int i = 0; i < persIndexes.count(); ++i) {
|
||||
const QPersistentModelIndex &pIndex = persIndexes.at(i);
|
||||
if (r != pIndex.row()) {
|
||||
// try to move (preserves selection)
|
||||
d->dropEventMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
|
||||
if (!d->dropEventMoved) // can't move - abort and let QAbstractItemView handle this
|
||||
dataMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
|
||||
if (!dataMoved) // can't move - abort and let QAbstractItemView handle this
|
||||
break;
|
||||
} else {
|
||||
// move onto itself is blocked, don't delete anything
|
||||
d->dropEventMoved = true;
|
||||
dataMoved = true;
|
||||
}
|
||||
r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
|
||||
}
|
||||
if (d->dropEventMoved)
|
||||
event->accept(); // data moved, nothing to be done in QAbstractItemView::dropEvent
|
||||
if (dataMoved)
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
// either we or a subclass accepted the move event, so assume that the data was
|
||||
// moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
|
||||
if (event->isAccepted())
|
||||
d->dropEventMoved = true;
|
||||
}
|
||||
|
||||
if (!d->commonListView->filterDropEvent(event) || !d->dropEventMoved) {
|
||||
|
@ -2679,7 +2679,8 @@ void QTableWidget::dropEvent(QDropEvent *event) {
|
||||
QModelIndex topIndex;
|
||||
int col = -1;
|
||||
int row = -1;
|
||||
if (d->dropOn(event, &row, &col, &topIndex)) {
|
||||
// check whether a subclass has already accepted the event, ie. moved the data
|
||||
if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
|
||||
const QModelIndexList indexes = selectedIndexes();
|
||||
int top = INT_MAX;
|
||||
int left = INT_MAX;
|
||||
@ -2701,9 +2702,11 @@ void QTableWidget::dropEvent(QDropEvent *event) {
|
||||
}
|
||||
|
||||
event->accept();
|
||||
// Don't want QAbstractItemView to delete it because it was "moved" we already did it
|
||||
d->dropEventMoved = true;
|
||||
}
|
||||
// either we or a subclass accepted the move event, so assume that the data was
|
||||
// moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
|
||||
if (event->isAccepted())
|
||||
d->dropEventMoved = true;
|
||||
}
|
||||
|
||||
QTableView::dropEvent(event);
|
||||
|
@ -3340,7 +3340,8 @@ void QTreeWidget::dropEvent(QDropEvent *event) {
|
||||
QModelIndex topIndex;
|
||||
int col = -1;
|
||||
int row = -1;
|
||||
if (d->dropOn(event, &row, &col, &topIndex)) {
|
||||
// check whether a subclass has already accepted the event, ie. moved the data
|
||||
if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
|
||||
const QList<QModelIndex> idxs = selectedIndexes();
|
||||
QList<QPersistentModelIndex> indexes;
|
||||
const int indexesCount = idxs.count();
|
||||
@ -3387,9 +3388,11 @@ void QTreeWidget::dropEvent(QDropEvent *event) {
|
||||
}
|
||||
|
||||
event->accept();
|
||||
// Don't want QAbstractItemView to delete it because it was "moved" we already did it
|
||||
d->dropEventMoved = true;
|
||||
}
|
||||
// either we or a subclass accepted the move event, so assume that the data was
|
||||
// moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
|
||||
if (event->isAccepted())
|
||||
d->dropEventMoved = true;
|
||||
}
|
||||
|
||||
QTreeView::dropEvent(event);
|
||||
|
Loading…
Reference in New Issue
Block a user