I've cooked up a QAbstractListModel
whose model indexes contain a pointer I absolutely needed in order to process data. I add the data like so:
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 );
}
It was only later that I realized that the argument to beginInsertRows
is asking for the parent model index of the new row, not the new row's actual model index.
So, at this point in time, Qt has given me no way of supplying a QModelIndex
to associate with this particular row. How do I create my own model index for this new row?
Okay, I'm rewriting my answer as after some research I've found out that I got it wrong.
You shouldn't do anything special to create a new index when you add new data. You code should look like this:
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();
Then you should implement the index()
method which will create indexes on demand and the parent()
method which will determine the parent of some index, but since you have a list model, it should probably always just return QModelIndex()
. Here is a good article about creating custom models.
Here is a complete example of a working 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())));
}
I've cooked up a QAbstractListModel whose model indexes contain a pointer I absolutely needed in order to process data.
If you start with wrong requirements, you end up with wrong solutions :)
A list model is simple enough so that you don't need more than the QModelIndex
's row()
to uniquely define the data the index addresses.
So, given a QModelIndex
mi
, when you before did
PointItem * item = static_cast<PointItem*>(mi.internalPointer());
you can instead do
PointItem * item = plm->pointItemFromIndex(mi);
where plm
is your PointListModel
. If you don't have a pointer to it lying around when you need to access the PointItem
, you can reconstruct it like this:
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
In turn, PointListMode::pointItemFromIndex()
would do the actual work:
PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
return mi.isValid() ? m_points[mi.row()] : 0 ;
}
This is the most important thing to realize when working with QAbstractListModel
in Qt: Mentally replace QModelIndex
with int row
, ignore everything else it has (an invalid QModelIndex
has row() == -1
).
Same for QAbstractTableModel
: mentally reduce the QModelIndex
to int row, int column
. Forget everything else.
The only time you need the full QModelIndex
(including its internalPointer()
or internalId()
is when you implement a tree model (QAbstractItemModel
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With