ДК
11 июля 2020 г. 17:51

Drug Drop problems

Drug & Drop, QMimeData, Qt, QSqlTableModel

Привет. Есть делегат QSqlTableModel, на основе которого сделал Drug Drop.
Проблема в том, что перетаскивание работает корректно только тогда, когда я отображаю первую колонку - ID, если её скрыть, то поля съезжают и вместо перенесения строки отрабатывает вставка пустой, а копируемые данные меняются полями, иногда строку переносит нормально, но поля съезжают всё-равно.
Вот я и разбираюсь теперь в отладчике. Возникают вопросы, ответы на которые не нашел:
1)QMimeData копирует только отображенную информацию или также и из скрытых колонок? Просто в отладчике, что вижу: если отображенные поля есть все,
то имею все данные отображенных полей, данные одного скрытого, а еще данные от 2 скрытых нет.
Конкретно про колонку с ID, если я отображаю колонку с ID, то вижу, что данные с неё заносятся в QMimeData, если скрываю её, то этот ID в QMimeData не заносится.
2)Где можно почитать про ВСЕ форматы данных для QMimeData?
Я использую "application/x-qabstractitemmodeldatalist", а какие еще есть? Просто в доке такого формата вообще не нашел, а именно с ним работает.

Сам делегат:

  1. SqlTableModelDrAndDr::SqlTableModelDrAndDr(QObject *parent, QSqlDatabase db) :
  2. QSqlTableModel(parent, db)
  3. {
  4. }
  5.  
  6. Qt::DropActions SqlTableModelDrAndDr::supportedDropActions() const
  7. {
  8. return Qt::CopyAction | Qt::MoveAction;
  9. }
  10.  
  11. Qt::ItemFlags SqlTableModelDrAndDr::flags(const QModelIndex &index) const
  12. {
  13. Qt::ItemFlags defaultFlags = QSqlTableModel::flags(index);
  14.  
  15. if (index.isValid())
  16. return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
  17. else
  18. return Qt::ItemIsDropEnabled | defaultFlags;
  19. }
  20.  
  21. QMimeData *SqlTableModelDrAndDr::mimeData(const QModelIndexList &indexes) const
  22. {
  23. QMimeData *mimeData = new QMimeData();
  24. QByteArray encodedData;
  25.  
  26. QDataStream stream(&encodedData, QIODevice::WriteOnly);
  27.  
  28. stream << indexes[0].row();
  29.  
  30. foreach (const QModelIndex &index, indexes) {
  31. if (index.isValid()) {
  32. QString text = data(index, Qt::DisplayRole).toString();
  33. stream << text;
  34. }
  35. }
  36.  
  37. mimeData->setData("application/x-qabstractitemmodeldatalist", encodedData);
  38. return mimeData;
  39. }
  40.  
  41. bool SqlTableModelDrAndDr::canDropMimeData(const QMimeData *data,
  42. Qt::DropAction action, int row, int column, const QModelIndex &parent) const
  43. {
  44. Q_UNUSED(action)
  45. Q_UNUSED(row)
  46. Q_UNUSED(column)
  47. Q_UNUSED(parent)
  48.  
  49. if (!data->hasFormat("application/x-qabstractitemmodeldatalist"))
  50. return false;
  51.  
  52. return true;
  53. }
  54.  
  55. bool SqlTableModelDrAndDr::dropMimeData(const QMimeData *data,
  56. Qt::DropAction action, int row, int column, const QModelIndex &parent)
  57. {
  58. if (!canDropMimeData(data, action, row, column, parent))
  59. return false;
  60.  
  61. if (action == Qt::IgnoreAction)
  62. return true;
  63.  
  64. int beginRow;
  65.  
  66. if (row != -1)
  67. beginRow = row;
  68. else if (parent.isValid())
  69. beginRow = parent.row();
  70. else
  71. beginRow = rowCount(QModelIndex());
  72.  
  73. QByteArray encodedData = data->data("application/x-qabstractitemmodeldatalist");
  74. QDataStream stream(&encodedData, QIODevice::ReadOnly);
  75. QStringList newItems;
  76.  
  77. int r;
  78. stream >> r;
  79.  
  80. while (!stream.atEnd()) {
  81. QString text;
  82. stream >> text;
  83. newItems << text;
  84. }
  85.  
  86. removeRow(r, QModelIndex());
  87. submitAll();
  88. if (beginRow > r)
  89. --beginRow;
  90.  
  91. _finishRow = beginRow;
  92. insertRow(beginRow, QModelIndex());
  93. int i = 0;
  94. foreach (const QString &text, newItems) {
  95. QModelIndex idx = index(beginRow, i++, QModelIndex());
  96. setData(idx, text);
  97. }
  98.  
  99. return true;
  100. }

Настройки вью и модели:

  1. _reportsSQL->setSort(ReportDataBase::WEIGHT, Qt::SortOrder::AscendingOrder);
  2. ui->_reportsTableView->setEditTriggers(QTableView::NoEditTriggers);
  3. ui->_reportsTableView->setModel(_reportsSQL);
  4. /*
  5. * Установказа заголовков
  6. * */
  7. for (int i = 0, j = 0; i < _reportsSQL->columnCount(); ++i, ++j)
  8. {
  9. _reportsSQL->setHeaderData(i, Qt::Horizontal, REPORTDATABASE->header(j).toUpper());
  10. }
  11.  
  12. if(!_roles.contains(Models::UserRole::ROLES::ADMIN))
  13. ui->_reportsTableView->setColumnHidden(ReportDataBase::PATH, true);
  14. ui->_reportsTableView->setColumnHidden(ReportDataBase::ID,true);
  15. ui->_reportsTableView->setColumnHidden(ReportDataBase::SERVER_ID,true);
  16. ui->_reportsTableView->setColumnHidden(ReportDataBase::LAB_ID,true);
  17. ui->_reportsTableView->setColumnHidden(ReportDataBase::WEIGHT, true);
  18. ui->_reportsTableView->setItemDelegateForColumn(ReportDataBase::PATH, pathDelegate);
  19. ui->_reportsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
  20. ui->_reportsTableView->setSelectionMode(QAbstractItemView::SingleSelection);
  21. ui->_reportsTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
  22. ui->_reportsTableView->horizontalHeader()->setStretchLastSection(true);
  23. ui->_reportsTableView->horizontalHeader()->moveSection(ReportDataBase::PATH, ReportDataBase::DESCRIPTION);
  24. ui->_reportsTableView->verticalHeader()->hide();
  25.  
  26. /*
  27. * For drag and drop
  28. * */
  29. ui->_reportsTableView->setDragDropMode(QAbstractItemView::DragDropMode::InternalMove);
  30. ui->_reportsTableView->setDragEnabled(true);
  31. ui->_reportsTableView->setAcceptDrops(true);
  32. ui->_reportsTableView->setDropIndicatorShown(true);
  33. ui->_reportsTableView->viewport()->setAcceptDrops(true);
  34. ui->_reportsTableView->setDefaultDropAction(Qt::MoveAction);
  35. ui->_reportsTableView->setDragDropOverwriteMode(false);
  36. _reportsSQL->setEditStrategy(QSqlTableModel::OnManualSubmit);

В классе, управляющим QSqlDatabase, поля установлены верно, если бы это было не так, то, навреное, и на вью информация отображалась не в правильных колонках.

2

Вам это нравится? Поделитесь в социальных сетях!

4
Evgenii Legotckoi
  • 13 июля 2020 г. 13:49

Добрый день.
mime data можно именовать как заблагоросудится. Просто есть стандартные типы данных, а есть кастомные. То есть разработчики сами решают как их называть.
Копирование со всех колонок скорее всего происходит из-за того, что у вас настроено построчное выделение.
По идее копировать должно только видимые поля, хотя при желании можно и переписать поведение. Но если учесть описание проблемы с первой колонкой и приложенный код, то становится ясно, что это ожидаемое поведение

В этом коде по логике забирается первая строка из QMimeData, если колонка скрыта, то естественно, что данные могут интерпретироваться как угодно. Может оказаться нужная строка, а может быть мусор.

  1. int r;
  2. stream >> r;

Так что тут нужно продумывать логику и решать, что конкретно вам нужно.

    ДК
    • 13 июля 2020 г. 14:58

    Доброе утро! спасибо за ответ! а как настраивается поведение, чтобы копировались все поля всегда? тогда и проблем не будет со скрытыми колонками. Я имею ввиду в делегате что-то переделывать с data надо или просто есть какой-то флаг под эту задачу?

      Evgenii Legotckoi
      • 13 июля 2020 г. 15:14
      • Ответ был помечен как решение.

      Я думаю, что вам этот метод нужно переписывать

      1. QMimeData *SqlTableModelDrAndDr::mimeData(const QModelIndexList &indexes) const

      То есть доделывать недостающие индексы, например, и по ним забирать данные.

        ДК
        • 13 июля 2020 г. 17:43

        благодорю!

          Комментарии

          Только авторизованные пользователи могут публиковать комментарии.
          Пожалуйста, авторизуйтесь или зарегистрируйтесь