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. Editing data in table view (row grater than 256) QSqlTableModel

Editing data in table view (row grater than 256) QSqlTableModel

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 2 Posters 2.2k 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.
  • N Offline
    N Offline
    nadamus
    wrote on last edited by
    #1

    Hi,
    I have some problems with editing data in tableview (QSqlTableModel). It is working OK until I have less than 256 records. If row is grater than 256, when cell editing is finished, all data in rows above no.256 dissipater leaving them empty. After scrolling records all the way up and down data appear back, but additional empty rows still remain. Each data edit increases number of empty rows. Underlying database is updated correctly.
    Resetting view does not improving things for me.
    Thanks in advance for your help.
    Regards

    JonBJ 1 Reply Last reply
    0
    • N nadamus

      Hi,
      I have some problems with editing data in tableview (QSqlTableModel). It is working OK until I have less than 256 records. If row is grater than 256, when cell editing is finished, all data in rows above no.256 dissipater leaving them empty. After scrolling records all the way up and down data appear back, but additional empty rows still remain. Each data edit increases number of empty rows. Underlying database is updated correctly.
      Resetting view does not improving things for me.
      Thanks in advance for your help.
      Regards

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

      @nadamus
      At some level, this will be to do with the fact that the rows are read in batches of size maximum 256 in the QSqlTableModel Qt code. IIRC that number is hard-coded. You must look at calling https://doc.qt.io/qt-5/qsqlquerymodel.html#fetchMore in a loop as necessary if you want to ensure you have all read all records returned from a query/in a table.

      N 1 Reply Last reply
      2
      • JonBJ JonB

        @nadamus
        At some level, this will be to do with the fact that the rows are read in batches of size maximum 256 in the QSqlTableModel Qt code. IIRC that number is hard-coded. You must look at calling https://doc.qt.io/qt-5/qsqlquerymodel.html#fetchMore in a loop as necessary if you want to ensure you have all read all records returned from a query/in a table.

        N Offline
        N Offline
        nadamus
        wrote on last edited by
        #3

        @JonB
        Thanks for reply.
        I tried to load all data using fetchMore() method, prior to data edit. I tried also to run fetchMore after cell edit. I connected dataChanged signal with my slot resetting view and loading all data. Result was the same.

        JonBJ 1 Reply Last reply
        0
        • N nadamus

          @JonB
          Thanks for reply.
          I tried to load all data using fetchMore() method, prior to data edit. I tried also to run fetchMore after cell edit. I connected dataChanged signal with my slot resetting view and loading all data. Result was the same.

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

          @nadamus
          Then show your code, because with the number being 256 I'm pretty sure this is the reason. And btw if you are inserting (or deleting) rows you will not get the dataChanged signal.

          1 Reply Last reply
          2
          • N Offline
            N Offline
            nadamus
            wrote on last edited by
            #5

            I'm pretty sure that 256 is the reason. :)
            I'm not referring to adding or removing rows which I have to check later. Now I'm focusing on editing data (double mouse click and edit). This emits dataChanged signal for sure. I'm using it for some data checks.

            Some explanation. My table is showing sets of points with numbers, 3D coordinates and point type code. Only two columns are editable (point number) and Point code.
            In my subclass I have re-implemented two methods:

            data - for display coordinates decimal precission (4 digits) and change code from int to particular code name

            flags - for setting particular columns editable

            I did not rimperilment setData method - since it was working OK until this grater than 256 rows issue. Maybe this is a reason for described behavior?

            This is my QSqlTableModel subclass:
            PointTableModel.h

            #ifndef POINTTABLEMODEL_H
            #define POINTTABLEMODEL_H
            
            #define REGULARTYPE QString("Regular")
            #define FACETYPE QString("Face")
            #define FLANGEFRONTTYPE QString("Flange front")
            #define FLANGEBACKTYPE QString("Flange back")
            #define BOLTTYPE QString("Bolt")
            #define FLANGEFRONTFLOWERTYPE QString("Flange front-flower")
            #define FLANGEBACKFLOWERTYPE QString("Flange back-flower")
            #define MASTERGRIDTYPE QString("MasterGrid")
            #define PIPEDIAMETERTYPE QString("Pipe diameter")
            #define AUTO_CADTYPE QString("AutoCad")
            #define UNSPECIFIEDTYPE QString("Unspecified")
            
            #include <QDebug>
            #include <QObject>
            #include <QSqlQuery>
            #include <QSqlQueryModel>
            #include <QSqlTableModel>
            #include <QComboBox>
            
            class PointTableModel : public QSqlTableModel
            {
            public:
            
            
                PointTableModel(QSqlDatabase polaczenie);
                PointTableModel(QList<int>editList,int kolKodow);
            
                QVariant data ( const QModelIndex & index, int role = Qt::EditRole ) const override;
                Qt::ItemFlags flags(const QModelIndex & indeks) const override;
                //bool setData(const QModelIndex &index, const QVariant &value, int role) override;
            
            private:
                QList<int> kolumnyEdytowalne;//editable collumns
                QList<int> kolumnyNumeryczne;//numeric collumns
                int kolumnaKodow;//codes column
            
            
            };
            

            PointTableMode.cpp

            #include "pointtablemodel.h"
            
            PointTableModel::PointTableModel(QSqlDatabase polaczenie)
                :QSqlTableModel (NULL,polaczenie)
            {
                kolumnaKodow=6;
                kolumnyEdytowalne={2,6};//editable collumns
                kolumnyNumeryczne={3,4,5};//numeric collumns
                setEditStrategy(QSqlTableModel::OnManualSubmit);
                //setEditStrategy(QSqlTableModel::OnFieldChange);
            }
            
            PointTableModel::PointTableModel(QList<int>editList,int kolKodow)
            {
                kolumnaKodow=kolKodow;//codes collmns
                kolumnyEdytowalne=editList;//editable collumns
            }
            
            QVariant PointTableModel::data(const QModelIndex &indeks, int rola) const
            {
                QVariant wartosc= QSqlTableModel::data(indeks,rola);
                double wart;
                if(rola==Qt::DisplayRole && kolumnyNumeryczne.indexOf(indeks.column())!=-1){
                  wart=wartosc.toDouble();
                  return QString::number(wart,'f',4);
                }
                if( indeks.column()==kolumnaKodow){
                    bool ok;
                    int typPunktu=wartosc.toInt(&ok);
                    if(ok){
                        switch (typPunktu){
                        case 0:
                            return QVariant(REGULARTYPE);
                        case 1:
                            return QVariant(FACETYPE);
                        case 2:
                            return QVariant(FLANGEFRONTTYPE);
                        case 3:
                            return QVariant(FLANGEBACKTYPE);
                        case 4:
                            return QVariant(BOLTTYPE);
                        case 5:
                            return QVariant(FLANGEFRONTFLOWERTYPE);
                        case 6:
                            return QVariant(FLANGEBACKFLOWERTYPE);
                        case 7:
                            return QVariant(MASTERGRIDTYPE);
                        case 8:
                            return QVariant(PIPEDIAMETERTYPE);
                        case 9:
                            return QVariant(AUTO_CADTYPE);
                        default:
                            return QVariant(UNSPECIFIEDTYPE);
                        }
                    }
                }
                return QSqlTableModel::data(indeks,rola);
            }
            
            Qt::ItemFlags PointTableModel::flags(const QModelIndex &indeks) const
            {
                Qt::ItemFlags flagi=QSqlTableModel::flags(indeks);
                flagi.setFlag(Qt::ItemIsEditable,false);
                int iterator=0;
                int max=kolumnyEdytowalne.size();
                bool znalazl=false;
                while(iterator<max && !znalazl){
                    if(indeks.column()==kolumnyEdytowalne[iterator]){
                        znalazl=true;
                    }
                    iterator++;
                }
                if(znalazl){
                    return flagi|Qt::ItemIsEditable;
                }else{
                    return flagi;
                }
            }
            

            New model creation method.

            PointTableModel* DbConnection::GetTabelaPktStanowiska(int indeksStanowiska)const
            {
                PointTableModel* nowymodelPtr=NULL;
                QString zapytanie;
                if(SprawdzPolaczenie()){
                    zapytanie=QString("stanowisko_Id=%1").arg(indeksStanowiska);//
                    nowymodelPtr=new PointTableModel(polaczenieGlowne);
                    if(nowymodelPtr) {
                        nowymodelPtr->setTable(TBL_PKT);
                        nowymodelPtr->setFilter(zapytanie);
                        nowymodelPtr->select();
                    }
                    return  nowymodelPtr;
                }else{
                    throw int(53);
                }
                
            }
            

            Then I'm setting this model to tableVeiw in mainWindow class
            Regards

            JonBJ 1 Reply Last reply
            0
            • N nadamus

              I'm pretty sure that 256 is the reason. :)
              I'm not referring to adding or removing rows which I have to check later. Now I'm focusing on editing data (double mouse click and edit). This emits dataChanged signal for sure. I'm using it for some data checks.

              Some explanation. My table is showing sets of points with numbers, 3D coordinates and point type code. Only two columns are editable (point number) and Point code.
              In my subclass I have re-implemented two methods:

              data - for display coordinates decimal precission (4 digits) and change code from int to particular code name

              flags - for setting particular columns editable

              I did not rimperilment setData method - since it was working OK until this grater than 256 rows issue. Maybe this is a reason for described behavior?

              This is my QSqlTableModel subclass:
              PointTableModel.h

              #ifndef POINTTABLEMODEL_H
              #define POINTTABLEMODEL_H
              
              #define REGULARTYPE QString("Regular")
              #define FACETYPE QString("Face")
              #define FLANGEFRONTTYPE QString("Flange front")
              #define FLANGEBACKTYPE QString("Flange back")
              #define BOLTTYPE QString("Bolt")
              #define FLANGEFRONTFLOWERTYPE QString("Flange front-flower")
              #define FLANGEBACKFLOWERTYPE QString("Flange back-flower")
              #define MASTERGRIDTYPE QString("MasterGrid")
              #define PIPEDIAMETERTYPE QString("Pipe diameter")
              #define AUTO_CADTYPE QString("AutoCad")
              #define UNSPECIFIEDTYPE QString("Unspecified")
              
              #include <QDebug>
              #include <QObject>
              #include <QSqlQuery>
              #include <QSqlQueryModel>
              #include <QSqlTableModel>
              #include <QComboBox>
              
              class PointTableModel : public QSqlTableModel
              {
              public:
              
              
                  PointTableModel(QSqlDatabase polaczenie);
                  PointTableModel(QList<int>editList,int kolKodow);
              
                  QVariant data ( const QModelIndex & index, int role = Qt::EditRole ) const override;
                  Qt::ItemFlags flags(const QModelIndex & indeks) const override;
                  //bool setData(const QModelIndex &index, const QVariant &value, int role) override;
              
              private:
                  QList<int> kolumnyEdytowalne;//editable collumns
                  QList<int> kolumnyNumeryczne;//numeric collumns
                  int kolumnaKodow;//codes column
              
              
              };
              

              PointTableMode.cpp

              #include "pointtablemodel.h"
              
              PointTableModel::PointTableModel(QSqlDatabase polaczenie)
                  :QSqlTableModel (NULL,polaczenie)
              {
                  kolumnaKodow=6;
                  kolumnyEdytowalne={2,6};//editable collumns
                  kolumnyNumeryczne={3,4,5};//numeric collumns
                  setEditStrategy(QSqlTableModel::OnManualSubmit);
                  //setEditStrategy(QSqlTableModel::OnFieldChange);
              }
              
              PointTableModel::PointTableModel(QList<int>editList,int kolKodow)
              {
                  kolumnaKodow=kolKodow;//codes collmns
                  kolumnyEdytowalne=editList;//editable collumns
              }
              
              QVariant PointTableModel::data(const QModelIndex &indeks, int rola) const
              {
                  QVariant wartosc= QSqlTableModel::data(indeks,rola);
                  double wart;
                  if(rola==Qt::DisplayRole && kolumnyNumeryczne.indexOf(indeks.column())!=-1){
                    wart=wartosc.toDouble();
                    return QString::number(wart,'f',4);
                  }
                  if( indeks.column()==kolumnaKodow){
                      bool ok;
                      int typPunktu=wartosc.toInt(&ok);
                      if(ok){
                          switch (typPunktu){
                          case 0:
                              return QVariant(REGULARTYPE);
                          case 1:
                              return QVariant(FACETYPE);
                          case 2:
                              return QVariant(FLANGEFRONTTYPE);
                          case 3:
                              return QVariant(FLANGEBACKTYPE);
                          case 4:
                              return QVariant(BOLTTYPE);
                          case 5:
                              return QVariant(FLANGEFRONTFLOWERTYPE);
                          case 6:
                              return QVariant(FLANGEBACKFLOWERTYPE);
                          case 7:
                              return QVariant(MASTERGRIDTYPE);
                          case 8:
                              return QVariant(PIPEDIAMETERTYPE);
                          case 9:
                              return QVariant(AUTO_CADTYPE);
                          default:
                              return QVariant(UNSPECIFIEDTYPE);
                          }
                      }
                  }
                  return QSqlTableModel::data(indeks,rola);
              }
              
              Qt::ItemFlags PointTableModel::flags(const QModelIndex &indeks) const
              {
                  Qt::ItemFlags flagi=QSqlTableModel::flags(indeks);
                  flagi.setFlag(Qt::ItemIsEditable,false);
                  int iterator=0;
                  int max=kolumnyEdytowalne.size();
                  bool znalazl=false;
                  while(iterator<max && !znalazl){
                      if(indeks.column()==kolumnyEdytowalne[iterator]){
                          znalazl=true;
                      }
                      iterator++;
                  }
                  if(znalazl){
                      return flagi|Qt::ItemIsEditable;
                  }else{
                      return flagi;
                  }
              }
              

              New model creation method.

              PointTableModel* DbConnection::GetTabelaPktStanowiska(int indeksStanowiska)const
              {
                  PointTableModel* nowymodelPtr=NULL;
                  QString zapytanie;
                  if(SprawdzPolaczenie()){
                      zapytanie=QString("stanowisko_Id=%1").arg(indeksStanowiska);//
                      nowymodelPtr=new PointTableModel(polaczenieGlowne);
                      if(nowymodelPtr) {
                          nowymodelPtr->setTable(TBL_PKT);
                          nowymodelPtr->setFilter(zapytanie);
                          nowymodelPtr->select();
                      }
                      return  nowymodelPtr;
                  }else{
                      throw int(53);
                  }
                  
              }
              

              Then I'm setting this model to tableVeiw in mainWindow class
              Regards

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

              @nadamus
              Your code shows no call at all to fetchMore(). You said:

              I tried to load all data using fetchMore() method, prior to data edit. I tried also to run fetchMore after cell edit.

              Since fetchMore() is going to be required to deal with the 256 rows, I don't see how the large amount of code you posted will address that? I was expecting just a couple of lines of your code, showing how & where you call fetchMore().

              N 1 Reply Last reply
              0
              • JonBJ JonB

                @nadamus
                Your code shows no call at all to fetchMore(). You said:

                I tried to load all data using fetchMore() method, prior to data edit. I tried also to run fetchMore after cell edit.

                Since fetchMore() is going to be required to deal with the 256 rows, I don't see how the large amount of code you posted will address that? I was expecting just a couple of lines of your code, showing how & where you call fetchMore().

                N Offline
                N Offline
                nadamus
                wrote on last edited by nadamus
                #7

                @JonB
                I created slot in attempt of deal with issue, but there was no change in table behavior. That's why I skipped it here. It was just long shot.
                it looks like that:
                Connection:

                ui->tableView->setModel(modelTabeliPunktowPtr);
                connect(modelTabeliPunktowPtr,SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),this,SLOT(SrpawdzPolaczeniaPunktu(const QModelIndex &)));
                connect(modelTabeliPunktowPtr,SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),this,SLOT(AktualizujTabele(const QModelIndex&,const QModelIndex& )));
                

                slot:

                void MainWindow::AktualizujTabele(const QModelIndex& indeksJeden,const QModelIndex& indeksDwa)
                {
                
                    if(modelTabeliPunktowPtr){
                        ui->tableView->reset();
                        modelTabeliPunktowPtr->rowCount();
                        while(modelTabeliPunktowPtr->canFetchMore()){
                            modelTabeliPunktowPtr->fetchMore();
                        }
                    }
                    ui->tableView->scrollTo(indeksJeden);
                }
                
                N 1 Reply Last reply
                0
                • N nadamus

                  @JonB
                  I created slot in attempt of deal with issue, but there was no change in table behavior. That's why I skipped it here. It was just long shot.
                  it looks like that:
                  Connection:

                  ui->tableView->setModel(modelTabeliPunktowPtr);
                  connect(modelTabeliPunktowPtr,SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),this,SLOT(SrpawdzPolaczeniaPunktu(const QModelIndex &)));
                  connect(modelTabeliPunktowPtr,SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),this,SLOT(AktualizujTabele(const QModelIndex&,const QModelIndex& )));
                  

                  slot:

                  void MainWindow::AktualizujTabele(const QModelIndex& indeksJeden,const QModelIndex& indeksDwa)
                  {
                  
                      if(modelTabeliPunktowPtr){
                          ui->tableView->reset();
                          modelTabeliPunktowPtr->rowCount();
                          while(modelTabeliPunktowPtr->canFetchMore()){
                              modelTabeliPunktowPtr->fetchMore();
                          }
                      }
                      ui->tableView->scrollTo(indeksJeden);
                  }
                  
                  N Offline
                  N Offline
                  nadamus
                  wrote on last edited by
                  #8

                  OK
                  I have managed to deal with issue. It is more walk around than decent way to do it, but it works for now.

                  void MainWindow::AktualizujTabele(const QModelIndex& indeksJeden,const QModelIndex& indeksDwa)
                  {
                      int wiersz=indeksJeden.row();
                      if(wiersz>256){
                          if(modelTabeliPunktowPtr){
                              ui->tableView->setModel(modelTabeliPunktowPtr);//reassigning model
                              while(modelTabeliPunktowPtr->canFetchMore()){
                                  modelTabeliPunktowPtr->fetchMore();
                              }
                              if(wiersz>modelTabeliPunktowPtr->rowCount()){
                                  wiersz=modelTabeliPunktowPtr->rowCount();
                              }
                              ui->tableView->selectRow(wiersz);
                              ui->tableView->scrollTo(ui->tableView->currentIndex());
                          }
                      }
                  }
                  
                  JonBJ 1 Reply Last reply
                  0
                  • N nadamus

                    OK
                    I have managed to deal with issue. It is more walk around than decent way to do it, but it works for now.

                    void MainWindow::AktualizujTabele(const QModelIndex& indeksJeden,const QModelIndex& indeksDwa)
                    {
                        int wiersz=indeksJeden.row();
                        if(wiersz>256){
                            if(modelTabeliPunktowPtr){
                                ui->tableView->setModel(modelTabeliPunktowPtr);//reassigning model
                                while(modelTabeliPunktowPtr->canFetchMore()){
                                    modelTabeliPunktowPtr->fetchMore();
                                }
                                if(wiersz>modelTabeliPunktowPtr->rowCount()){
                                    wiersz=modelTabeliPunktowPtr->rowCount();
                                }
                                ui->tableView->selectRow(wiersz);
                                ui->tableView->scrollTo(ui->tableView->currentIndex());
                            }
                        }
                    }
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @nadamus
                    If you have something which now works, and the reason is the 256 rows and the fetchMore() calls I said you will need, that is good for you.

                    I will just say that your code should have no reference to the 256 (your if(wiersz>256)) as that could change at any time and there is no need to rely/hard-code it. Nor certainly should you be "reassigning model" anywhere as you do, that is wrong and slow. I don't know where you call your function from, but it may not be the correct/best place to be doing the fetchMore() from.

                    However, I leave this to you now.

                    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