¿Cómo asociar qmodelindex con una nueva fila?
-
25-10-2019 - |
Pregunta
He cocinado un QAbstractListModel
cuyos índices de modelo contienen un puntero que absolutamente necesitaba para procesar datos. Agrego los datos así:
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 );
}
Fue solo más tarde que me di cuenta de que el argumento a beginInsertRows
está pidiendo el padre Índice de modelo de la nueva fila, no el índice de modelo real de la nueva fila.
Entonces, en este momento, QT no me ha dado forma de suministrar un QModelIndex
asociar con esta fila en particular. ¿Cómo creo mi propio índice de modelo para esta nueva fila?
Solución
De acuerdo, estoy reescribiendo mi respuesta, ya que después de una investigación, descubrí que me equivocé.
No debe hacer nada especial para crear un nuevo índice cuando agregue nuevos datos. Tu código debería verse así:
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();
Entonces debe implementar el index()
método que creará índices a pedido y el parent()
Método que determinará al padre de algún índice, pero como tiene un modelo de lista, probablemente siempre debería volver QModelIndex()
. Aquí está Un buen artículo sobre la creación de modelos personalizados.
Aquí hay un ejemplo completo de un trabajo 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())));
}
Otros consejos
He cocinado un QABstractListModel cuyos índices de modelo contienen un puntero que absolutamente necesitaba para procesar datos.
Si comienza con requisitos incorrectos, termina con soluciones incorrectas :)
A lista El modelo es bastante simple para que no necesite más que el QModelIndex
's row()
Para definir de manera única los datos que aborda el índice.
Entonces, dado un QModelIndex
mi
, cuando antes lo hiciste
PointItem * item = static_cast<PointItem*>(mi.internalPointer());
en su lugar puede hacer
PointItem * item = plm->pointItemFromIndex(mi);
dónde plm
es tuyo PointListModel
. Si no tiene un puntero por ahí cuando necesite acceder al PointItem
, puedes reconstruirlo así:
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
Sucesivamente, PointListMode::pointItemFromIndex()
haría el trabajo real:
PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
return mi.isValid() ? m_points[mi.row()] : 0 ;
}
Esto es lo más importante para darse cuenta cuando se trabaja con QAbstractListModel
En Qt: reemplazar mentalmente QModelIndex
con int row
, ignora todo lo demás que tiene (un inválido QModelIndex
posee row() == -1
).
Igual por QAbstractTableModel
: Mentalmente reduce el QModelIndex
a int row, int column
. Olvida todo lo demás.
La única vez que necesitas la completa QModelIndex
(incluyendo su internalPointer()
o internalId()
es cuando implementa un modelo de árbol (QAbstractItemModel
).