QTableView - как узнать, какие элементы выбраны в отсортированной таблице? - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть QTableView table. Данные для таблицы предоставляются как QStandardItemModel model, но данные могут быть отсортированы по QSortFilterProxyModel. То есть:

auto *header = ui.table->horizontalHeader();
// ... some configuration of header
auto *sorted = new QSortFilterProxyModel(window);
QObject::connect(header, &QHeaderView::sortIndicatorChanged, sorted, &QSortFilterProxyModel::sort);
sorted->setSourceModel(model);
ui.table->setModel(sorted);

Все элементы, которые я вставляю в таблицу, QStandardItem, добавлены так:

QStandardItem* item = new QStandardItem("some data");
model->appendRow({item});

Теперь, когда пользователь выбирает строки, я хотел бы знать, какие QStandardItems выбраны. Я пытался так:

QObject::connect(ui.table->selectionModel(), &QItemSelectionModel::selectionChanged, this,
                 [this](const QItemSelection &selected, const QItemSelection &deselected) {
    QModelIndexList selectedIdxs = selected.indexes();
    for(QModelIndex &idx : selectedIdxs) {
        QStandardItem* item = model->item(idx.row());
        //'item' is what I need, do something with it
    }
});

Сначала все работало нормально. Однако, как только я отсортировал массив, я понял, что индексы строк не там, где они должны быть! Если элемент после сортировки является первым, idx.row(), кажется, возвращает 0, но model ничего не знает о сортировке.

Итак, мой вопрос, как перевести отсортированные индексы в исходные? Я надеялся найти аналогичную функцию, возвращающую QStandardItem* как QSortFilterProxyModel::item - но ее там нет.

Или, может быть, есть более стандартный способ сделать это, без индексов строк вообще?

Ответы [ 2 ]

1 голос
/ 19 апреля 2020

Если вы считаете код в своей лямбде ...

[this](const QItemSelection &selected, const QItemSelection &deselected)
  {
    QModelIndexList selectedIdxs = selected.indexes();
    for (QModelIndex &idx: selectedIdxs) {
      QStandardItem *item = model->item(idx.row());
      //'item' is what I need, do something with it
    }
  }

Проблема в том, что QModelIndex idx связан с QSortFilterProxyModel, а не QStandardItemModel. В этом случае вам нужно использовать QSortFilterProxyModel::mapToSource для сопоставления idx с соответствующим QModelIndex в QStandardItemModel. Предполагая, что содержащий класс имеет QSortFilterProxyModel * член данных с именем sorted, код станет ...

[this](const QItemSelection &selected, const QItemSelection &deselected)
  {
    QModelIndexList selectedIdxs = selected.indexes();
    for (QModelIndex &idx: selectedIdxs) {
      auto source_idx = sorted->mapToSource(idx);
      QStandardItem *item = model->item(source_idx.row());
      //'item' is what I need, do something with it
    }
  }

В дополнение к вышесказанному вы можете написать функцию, которая итеративно отображает индекс модели до связанной модели. больше не модель прокси. Что-то вроде (не проверено) ...

QModelIndex map_to_source (QModelIndex index)
{
  const auto *model = index.model();
  for (const auto *pm = dynamic_cast<const QAbstractProxyModel *>(model); pm;
       pm = dynamic_cast<const QAbstractProxyModel *>(model)) {
    index = pm->mapToSource(index);
    model = pm->sourceModel();
  }
  return index;
}
0 голосов
/ 19 апреля 2020

Вы можете сохранить эти индексы в виде списка QPersistentModelIndex .

QPersistentModelIndex - это модельный индекс, который может быть сохранен приложением, а затем использован для доступа к информации в модель. В отличие от класса QModelIndex, безопасно хранить QPersistentModelIndex, так как модель гарантирует, что ссылки на элементы будут оставаться действительными до тех пор, пока они могут быть доступны для модели.

Поскольку вы используете QSortFilterProxyModel, вы также можете использовать QSortFilterProxyModel::mapToSource() для хранения фактических элементов исходной модели, они не должны быть признаны недействительными при сортировке прокси-модели. Затем вы можете выполнить обратное действие и получить прокси-элементы через QSortFilterProxyModel::mapFromSource позже, когда вам нужно будет выполнить операции с ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...