Как связать QModelIndex с новой строкой?

Я приготовил QAbstractListModel чьи модельные индексы содержат указатель, который мне абсолютно необходим для обработки данных. Я добавляю данные так:

void PointListModel::addPoint(int frameNumber, QPoint const& pos)
{
    PointItem *pointItem = new PointItem( frameNumber, pos );
    QModelIndex newRow = this->createIndex( m_points.count(), 0, pointItem );

    qDebug() << newRow.internalPointer();

    beginInsertRows( newRow, m_points.count(), m_points.count() );
    m_points.insert( m_points.count( ), pointItem );
    endInsertRows();

    emit pointAdded( pointItem, pos );
}

Только позже я понял, что аргумент beginInsertRows запрашивает родительский модельный индекс новой строки, а не фактический модельный индекс новой строки.

Итак, на данный момент Qt не дал мне никакой возможности предоставить QModelIndex ассоциировать с этим конкретным рядом. Как мне создать свой собственный модельный индекс для этой новой строки?

2 ответа

Решение

Хорошо, я переписываю свой ответ, так как после некоторого исследования я обнаружил, что я понял это неправильно.

Вы не должны делать ничего особенного, чтобы создать новый индекс при добавлении новых данных. Ваш код должен выглядеть так:

PointItem *pointItem = new PointItem( frameNumber, pos );
// assume you insert a top level row, having no parent
beginInsertRows( QModelIndex(), m_points.count(), m_points.count() );
m_points.insert( m_points.count( ), pointItem );
endInsertRows();

Тогда вы должны реализовать index() метод, который будет создавать индексы по требованию и parent() метод, который будет определять родителя некоторого индекса, но поскольку у вас есть модель списка, он, вероятно, всегда должен просто возвращать QModelIndex(), Вот хорошая статья о создании пользовательских моделей.

Вот полный пример работы QAbstractListModel:

class MyModel: public QAbstractListModel {
  Q_OBJECT
  public:
    virtual QModelIndex index(int row, int column = 0,
        const QModelIndex &parent = QModelIndex()) const;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    void add(int i);
  private:
    QList<int> list;
};

void MyModel::add(int i)
{
  beginInsertRows(QModelIndex(), list.size(), list.size());
  list.append(i);
  endInsertRows();
}

QModelIndex MyModel::index(int row, int column,
        const QModelIndex &parent) const
{
  return hasIndex(row, column, parent) ? createIndex(row, column, (void*)&list[row])
    : QModelIndex();
}

int MyModel::rowCount(const QModelIndex &parent) const
{
  if (parent.isValid())
    return 0;
  return list.size();
}

QVariant MyModel::data(const QModelIndex &index,
    int role) const
{
  if (!index.isValid())
    return QVariant();
  if (role != Qt::DisplayRole)
    return QVariant();
  return QVariant(QString::number(*static_cast<int*>(index.internalPointer())));
}

Я подготовил QAbstractListModel, чьи модельные индексы содержат указатель, который мне абсолютно необходим для обработки данных.

Если вы начнете с неправильных требований, вы получите неправильные решения:)

Модель списка достаточно проста, так что вам не нужно больше, чем QModelIndex"s row() чтобы однозначно определить данные индекса адреса.

Итак, учитывая QModelIndexmiкогда ты раньше делал

PointItem * item = static_cast<PointItem*>(mi.internalPointer());

вы можете вместо этого сделать

PointItem * item = plm->pointItemFromIndex(mi);

где plm твой PointListModel, Если у вас нет указателя на него, когда вам нужно получить доступ к PointItem, вы можете восстановить это так:

PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)

В очереди, PointListMode::pointItemFromIndex() будет делать фактическую работу:

PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
    return mi.isValid() ? m_points[mi.row()] : 0 ;
}

Это самое важное, что нужно понимать при работе с QAbstractListModel в Qt: мысленно заменить QModelIndex с int row, игнорировать все остальное (недействительный QModelIndex имеет row() == -1).

То же самое для QAbstractTableModel: мысленно уменьшить QModelIndex в int row, int column, Забудь обо всем остальном.

Единственный раз, когда вам нужно полное QModelIndex (включая его internalPointer() или же internalId() когда вы реализуете модель дерева (QAbstractItemModel).

Другие вопросы по тегам