Не могу разобраться в том, как работает drag & drop в qt-ишной model-view. Мне нужно реализовать перетаскивание между двумя view
(QTreeView) в которых находятся разные модели (но с данными одного типа). Элементы захватываются в одном view
и перетаскиваются во второй:
ui_->componentsView->setDragDropMode(
QAbstractItemView::DragDropMode::DragOnly);
ui_->componentsView->setDragEnabled(true);
ui_->devicesView->setDragDropMode(QAbstractItemView::DragDropMode::DropOnly);
ui_->devicesView->setAcceptDrops(true);
ui_->devicesView->setDropIndicatorShown(true);
При этоп "дропнуть" данные мы можем только в уже существующий элемент второй модели, данные в котором изменяться соответствующим образом:
bool DeviceModelAdapter::canDropMimeData(const QMimeData *data,
Qt::DropAction /*action*/,
int /*row*/,
int /*column*/,
const QModelIndex &parent) const {
if (auto mimeData = dynamic_cast<const NodeMimeData *>(data);
mimeData && parent.isValid()) {
return true;
}
return false;
}
QStringList DeviceModelAdapter::mimeTypes() const {
return {NodeMimeData::mimeType()};// перетаскиваемый тип, содержит
// указатели на некоторые объеты, которые добавятся к объетку, хранимому в модели
}
Qt::ItemFlags DeviceModelAdapter::flags(const QModelIndex &index) const {
if (index.isValid()) {
return ModelAdapter::flags(index) | Qt::ItemIsDropEnabled;
}
return {};
}
bool DeviceModelAdapter::dropMimeData(const QMimeData *data,
Qt::DropAction /*action*/,
int row,
int /*column*/,
const QModelIndex &parent) {
if (auto nodeData = dynamic_cast<const NodeMimeData *>(data);
nodeData && !parent.isValid()) {
auto curIndex = index(row, 0);
if (auto node = getNodeFromIndex(curIndex)) {
for (auto &i : nodeData->ptrList()) {
if (i) {
i->setParent(node);
}
}
}
emit dataChanged(curIndex, curIndex);
}
return false;
}
Однако при навелении курсора на элемент в модели (куда должен происходить drop) курсор показывает, что невозможно дропнуть данные. При этом если в методе canDropMimeData
меняю parent.isValid()
на !parentIsValid()
, а в методе flags
возвращаю при невалидном индексе Qt::ItemIsDropEnabled
, то курсор показывает, что перетаскивание возможно в любой части view, но только не в уже существующий элемент. Где я ошибся?
UDP потестив немного я понял, что drop на самом деле работает, а проблема заключается в другом (не в модели). Если при первом наведении во view мышь не попала на элемент, то метод canDropMimeData
вызывается только один раз и сколько мы не двигаем мышь - он вызываться не будет. Но если первый раз мы попали на элемент, то вызов происходит при каждом движении мыши. Извиняюсь если описал не понятно, потому что я и сам не понимаю, как такое вообще проиходит.
Собственно, в чем оказалась проблема: я использовал свой унаследованный от qmimedata класс, который не использовал метод setdata, в результате чего, при проверке dragenterevent не сходились типы моего mime и того, что может обрабатывать модель. Но! Несмотря на это, в этом случае (конкретно для dragenterevent), проверка на этом не заканчивается, а передаеться методу модели candropdata. Как результат - неожиданное (противоречивое) поведение программы.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Нужно запретить редактирование JTable, чтобы при нажатие на конкретную строку она только выделялась и можно было обработать слушателем это...
Не могу понять почему метод say(String something) не возвращает "Ты чё не знаешь, что рыбы не разговаривают?"
Пишу интеграционные тесты для сервисов с базой в памяти (h2)Сервисы не содержат никакой логики и просто вызывают аналогичные методы у ДАО