QSqlRelationTableModel - setData not working until model->select() is called - Comprehension question
-
Hi,
I think I have a problem understanding Qt or a QSqlRelationTableModel. Let me post a few lines of code, then I'll get to my question.databasemanager.cpp
QSqlRelationalTableModel *DatabaseManager::gSourceModel() { QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this); model->setTable("Deutscher_Pilzname"); model->setRelation(model->fieldIndex("Deutscher_name_id"), QSqlRelation("Deutscher_Name", "Id", "Name")); model->setJoinMode(QSqlRelationalTableModel::LeftJoin); model->setSort(SORT::NAME, Qt::AscendingOrder); model->setEditStrategy(QSqlRelationalTableModel::OnManualSubmit); model->select(); while (model->canFetchMore()) { model->fetchMore(); } return model; }
mainwindow.cpp
//this is called in a function that is set in constructor to load all data m_gSourceModel = m_databaseManager->gSourceModel(); // QSqlRelationTableModel m_gnameFilter->setSourceModel(m_gSourceModel); //subclassed QSortFilterProxyModel, where I can filter by ID called GermanNameFilter m_gRelationModel = m_gSourceModel->relationModel(1); while (m_gRelationModel->canFetchMore()) { m_gRelationModel->canFetchMore(); } //m_gnameEditor is a QDialog whichs opens if I click on a Button called "add" m_gnameEditor->setFilterModels(m_gnameEditorFilter, m_gSourceModel, m_gRelationModel);
If I click on a button called Add, a new QDialog is open, where I can type a name. This name should be added to the
m_relationModel
and after that it should be added to them_sourceModel
. For that I have created a function calledaddGermanName(const QString &name)
. This function is added in the class GermanNameEditorgermannameeditor.cpp
void GermanNameEditor::setFilterModels(GermanNameFilter *filterModel, QSqlRelationalTableModel *sourceModel, QSqlTableModel *relationModel) { m_filterModel = filterModel; m_sourceModel = sourceModel; m_relationModel = relationModel; qDebug() << "filterModel=" << m_filterModel->rowCount(); //returns all Rows that exists in database qDebug() << "sourceRows=" << m_sourceModel->rowCount(); //returns all Rows that exists in database qDebug() << "relationRows=" << m_relationModel->rowCount(); //returns all Rows that exists in database } void GermanNameEditor::addNewName(const QString &name) { // m_sourceModel->select(); //If this enable all works as aspected QSqlQuery query; query.prepare("SELECT Id FROM Deutscher_Name ORDER BY Id DESC LIMIT 1"); if(query.exec()){ int lastGnameId = -1; if(query.next()){ lastGnameId = query.value(0).toInt(); int gnameId = lastGnameId + 1; const int relationRows = m_relationModel->rowCount(); const int sourceRows = m_sourceModel->rowCount(); qDebug() << "A="<< m_relationModel->insertRow(relationRows); //true qDebug() << "B="<< m_relationModel->setData(m_relationModel->index(relationRows,0), gnameId, Qt::EditRole); //true qDebug() << "C="<< m_relationModel->setData(m_relationModel->index(relationRows,1), name, Qt::EditRole); //true qDebug() << "D="<< m_sourceModel->insertRow(sourceRows); qDebug() << "E="<< m_sourceModel->setData(m_sourceModel->index(sourceRows,1), gnameId, Qt::EditRole); //always false, until I do m_sourceModel->select(); qDebug() << "F="<< m_sourceModel->setData(m_sourceModel->index(sourceRows,2), m_fnameId, Qt::EditRole); //true } } }
My current problem: I don't understand why I have to call
m_sourceModel->select()
again in theaddGermanName(const QString &name)
method, although this has already happened before in the DatabasManager class. Without this, the method does not work as desired, because setData always returns false. Can someone please explain this to me? Is it perhaps because data is filtered beforehand via the GermanNameFilter or what is the problem here?Thanks!
-
Hi,
I think I have a problem understanding Qt or a QSqlRelationTableModel. Let me post a few lines of code, then I'll get to my question.databasemanager.cpp
QSqlRelationalTableModel *DatabaseManager::gSourceModel() { QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this); model->setTable("Deutscher_Pilzname"); model->setRelation(model->fieldIndex("Deutscher_name_id"), QSqlRelation("Deutscher_Name", "Id", "Name")); model->setJoinMode(QSqlRelationalTableModel::LeftJoin); model->setSort(SORT::NAME, Qt::AscendingOrder); model->setEditStrategy(QSqlRelationalTableModel::OnManualSubmit); model->select(); while (model->canFetchMore()) { model->fetchMore(); } return model; }
mainwindow.cpp
//this is called in a function that is set in constructor to load all data m_gSourceModel = m_databaseManager->gSourceModel(); // QSqlRelationTableModel m_gnameFilter->setSourceModel(m_gSourceModel); //subclassed QSortFilterProxyModel, where I can filter by ID called GermanNameFilter m_gRelationModel = m_gSourceModel->relationModel(1); while (m_gRelationModel->canFetchMore()) { m_gRelationModel->canFetchMore(); } //m_gnameEditor is a QDialog whichs opens if I click on a Button called "add" m_gnameEditor->setFilterModels(m_gnameEditorFilter, m_gSourceModel, m_gRelationModel);
If I click on a button called Add, a new QDialog is open, where I can type a name. This name should be added to the
m_relationModel
and after that it should be added to them_sourceModel
. For that I have created a function calledaddGermanName(const QString &name)
. This function is added in the class GermanNameEditorgermannameeditor.cpp
void GermanNameEditor::setFilterModels(GermanNameFilter *filterModel, QSqlRelationalTableModel *sourceModel, QSqlTableModel *relationModel) { m_filterModel = filterModel; m_sourceModel = sourceModel; m_relationModel = relationModel; qDebug() << "filterModel=" << m_filterModel->rowCount(); //returns all Rows that exists in database qDebug() << "sourceRows=" << m_sourceModel->rowCount(); //returns all Rows that exists in database qDebug() << "relationRows=" << m_relationModel->rowCount(); //returns all Rows that exists in database } void GermanNameEditor::addNewName(const QString &name) { // m_sourceModel->select(); //If this enable all works as aspected QSqlQuery query; query.prepare("SELECT Id FROM Deutscher_Name ORDER BY Id DESC LIMIT 1"); if(query.exec()){ int lastGnameId = -1; if(query.next()){ lastGnameId = query.value(0).toInt(); int gnameId = lastGnameId + 1; const int relationRows = m_relationModel->rowCount(); const int sourceRows = m_sourceModel->rowCount(); qDebug() << "A="<< m_relationModel->insertRow(relationRows); //true qDebug() << "B="<< m_relationModel->setData(m_relationModel->index(relationRows,0), gnameId, Qt::EditRole); //true qDebug() << "C="<< m_relationModel->setData(m_relationModel->index(relationRows,1), name, Qt::EditRole); //true qDebug() << "D="<< m_sourceModel->insertRow(sourceRows); qDebug() << "E="<< m_sourceModel->setData(m_sourceModel->index(sourceRows,1), gnameId, Qt::EditRole); //always false, until I do m_sourceModel->select(); qDebug() << "F="<< m_sourceModel->setData(m_sourceModel->index(sourceRows,2), m_fnameId, Qt::EditRole); //true } } }
My current problem: I don't understand why I have to call
m_sourceModel->select()
again in theaddGermanName(const QString &name)
method, although this has already happened before in the DatabasManager class. Without this, the method does not work as desired, because setData always returns false. Can someone please explain this to me? Is it perhaps because data is filtered beforehand via the GermanNameFilter or what is the problem here?Thanks!
@Gabber
I don't know, but if it were me I would do some more tests and make your code 100% consistent.In
gSourceModel()
what you actually do is callfetchMore()
until the table is full. Does it get called (i.e. are there > 256 rows so that it needs to fetch more)? If so that leaves the table in a different state from your commented out line// m_sourceModel->select(); //If this enable all works as aspected
since that call will only fetch some of the rows, and will affect its choice of value for
sourceRows
. Compare that value with and without your commented line. Change code to either do or not do thefetchMore()
in both places. Remove thefetchMore()
if it is not needed while debugging this.Remove your
filterModel
while debugging this, in case it interferes.Reverse the order you add to relational model followed by adding to source model, any difference?
Move the code from
addNewName()
to, say,gSourceModel()
and do it directly there so we are 100% sure we know what state we are in.Remove the query in
addNewName()
--- just look at what the highestId
is externally and hard-code that value without querying while you test.Those will do for a start! Let's get some answers before proceeding further.