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?

¿Fue útil?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top