Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.15.1
-
None
-
0f1008a5936c903ca9448193df7df6117e2c617b (qt/qtbase/dev) e356239397def8540ca2ec82274830a6c980a1a7 (qt/qtbase/5.15)
Description
With the following example running against Qt 5.15.1, moving items around via internal drag'n'drop loses the moved item. Running the same example against 5.15.0 does not. This regression was introduced in fd894fd68edf3d67975cda8eb9dda43646887b0d.
#include <QApplication> #include <QAbstractListModel> #include <QStringList> #include <QListView> class ListModel : public QAbstractListModel { public: ListModel(QObject * parent = nullptr) : QAbstractListModel {parent} , list {"A", "B", "C", "D"} { } protected: int rowCount(QModelIndex const& index = QModelIndex {}) const override { return index.isValid() ? 0 : list.size(); } QVariant data(QModelIndex const& index, int role) const override { QVariant result; if (Qt::DisplayRole == role) result = list[index.row()]; return result; } Qt::ItemFlags flags(QModelIndex const& index) const override { auto flags = QAbstractListModel::flags(index) | Qt::ItemIsDragEnabled; if (!index.isValid()) flags |= Qt::ItemIsDropEnabled; return flags; } bool setData(QModelIndex const& index, QVariant const& value, int role = Qt::EditRole) override { if (index.isValid() && index.row() < rowCount() && Qt::DisplayRole == role) { list[index.row ()] = value.toString(); Q_EMIT dataChanged(index, index, QVector<int> {role}); return true; } return false; } Qt::DropActions supportedDropActions() const override {return Qt::MoveAction;} bool insertRows(int row, int count, QModelIndex const& parent = QModelIndex {}) override { beginInsertRows(parent, row, row + count - 1); for (int i = 0; i < count; ++i) list.insert(row, {}); endInsertRows(); return true; } bool removeRows(int row, int count, QModelIndex const& parent = QModelIndex {}) override { beginRemoveRows(parent, row, row + count - 1); for (int index = 0; index < count; ++index) list.removeAt(row); endRemoveRows(); return true; } private: QStringList list; }; int main (int argc, char * argv[]) { QApplication controller {argc, argv}; ListModel model; QListView view; view.setModel (&model); view.setDragDropMode (QListView::InternalMove); view.show (); return controller.exec (); }
The problem is that dropEvent, which in 5.15.1 is implemented in QListView (rather than only QListWidget) to move rows around, only tries to move the rows via moveRows. If the model doesn't implement moveRows (ie returns false), then the event is nevertheless accepted.
In 5.15.0, the default dropEvent implementation in QAbstractItemView was used with an unaccepted event, which used QAbstractItemModel::dropMimeData rather than moveRows.
Attachments
Issue Links
- resulted from
-
QTBUG-83084 Wrong Selection After Drag Move in QListWidget
- Closed
- resulted in
-
QTBUG-100128 QListWidget/QListView: item widget disappears when item is dragged and dropped on itself
- Closed
For Gerrit Dashboard: QTBUG-87057 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
315789,3 | QAbstractItemView: Don't allow CopyAction for InternalMove views | dev | qt/qtbase | Status: MERGED | +2 | 0 |
315790,7 | QAbstractItemView: don't lose items if model only allows MoveAction | dev | qt/qtbase | Status: MERGED | +2 | 0 |
315992,2 | QAbstractItemView: Don't allow CopyAction for InternalMove views | 5.15 | qt/qtbase | Status: MERGED | +2 | 0 |
317840,2 | QAbstractItemView: don't lose items if model only allows MoveAction | 5.15 | qt/qtbase | Status: MERGED | +2 | 0 |
338469,2 | Delete invalid variable value | dev | qt/qtbase | Status: ABANDONED | -1 | 0 |
346276,6 | ItemViews: don't delete dragged items when a subclass accepted the move | dev | qt/qtbase | Status: MERGED | +2 | 0 |
346863,2 | ItemViews: don't delete dragged items when a subclass accepted the move | 6.1 | qt/qtbase | Status: MERGED | +2 | 0 |