Как связать QModelIndex с новой строкой? - PullRequest
7 голосов
/ 27 января 2011

Я приготовил 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 запрашивает модельный индекс parent новой строки, а неФактический модельный индекс новой строки.

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

Ответы [ 2 ]

6 голосов
/ 27 января 2011

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

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

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())));
}
2 голосов
/ 24 июня 2012

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

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

Модель

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

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

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).

...