SetData or reading from new row crashes
-
I have a model called modelBox which is in a QTableView using the QStandardItemModel.
If I insert a row withmodelBox->insertRow(0);
Then use setData it crashes.
modelBox->setData(modelBox->index(0, 1),"test");
If I take a line that is already in the database and read from it, it is fine, but if I read from the new line it also crashes.
eg usingQString boxID = modelBox->item(index.row(),0)->text(); QString boxName = modelBox->item(index.row(),1)->text(); QString boxLocation = modelBox->item(index.row(),2)->text();
Both setData and reading work on a line that is already in the database, but when I add a new row, and try to read or write to it, it crashes straight away.
-
Hi,
Please provide a stack trace.
-
I have just found out that it wasn't setData crashing, but reading from the line. I thought it was crashing because I was reading from a null row, so I thought that adding data before reading it would stop it crashing, but it doesn't.
Stupid thing is that it shouldn't crash until I edit the line and hit enter, because the signal shouldn't fire until I hit enter, but it crashes on creating the new line. eg I use this function to add the row.
void DbManager::addRowBox(){ qDebug() << "Add"; modelBox->insertRow(0); }
The following code should read the line, and after the enter key is pressed the signal is fired.
void DbManager::updateBoxList(const QModelIndex &topLeft, const QModelIndex &buttomRight){ qDebug() << "index: " << topLeft.row(); QString boxID = modelBox->item(topLeft.row(),0)->text(); QString boxName = modelBox->item(topLeft.row(),1)->text(); QString boxLocation = modelBox->item(topLeft.row(),2)->text(); if(boxID==""){ qDebug() << "insert"; }else{ qDebug() << "update"; } }
The idea being if id is empty then I have to insert into the sqlite database, and if an id exists it would update the database from the id value.
Now the code works fine if I click on a line that is in the database, but if I add a new line, it crashes.
What I don't understand is that it crashes before the signal is fired. eg as soon as I add the new line.
If I comment out the QString lines then it doesn't crash on adding the new line, and lets me edit the new line and press enter.So why is it crashing, and more importantly why is it crashing before the signal is fired.
I have googled and googled and I can't find out how to do a stack trace in QT. I haven't been using it very long at all, so I am new to it.
PS. Just a thought. Perhaps when I add a new line it is firing the signal because a new line is causing dataChanged to fire, but perhaps it is crashing because the line hasn't been created before my QStrings try to grab the data from the line.
I am right. dataChanged is firing when I add the new line before I have done any editing. Surely dataChanged should only fire on data changing. So this is why the program is crashing.
-
Silly question: did you initialise modelBox ?
-
@SGaist
Yes my modelBox is initialized in my headerpublic: QStandardItemModel *modelBox;
And I have a function which loads my sqlite data in.
I do know what the problem is now, but not how to solve it.
I am using the dataChanged signal to run my code when a table row is changed. egQObject::connect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList);
The signal works fine and calls my code when I edit a row and hit enter.
The problem is this which I have just discovered. The dataChanged signal is firing when I do this
void DbManager::addRowBox(){ qDebug() << "Add"; modelBox->insertRow(0); }
So what is happening my code is being called before I have edited the line which is causing the crash.
First of all I don't know why the signal is firing when I add a row, and I am not sure what to do instead.
-
No it's not.
modelBox
is just declared in your header, which means that you are trying to use an invalid pointer hence your crash. -
I said my model is setup in a function. I declare it in the header so I can use it in all functions in my class. The problem is that the dataChanged signal is firing when I insert a row. It should only fire when data is changed, and not when I add a row. My actual code for setting up the model is here.
void DbManager::boxList(){ QSqlQuery query; query.prepare("select `boxID`,`boxName`,`boxLocation` from `boxes`"); query.exec(); modelBox= new QStandardItemModel(sqlSize(query), 3); int i=0; while (query.next()) { modelBox->setData(modelBox->index(i, 0), query.value("boxID")); modelBox->setData(modelBox->index(i, 1), query.value("boxName")); modelBox->setData(modelBox->index(i, 2), query.value("boxLocation")); i++; } modelBox->setHeaderData(1, Qt::Horizontal, QObject::tr("Box ID / Name")); modelBox->setHeaderData(2, Qt::Horizontal, QObject::tr("Box Location")); QObject::connect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList); }
The model is working fine. If I click on a table row I can edit it no problem. It is only when I insert a new row it is not working, and that is because dataChanged is firing when I insert the row, instead of firing when I click enter after changing the row. If I edit an existing row dataChange fires when it should.
-
I have a solution, but I don't know if it is the best solution as of yet.
Because the crash was being caused by the signal being fired when I added a new row, my solution was to disconnect the signal when I add a new row., and re-connect the signal afterwards egvoid DbManager::addRowBox(){ qDebug() << "Add"; disconnect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList); modelBox->insertRow(0); QObject::connect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList); }
That let me edit the row, which was great, but it was still crashing when I hit the enter key. You see when you run the following lines and any of the columns are null data it will crash.
QString boxID = modelBox->item(topLeft.row(),0)->text(); QString boxName = modelBox->item(topLeft.row(),1)->text(); QString boxLocation = modelBox->item(topLeft.row(),2)->text();
So the answer was this. I add dummy data. For the id column I will add the text "Add". It doesn't matter what I put in this column because on an insert an id is not needed. I will just use this to check if the data needs to be inserted or updated.
So here is the solution
void DbManager::addRowBox(){ qDebug() << "Add"; disconnect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList); modelBox->insertRow(0); modelBox->setData(modelBox->index(0, 0),"add"); modelBox->setData(modelBox->index(0, 1),""); modelBox->setData(modelBox->index(0, 2),""); QObject::connect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList); }
So the solution is in two parts. The first part is to disconnect the dataChanged signal. Then add the row, and then add dummy data. Then the dummy data will stop it crashing when you hit enter and haven't filled in all the columns. Adding a "" to the cell will stop it being a null cell, and will stop it crashing.
In a few days if nobody has given me a better solution I will mark this as solved, but I will leave it open for a while in case somebody has a better way of doing this. I had to come up with a solution myself because nobody else came up with one. I do believe there may be a better way of doing this though.
-
Can you show the stack trace of your crash ?
There's something fishy.
Otherwise, you can use blockSignals.
-
@SGaist
Now I am disconnecting and adding the row it isn't crashing anymore.I would really love to give you a stack trace, but I don't know how.
I spent 2 days googling how to do a stack trace in QT and couldn't find any help at all.When I find a tutorial or some help on how to do a stack trace, I will certainly give you one.
-
Build your application in debug mode, start a debugging session, make it crash and you'll have the stack trace.
-
@SGaist
I quoted out the disconnect to purposely cause the crash again. Then run in debug mode, which is actually what I always run it in.Went to menu Debug, and clicked on start debuggin (F5) and I get a message window pop up "Unknown debugger type
no engine
. Unable to create a debugger typeno engine
".So the debugger does not seem to work.
-
Did you install one ? Which OS are you running with which compiler?