Как связать 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()
чтобы однозначно определить данные индекса адреса.
Итак, учитывая 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
).