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. How to save a table in a file
Forum Updated to NodeBB v4.3 + New Features

How to save a table in a file

Scheduled Pinned Locked Moved Unsolved General and Desktop
27 Posts 5 Posters 6.1k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    Daesos
    wrote on last edited by Daesos
    #17

    I used debugger and when i click on pushButton_2 (save on interface) it returns a Segmentation Fault at "QTableWidgetItem::text".
    @J.Hilk, I didn't even notice. I edited the increment.

    Segmentation Fault occurs when I try to access to a NULL pointer, right? So, it might be out of bound.

    JonBJ 1 Reply Last reply
    0
    • D Daesos

      I used debugger and when i click on pushButton_2 (save on interface) it returns a Segmentation Fault at "QTableWidgetItem::text".
      @J.Hilk, I didn't even notice. I edited the increment.

      Segmentation Fault occurs when I try to access to a NULL pointer, right? So, it might be out of bound.

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

      @Daesos
      I don't see save_button in the code you've posted?

      I notice you have:

                      ui->tableWidget->setItem(i, 0, itm);
                      ui->tableWidget->setItem(i, 2, new QTableWidgetItem("Modified"));
                      ui->tableWidget->setItem(i, 3, new QTableWidgetItem(newlist.at(j).lastModified().toString()));
      

      Where do you setItem() on i, 1 ?

      for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
          for (int j = 1; j < ui->tableWidget->columnCount(); j++){
              QString txt(ui->tableWidget->item(i, j)->text());
              out<<txt;
          }
      

      Check your accesses on every i, j here. Somewhere you do not have an item at item(i, j)!

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Daesos
        wrote on last edited by Daesos
        #19

        I've edited the increment:

           for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
               for (int j = 1; j < ui->tableWidget->columnCount(); ++j)
                   out<<ui->tableWidget->item(i, j)->text();
        

        @JonB said in How to save a table in a file:

        @Daesos

        I notice you have:

                        ui->tableWidget->setItem(i, 0, itm);
                        ui->tableWidget->setItem(i, 2, new QTableWidgetItem("Modified"));
                        ui->tableWidget->setItem(i, 3, new QTableWidgetItem(newlist.at(j).lastModified().toString()));
        

        Where do you setItem() on i, 1 ?

        I've inizialized item at (i, 1) before. Once inizialized the name of the file must not be modified. So I didn't use setItem on i, 1 again.

        @Daesos
        ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, new QTableWidgetItem(newlist.at(index_new).fileName()));

        J.HilkJ 1 Reply Last reply
        0
        • D Daesos

          I've edited the increment:

             for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
                 for (int j = 1; j < ui->tableWidget->columnCount(); ++j)
                     out<<ui->tableWidget->item(i, j)->text();
          

          @JonB said in How to save a table in a file:

          @Daesos

          I notice you have:

                          ui->tableWidget->setItem(i, 0, itm);
                          ui->tableWidget->setItem(i, 2, new QTableWidgetItem("Modified"));
                          ui->tableWidget->setItem(i, 3, new QTableWidgetItem(newlist.at(j).lastModified().toString()));
          

          Where do you setItem() on i, 1 ?

          I've inizialized item at (i, 1) before. Once inizialized the name of the file must not be modified. So I didn't use setItem on i, 1 again.

          @Daesos
          ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, new QTableWidgetItem(newlist.at(index_new).fileName()));

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #20

          @Daesos said in How to save a table in a file:

          for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
          for (int j = 1; j < ui->tableWidget->columnCount(); ++j)
          out<<ui->tableWidget->item(i, j)->text();

          Maybe it's time to #include good old <QDebug>

          for(int i = 0; i < ui->tableWidget->rowCount(); ++i)
                 for (int j = 1; j < ui->tableWidget->columnCount(); ++j){
                     qDebug() << i << "of" << ui->tableWidget->rowCount() << endl
                                       << j << "of" << ui->tableWidget->columnCount();
                     out<<ui->tableWidget->item(i, j)->text();
                     qDebug() << QString("Found text at %1 | %2").arg(i).arg(j);
                 }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by VRonin
            #21

            Replace out<<ui->tableWidget->item(i, j)->text(); with out<<ui->tableWidget->model()->index(i, j).data().tostring(); to prevent segfaults

            The problems I highlighted are still present though

            @VRonin said in How to save a table in a file:

            In your code above you are not:

            • Writing any new line to separate rows.
            • Writing any column separator
            • Escaping column separators inside the data

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            D 1 Reply Last reply
            3
            • VRoninV VRonin

              Replace out<<ui->tableWidget->item(i, j)->text(); with out<<ui->tableWidget->model()->index(i, j).data().tostring(); to prevent segfaults

              The problems I highlighted are still present though

              @VRonin said in How to save a table in a file:

              In your code above you are not:

              • Writing any new line to separate rows.
              • Writing any column separator
              • Escaping column separators inside the data
              D Offline
              D Offline
              Daesos
              wrote on last edited by Daesos
              #22

              @VRonin In a previous version I've added both ";" and "\n", but I forgot to write them again.
              However I forgot one case: what happen if I did not create/delete/modify any file, folder, or other?
              The cells (i, 2) might be empty and here is where the program fails.
              I resolved by editing some code:

              void MainWindow::on_pushButton_2_clicked()
              {
              QFile csv(f_name);
              
              if(!csv.open(QFile::WriteOnly))
                  return;
              
              QTextStream out(&csv);
              int tmp_column = 0;
              
              for(int i = 0; i < ui->tableWidget->rowCount(); ++i){
                  for (int j = 1; j < ui->tableWidget->columnCount(); ++j){
                      if(ui->tableWidget->item(i, j) != 0)
                          out<<ui->tableWidget->item(i, j)->text();
                          out<<";";
                          tmp_column = j;
                  }
                  if(ui->tableWidget->item(i, tmp_column) != 0)
                      out<<"\n";
              }
              
              out.flush();
              csv.close();
              }
              

              It may not be quite good-looking but it works:

              0_1531227135676_6d7d870f-2968-47b7-8941-b6ffbaac0431-image.png

              I've also prevented segmentation faults like this for example:

              ui->tableWidget->setItem(index_delete, 0, itm);
                  if(ui->tableWidget->item(index_delete, 2) != 0 && ui->tableWidget->item(index_delete, 2)->text() != "Deleted")
                      ui->tableWidget->setItem(index_delete, 3, new QTableWidgetItem(QDateTime::currentDateTime().toString()));
              
              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #23

                Try naming a folder Ugly; Name and save your model

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                D VRoninV 2 Replies Last reply
                1
                • VRoninV VRonin

                  Try naming a folder Ugly; Name and save your model

                  D Offline
                  D Offline
                  Daesos
                  wrote on last edited by
                  #24

                  @VRonin You got me, this is another case to write.

                  1 Reply Last reply
                  0
                  • VRoninV VRonin

                    Try naming a folder Ugly; Name and save your model

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by VRonin
                    #25

                    P.S.
                    new QTableWidgetItem(QDateTime::currentDateTime().toString()) see https://bugreports.qt.io/browse/QTBUG-65555

                    this should be separated in 3 lines:

                    QTableWidgetItem* tableItem = new QTableWidgetItem;
                    tableItem->setData(Qt::EditRole,QDateTime::currentDateTime());
                    ui->tableWidget->setItem(index_delete, 3,tableItem);
                    

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    2
                    • D Offline
                      D Offline
                      Daesos
                      wrote on last edited by Daesos
                      #26

                      Say I want to order the items of the table by name or date once I push Save, but without sorting the table itself (just the output in the file.csv). What can I do? Should I create a temporary table, order it and then store in the file?
                      Tell me if the question is not clear.

                      1 Reply Last reply
                      0
                      • VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by VRonin
                        #27

                        Not a temporary table, you can use a QSortFilterProxyModel and then serialise the proxy rather than the original model.
                        Since your current architecture relies on the QStandardItem interface rether than the QAbstractItemModel one you'll need to do some rewriting.

                        To give you an idea, being QString m_csvSeparator the column separator:

                        #include <QStringBuilder>
                        QString escapedCSV(QString unexc) const
                        {
                            if (!unexc.contains(m_csvSeparator))
                                return unexc;
                            unexc.replace(QLatin1Char('\"'), QStringLiteral("\"\""));
                            return '\"' % unexc % '\"';
                        
                        }
                        bool writeCsv(QTextStream& writer, const QAbstractItemModel* constModel) const
                        {
                            if (!constModel)
                                return false;
                            for (int i = 0, maxRow = constModel->rowCount(); i < maxRow ; ++i) {
                                for (int j = 0, maxCol = constModel->columnCount(); j < maxCol ; ++j) {
                                    const QString roleData = constModel->index(i, j).data().toString();
                                    if (j>0)
                                        writer << m_csvSeparator;
                                    if (!roleData.isEmpty()) 
                                        writer << escapedCSV(roleData);
                                }
                                writer << '\n';
                            }
                            return writer.status() == QTextStream::Ok;
                        }
                        

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        4

                        • Login

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