How to bind QModelIndex with a new line?

I have prepared a QAbstractListModel whose model indexes contain a pointer that I absolutely need to process the data. I am adding data like this:

 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 ); } 

Only then did I realize that the beginInsertRows argument beginInsertRows for the index of the parent newline model, not the index of the current actual row model.

So, at this point, Qt did not provide me with the ability to associate QModelIndex with this particular line. How to create your own model index for this new row?

+7
source share
2 answers

Well, I rewrite my answer, as after some research, which I found out that I was wrong.

You should not do anything special to create a new index when adding new data. You 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 must implement the index() method, which will create indexes on demand and the parent() method, which will determine the parent of an index, but since you have a list model, it should probably always just return QModelIndex() Here is a good article on 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()))); } 
+6
source

I prepared a QAbstractListModel, whose model indices contain a pointer that I absolutely need to process the data.

If you start with the wrong requirements, you get the wrong decisions :)

The list model is simple enough, so you don't need more than QModelIndex row() to uniquely identify data by index addresses.

So, considering QModelIndex mi , when did you do before

 PointItem * item = static_cast<PointItem*>(mi.internalPointer()); 

you can instead

 PointItem * item = plm->pointItemFromIndex(mi); 

where plm is your PointListModel . If you do not have a pointer to it, when you need to access PointItem , you can restore it as follows:

 PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model()); // check for !plm here (!mi.isValid() || qobject_cast fails) 

In turn, PointListMode::pointItemFromIndex() will 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 implement when working with QAbstractListModel in Qt: mentally replace QModelIndex with int row , ignore everything else that it has (invalid QModelIndex has row() == -1 ).

Same thing for QAbstractTableModel : mentally reduce QModelIndex to int row, int column . Forget the rest.

The only time you need a full QModelIndex (including its internalPointer() or internalId() ) when you implement the tree model ( QAbstractItemModel ).

+2
source

All Articles