Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSqlRelationTableModel - setData not working until model->select() is called - Comprehension question
Forum Updated to NodeBB v4.3 + New Features

QSqlRelationTableModel - setData not working until model->select() is called - Comprehension question

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 168 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by A Former User
    #1

    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 the m_sourceModel. For that I have created a function called addGermanName(const QString &name). This function is added in the class GermanNameEditor

    germannameeditor.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 the addGermanName(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!

    JonBJ 1 Reply Last reply
    0
    • ? A Former User

      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 the m_sourceModel. For that I have created a function called addGermanName(const QString &name). This function is added in the class GermanNameEditor

      germannameeditor.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 the addGermanName(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!

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @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 call fetchMore() 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 the fetchMore() in both places. Remove the fetchMore() 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 highest Id 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.

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved