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. Export QTableView data with a delegated column to CSV
QtWS25 Last Chance

Export QTableView data with a delegated column to CSV

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 3 Posters 1.9k 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.
  • M morteza ali ahmadi

    @JonB Thanks for your response. I prefer to use your original approach compare to the second and third choices, but how can I produce the desired string format in the models data(index, role=Qt::DisplayRole)?

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

    @morteza-ali-ahmadi

    QVariant MyModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
    {
        if (!index.isValid())
            return QVariant();
        QVariant v = BaseModel::data(index, role);
        if (role == Qt::DisplayRole)
            if (isTimeStampColumn(index.column()))
            {
                double value = v.toDouble();
                ...
                return QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime).toString("yyyy-MM-dd HH:mm:ss.zzz");
            }
        return v;
    }
    

    If you want to correctly sort on this column, you ought have a sort role which returns the base data value, not the string.

    Remember from what I said above, don't blame me if one of the expert critics --- @VRonin, IIRC, though I might be mistaken --- calls for your beheading for using this approach... ;-)

    M 1 Reply Last reply
    2
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #5

      What I would do:
      In the delegate, don't reimplement paint(), but displayText() (it's also a lot easier than what you did):

       class TimeDgDelegate : public QStyledItemDelegate{
      Q_OBJECT
      public:
      using QStyledItemDelegate::QStyledItemDelegate;
      QString displayText(const QVariant &value, const QLocale &locale) const override{
      double value = value.toDouble();
      double qd_ts = value*1.25/(256.0*256.0);
      qd_ts += 315964800000;
      return locale.toString(QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime),QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz"));
      }
      };
      

      Then your csv export would become:

      for (int i = 0; i < rows; i++) {
          for (int j = 0; j < columns; j++) {
              const QModelIndex idx = model->index(i,j);
              textData += ui->tableView->itemDelegate(idx)->displayText(model->data(idx),locale()) + QLatin1Char(',');
          }
          textData += QLatin1Char('\n'); 
      }
      

      P.S.
      Probably doesn't apply here but generally csv exporting requires you to escape , and " characters in 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

      JonBJ M 3 Replies Last reply
      3
      • JonBJ JonB

        @morteza-ali-ahmadi

        QVariant MyModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
        {
            if (!index.isValid())
                return QVariant();
            QVariant v = BaseModel::data(index, role);
            if (role == Qt::DisplayRole)
                if (isTimeStampColumn(index.column()))
                {
                    double value = v.toDouble();
                    ...
                    return QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime).toString("yyyy-MM-dd HH:mm:ss.zzz");
                }
            return v;
        }
        

        If you want to correctly sort on this column, you ought have a sort role which returns the base data value, not the string.

        Remember from what I said above, don't blame me if one of the expert critics --- @VRonin, IIRC, though I might be mistaken --- calls for your beheading for using this approach... ;-)

        M Offline
        M Offline
        morteza ali ahmadi
        wrote on last edited by
        #6

        @JonB Thank you again for your codes.

        1 Reply Last reply
        0
        • VRoninV VRonin

          What I would do:
          In the delegate, don't reimplement paint(), but displayText() (it's also a lot easier than what you did):

           class TimeDgDelegate : public QStyledItemDelegate{
          Q_OBJECT
          public:
          using QStyledItemDelegate::QStyledItemDelegate;
          QString displayText(const QVariant &value, const QLocale &locale) const override{
          double value = value.toDouble();
          double qd_ts = value*1.25/(256.0*256.0);
          qd_ts += 315964800000;
          return locale.toString(QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime),QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz"));
          }
          };
          

          Then your csv export would become:

          for (int i = 0; i < rows; i++) {
              for (int j = 0; j < columns; j++) {
                  const QModelIndex idx = model->index(i,j);
                  textData += ui->tableView->itemDelegate(idx)->displayText(model->data(idx),locale()) + QLatin1Char(',');
              }
              textData += QLatin1Char('\n'); 
          }
          

          P.S.
          Probably doesn't apply here but generally csv exporting requires you to escape , and " characters in the data

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

          @VRonin
          Thanks for posting. I forget about just QStyledItemDelegate::displayText(), that's a good one to remember.

          Assuming you are indeed the expert poster in the past about use of Qt::DisplayRole I recall, and who called for my execution :) You don't like that use of the model/display role, and now I feel similarly uncomfortable about your use of anything QStyledItemDelegate, ui->tableView->itemDelegate(idx), when you are exporting model data to CSV. Your export requires access to a UI table view, but the format for CSV export has nothing to do with any model views, and there is no reason to suppose exporting code would have any UI access at all, or even be a GUI application. IMHO. We're probably not going to agree ;-)

          VRoninV 1 Reply Last reply
          0
          • VRoninV VRonin

            What I would do:
            In the delegate, don't reimplement paint(), but displayText() (it's also a lot easier than what you did):

             class TimeDgDelegate : public QStyledItemDelegate{
            Q_OBJECT
            public:
            using QStyledItemDelegate::QStyledItemDelegate;
            QString displayText(const QVariant &value, const QLocale &locale) const override{
            double value = value.toDouble();
            double qd_ts = value*1.25/(256.0*256.0);
            qd_ts += 315964800000;
            return locale.toString(QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime),QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz"));
            }
            };
            

            Then your csv export would become:

            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < columns; j++) {
                    const QModelIndex idx = model->index(i,j);
                    textData += ui->tableView->itemDelegate(idx)->displayText(model->data(idx),locale()) + QLatin1Char(',');
                }
                textData += QLatin1Char('\n'); 
            }
            

            P.S.
            Probably doesn't apply here but generally csv exporting requires you to escape , and " characters in the data

            M Offline
            M Offline
            morteza ali ahmadi
            wrote on last edited by
            #8

            @VRonin Thank you very much, yes, it could solve my problem with a better implementation.

            1 Reply Last reply
            0
            • JonBJ JonB

              @VRonin
              Thanks for posting. I forget about just QStyledItemDelegate::displayText(), that's a good one to remember.

              Assuming you are indeed the expert poster in the past about use of Qt::DisplayRole I recall, and who called for my execution :) You don't like that use of the model/display role, and now I feel similarly uncomfortable about your use of anything QStyledItemDelegate, ui->tableView->itemDelegate(idx), when you are exporting model data to CSV. Your export requires access to a UI table view, but the format for CSV export has nothing to do with any model views, and there is no reason to suppose exporting code would have any UI access at all, or even be a GUI application. IMHO. We're probably not going to agree ;-)

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

              @JonB said in Export QTableView data with a delegated column to CSV:

              Your export requires access to a UI table view, but the format for CSV export has nothing to do with any model views, and there is no reason to suppose exporting code would have any UI access at all, or even be a GUI application

              I think we actually agree on this one. The clean way here is to have a function that handles the conversion of data from double to QDate. The delegate will call it and then format it as a string to display, the csv serialiser will call it and then save the QDate to csv.

              Assuming you are indeed the expert poster in the past about use of Qt::DisplayRole I recall, and who called for my execution

              This is a very corner case in which your approach doesn't do much harm and can be used. if, however, the date format was dd-MM-yyyy HH:mm:ss.zzz then your solution would break sorting in the table (as it would sort as string, not as dates)

              "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

              JonBJ 1 Reply Last reply
              2
              • VRoninV VRonin

                @JonB said in Export QTableView data with a delegated column to CSV:

                Your export requires access to a UI table view, but the format for CSV export has nothing to do with any model views, and there is no reason to suppose exporting code would have any UI access at all, or even be a GUI application

                I think we actually agree on this one. The clean way here is to have a function that handles the conversion of data from double to QDate. The delegate will call it and then format it as a string to display, the csv serialiser will call it and then save the QDate to csv.

                Assuming you are indeed the expert poster in the past about use of Qt::DisplayRole I recall, and who called for my execution

                This is a very corner case in which your approach doesn't do much harm and can be used. if, however, the date format was dd-MM-yyyy HH:mm:ss.zzz then your solution would break sorting in the table (as it would sort as string, not as dates)

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

                @VRonin said in Export QTableView data with a delegated column to CSV:

                I think we actually agree on this one.

                Amazing :)

                This is a very corner case in which your approach doesn't do much harm

                It is good to know that at worst I am "harmless" ;-)

                The clean way here is to have a function that handles the conversion of data from double to QDate. The delegate will call it and then format it as a string to display, the csv serialiser will call it and then save the QDate to csv.

                I suggested that as my 3rd alternative.

                then your solution would break sorting in the table (as it would sort as string, not as dates)

                Absolutely, and I thought I typed into my answer about if you did this you need to use a different sort role if you sort, but maybe I deleted that. But yes people should bear this in mind.

                1 Reply Last reply
                0
                • VRoninV VRonin

                  What I would do:
                  In the delegate, don't reimplement paint(), but displayText() (it's also a lot easier than what you did):

                   class TimeDgDelegate : public QStyledItemDelegate{
                  Q_OBJECT
                  public:
                  using QStyledItemDelegate::QStyledItemDelegate;
                  QString displayText(const QVariant &value, const QLocale &locale) const override{
                  double value = value.toDouble();
                  double qd_ts = value*1.25/(256.0*256.0);
                  qd_ts += 315964800000;
                  return locale.toString(QDateTime::fromMSecsSinceEpoch(qd_ts, Qt::LocalTime),QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz"));
                  }
                  };
                  

                  Then your csv export would become:

                  for (int i = 0; i < rows; i++) {
                      for (int j = 0; j < columns; j++) {
                          const QModelIndex idx = model->index(i,j);
                          textData += ui->tableView->itemDelegate(idx)->displayText(model->data(idx),locale()) + QLatin1Char(',');
                      }
                      textData += QLatin1Char('\n'); 
                  }
                  

                  P.S.
                  Probably doesn't apply here but generally csv exporting requires you to escape , and " characters in the data

                  M Offline
                  M Offline
                  morteza ali ahmadi
                  wrote on last edited by
                  #11

                  @VRonin Does your solution convert epochs format to string one twice? i.e. for each database record in your solution,

                  • Conversion with displayText function is used to display "yyyy-MM-dd HH:mm:ss.zzz" format in QTableView and,

                  • Conversion with displayText function is used to store "yyyy-MM-dd HH:mm:ss.zzz" format in CSV.

                  Is it right?

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

                    correct, you are basically using displayText as a fancy toString().

                    Also, just to be clear, the delegate repaints on demand and doesn't cache the displayText so it's actually calculated every time a repaints happens

                    "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

                    M 1 Reply Last reply
                    1
                    • VRoninV VRonin

                      correct, you are basically using displayText as a fancy toString().

                      Also, just to be clear, the delegate repaints on demand and doesn't cache the displayText so it's actually calculated every time a repaints happens

                      M Offline
                      M Offline
                      morteza ali ahmadi
                      wrote on last edited by
                      #13

                      @VRonin, So I think the combination of your solution and the third solution of @JonB is the best choice. It means that, I can override displayText() instead of paint() and use a function X within that which handles the conversion of data from double to "dd-MM-yyyy HH:mm:ss.zzz". Also, the X function can be used in export to CSV procedure.

                      @VRonin and @JonB, do you agree with me?

                      JonBJ 1 Reply Last reply
                      2
                      • M morteza ali ahmadi

                        @VRonin, So I think the combination of your solution and the third solution of @JonB is the best choice. It means that, I can override displayText() instead of paint() and use a function X within that which handles the conversion of data from double to "dd-MM-yyyy HH:mm:ss.zzz". Also, the X function can be used in export to CSV procedure.

                        @VRonin and @JonB, do you agree with me?

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

                        @morteza-ali-ahmadi Yes.

                        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