QAbstractItemModel beginInsertRow, reenumerate other rows?
-
Hi
I have question:
I'm adding data to QAbstractItemModel that was previously set. I havestruct DevPlaceDataStruct { int row; int dev_id; QString text; };
and of course
private: QMap<int,DevPlaceDataStruct*> modelMap;
Model is indexed in modelMap by (int)row. So if I add a new row, I need to reenumerate the rest of rows, right?
beginInsertRows only notifies the model about the change?
So in consequence I need to change modelMap from the row position I'm inserting to the end ?best,
Marek -
Why not simply use a QVector<DevPlaceDataStruct*> instead? Then use the index as row and all works without additional stuff.
-
@Christian-Ehrlicher actually... I haven't thought about this earlier, because every subclass of QAbstractListModel I have seen used QMap not QVector but yes it should work.
Thanks,
Marek -
@Marek can you marked this as solved if @Christian-Ehrlicher's answer solves the issue for you? Thanks.
-
Hi
Actually I have problem with both methods QVector and QMap it gives me the same result.
Problem is when I remove row=0 and then I add item which should go into row=0.
Result is that I have in view: Item1, Item2, black space, item3.
When I add row in the middle or at the end it is OK.
When I'm checking debug it looks like it should work, row is correct, model count is correctDevPlaceModel::removeRow dev_id: 74 row: 0 count: 2 DevPlaceModel::addRow dev_id: 74 place_number: 1 row: 0 count: 3
I have attached cpp, h and qml file.
Cpp and h has commented out version with QMap, so it works with QVector, but both methods have a problem with row=0.
At the beginning I'm settings model from another class by calling
beginSetModel();
addPlace(int dev_id,int place_number);
endSetModel();When model is set I'm using
addRow(int dev_id,int place_number);
removeRow(int dev_id);Can someone shed some light?
Best,
Marek#include <QtCore> #include <QAbstractListModel> #include <QtXml/QDomNode> #include <QtXml/QDomElement> #include <QGeoCoordinate> #include <QGeoRectangle> #include "helper.h" struct DevPlaceDataStruct { int row; int dev_id; int place_number; QString text; }; class DevPlaceModel : public QAbstractListModel { Q_OBJECT public: enum ItemRoles { IdRole = Qt::UserRole + 1, TextRole = Qt::UserRole + 2, RowRole = Qt::UserRole + 3, }; DevPlaceModel(QObject *parent); virtual int rowCount(const QModelIndex&) const { return vector.count(); } // virtual int rowCount(const QModelIndex&) const { return modelMap.count(); } virtual QVariant data(const QModelIndex &index, int role) const; QHash<int, QByteArray> roleNames() const; Q_INVOKABLE int getRow(int dev_id); Q_INVOKABLE int getDevId(int row); public slots: void beginSetModel(); void addPlace(int dev_id,int place_number); void addRow(int dev_id,int place_number); void removeRow(int dev_id); void endSetModel(); signals: private slots: QVariant getRoleData(int role,int row) const; private: QVector<DevPlaceDataStruct*> vector; // QMap<int,DevPlaceDataStruct*> modelMap; QHash<int, QByteArray> roles; int curr_dev_id; };
#include "dev-place-model.h" DevPlaceModel::DevPlaceModel(QObject *parent):QAbstractListModel(parent) { roles[IdRole] = "id_role"; roles[TextRole]= "text_role"; roles[RowRole]= "row_role"; curr_dev_id=0; } QHash<int, QByteArray> DevPlaceModel::roleNames() const { return roles; } QVariant DevPlaceModel::data(const QModelIndex &index, int role) const { if(!index.isValid()) { return QVariant(); } if(roles.contains(role) && vector.count()-1>=index.row()) { return getRoleData(role,index.row()); } // if(roles.contains(role) && modelMap.contains(index.row())) { // return getRoleData(role,index.row()); // } return QVariant(); } QVariant DevPlaceModel::getRoleData(int role, int row) const { DevPlaceDataStruct *p=vector.at(row); // DevPlaceDataStruct *p=modelMap[row]; switch(role) { case IdRole: return QVariant(p->dev_id); case TextRole: return QVariant(p->text); case RowRole: // return QVariant(p->row); return QVariant(row); default: qWarning()<<"DevPlaceModel::getRoleData there is no role:"<<role; } } void DevPlaceModel::beginSetModel() { beginResetModel(); for(int i=0;i<vector.count();i++) { delete vector.at(i); } vector.clear(); // beginResetModel(); // if(modelMap.count()) { // QMapIterator<int,DevPlaceDataStruct*> i(modelMap); // while(i.hasNext()) { // i.next(); // delete i.value(); // } // modelMap.clear(); // } } void DevPlaceModel::addPlace(int dev_id, int place_number) { qDebug()<<"DevPlaceModel::addPlace dev_id:"<<dev_id<<" place_number:"<<place_number; DevPlaceDataStruct *p=new DevPlaceDataStruct; p->dev_id=dev_id; p->text=QString("Miejsce: %1").arg(place_number); p->place_number=place_number; vector.append(p); // p->row=modelMap.count(); // modelMap.insert(p->row,p); } void DevPlaceModel::endSetModel() { emit endResetModel(); } void DevPlaceModel::addRow(int dev_id, int place_number) { int row=-1; for(int i=0;i<vector.count();i++) { DevPlaceDataStruct *d=vector.at(i); if(d->place_number>=place_number) { row=((i-1)<0 ? 0 : i-1); break; } } if(row==-1) { row=vector.count(); } DevPlaceDataStruct *em=new DevPlaceDataStruct; em->dev_id=dev_id; em->text=QString("Miejsce: %1").arg(place_number); em->place_number=place_number; emit beginInsertRows(QModelIndex(),row,row); vector.insert(row,em); emit endInsertRows(); qDebug()<<"DevPlaceModel::addRow dev_id:"<<dev_id<<" place_number:"<<place_number<<" row:"<<row<<" count:"<<vector.count(); // int row=-1; // bool found=false; // int new_idx=0; // QMap<int,DevPlaceDataStruct*> new_modelMap; // QMapIterator<int,DevPlaceDataStruct*> i(modelMap); // while(i.hasNext()) { // i.next(); // if(!found && i.value()->place_number>=place_number) { // row=((i.value()->row-1)<0 ? 0 : i.value()->row-1); // found=true; // new_idx++; // } // i.value()->row==new_idx; // new_modelMap.insert(new_idx,i.value()); // new_idx++; // } // if(row==-1) { // row=modelMap.count(); // } // DevPlaceDataStruct *em=new DevPlaceDataStruct; // em->dev_id=dev_id; // em->text=QString("Miejsce: %1").arg(place_number); // em->place_number=place_number; // em->row=row; // emit beginInsertRows(QModelIndex(),row,row); // new_modelMap.insert(em->row,em); // modelMap.clear(); // modelMap=new_modelMap; // emit endInsertRows(); // qDebug()<<"DevPlaceModel::addRow dev_id:"<<dev_id<<" place_number:"<<place_number<<" row:"<<row<<" count:"<<modelMap.count(); } void DevPlaceModel::removeRow(int dev_id) { int row=-1; for(int i=0;i<vector.count();i++) { DevPlaceDataStruct *d=vector.at(i); if(d->dev_id==dev_id) { row=i; break; } } if(row>=0) { beginRemoveRows(QModelIndex(),row,row); delete vector.at(row); vector.remove(row); endRemoveRows(); } qDebug()<<"DevPlaceModel::removeRow dev_id:"<<dev_id<<" row:"<<row<<" count:"<<vector.count(); // int row=-1; // int new_idx=0; // QMap<int,DevPlaceDataStruct*> new_modelMap; // QMapIterator<int,DevPlaceDataStruct*> i(modelMap); // while(i.hasNext()) { // i.next(); // if(i.value()->dev_id==dev_id) { // row=i.key(); // } // else { // i.value()->row=new_idx; // new_modelMap.insert(new_idx,i.value()); // new_idx++; // } // } // if(row<0) { // qWarning()<<"DevPlaceModel::removeRow no row:"<<row; // return; // } // beginRemoveRows(QModelIndex(),row,row); // delete modelMap[row]; // modelMap.clear(); // modelMap=new_modelMap; // endRemoveRows(); // qDebug()<<"DevPlaceModel::removeRow dev_id:"<<dev_id<<" row:"<<row<<" count:"<<modelMap.count(); } int DevPlaceModel::getRow(int dev_id) { for(int i=0;i<vector.count();i++) { DevPlaceDataStruct *d=vector.at(i); if(d->dev_id==dev_id) return i; } return -1; // QMapIterator<int,DevPlaceDataStruct*> i(modelMap); // while(i.hasNext()) { // i.next(); // if(i.value()->dev_id==dev_id) // return i.value()->row; // } // return 0; } int DevPlaceModel::getDevId(int row) { if(vector.count()-1>=row) { qWarning()<<"DevPlaceModel::getDevId there is no row:"<<row; return 0; } return vector.at(row)->dev_id; // if(!modelMap.contains(row)) { // qWarning()<<"DevPlaceModel::getDevId there is no row:"<<row; // return 0; // } // return modelMap[row]->dev_id; }
QControls2.ComboBox { id:placeCombo anchors.top:addressText.bottom anchors.horizontalCenter: parent.horizontalCenter width:parent.width*0.6 height:parent.height*0.15 model: DevPlaceModel textRole:"text_role" // currentIndex:DevPlaceModel.getRow(root.dev_id) }
-
@Marek
Two observations:-
It does not actually matter, but why does your
beginSetModel()
callbeginResetModel();
directly whileendSetModel()
does anemit endResetModel();
? -
Your
addRow()
'srow=((i-1)<0 ? 0 : i-1);
returns 0 for all 3row == -1
androw == 0
androw == 1
. Is that related to your problem?
-
-
- My mistake shold call endResetModel
- This is correct I think, It is in loop from i=0 to vector.count. So when I have items (2,3) in vector and I'm adding item 1, it will go to row=0
When I have items 1,3 and I'm adding item 2 it will go to row=1
Right?
-
@JonB IMHO model is OK, when I remove and then add item 1 (I have 1,2,3) from debug I have:
DevPlaceModel::removeRow dev_id: 74 row: 0 count: 2 DevPlaceModel::addRow dev_id: 74 place_number: 1 row: 0 count: 3 vector: QVector(0x5636891742c0, 0x56368c2e0a90, 0x56368c23d700)
So view should have 3 items, instead there is like in image (
-