В одном из моих проектов мне нужно управлять списком элементов, порядок которых можно изменить с помощью перетаскивания.
Теперь все элементы имеют приоритет, который пользователь не может изменить. Существует ограничение на порядок элементов в списке, а именно то, что элементы с более низким приоритетом должны стоять первыми, но элементы с таким же приоритетом могут быть заменены местами.
Например, следующий список является нормальным:
(A,1),(B,1),(C,1),(D,2),(E,3)
тогда как следующее не работает:
(A,1),(B,1),(E,3),(D,2)
Следующий код показывает отправную точку моей проблемы:
#include <QApplication>
#include <QFrame>
#include <QHBoxLayout>
#include <QListView>
#include <QStandardItemModel>
QStandardItem* create(const QString& text, int priority) {
auto ret = new QStandardItem(text);
ret->setData(priority);
return ret;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto frame = new QFrame;
frame->setLayout(new QVBoxLayout);
auto view = new QListView;
frame->layout()->addWidget(view);
auto model = new QStandardItemModel;
view->setModel(model);
model->appendRow(create("1. A", 1));
model->appendRow(create("1. B", 1));
model->appendRow(create("2. X", 2));
model->appendRow(create("2. Y", 2));
model->appendRow(create("2. Z", 2));
view->setDragEnabled(true);
view->viewport()->setAcceptDrops(true);
view->setDropIndicatorShown(true);
view->setDragDropMode(QAbstractItemView::DragDropMode::InternalMove);
view->setDefaultDropAction(Qt::DropAction::MoveAction);
view->setDragDropOverwriteMode(false);
frame->show();
return a.exec();
}
Теперь DefaultDropAction
должен изменить контекст в зависимости от элемента, который будет перемещен, а также от элемента, в который он будет перемещен.
Если приоритеты двух элементов равны, то у меня есть MoveAction
. На случай, если приоритеты двух элементов различаются, у меня есть IgnoreAction
.
Можно ли добиться такого поведения без реализации my on QListView
и чего можно добиться, адаптировав пользовательский QAbstractItemModel
.
Возможным обходным путем может быть даже отказ от интерфейса перетаскивания и использование клавиш со стрелками вверх и вниз для перемещения элементов. Или даже более общее действие с операцией вырезания и вставки. Но я действительно предпочитаю придерживаться интерфейса перетаскивания.