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. Custom sortable columns in QFileSystemModel
Forum Updated to NodeBB v4.3 + New Features

Custom sortable columns in QFileSystemModel

Scheduled Pinned Locked Moved Unsolved General and Desktop
23 Posts 3 Posters 1.4k 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.
  • J Jo Jo

    @JonB Sorry, sorting by "Date Modified" and "Date Created" columns does not work properly (yes, i use qDebug() for tests)

    UPDATE:
    I think it should be implemented like this

    class CustomSortFilterProxyModel : public QSortFilterProxyModel
    {
        QList<int> m_dtCols{3,4};
    public:
        explicit CustomSortFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
    
    protected:
        bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
        {
            auto model = (QFileSystemModel*)sourceModel();
            bool isLeftDir = model->isDir(left);
            bool isRightDir = model->isDir(right);
    
            if ((isLeftDir && isRightDir) || (!isLeftDir && !isRightDir))
            {
                auto leftName  = model->data(left,  Qt::DisplayRole);
                auto rightName = model->data(right, Qt::DisplayRole);
    
                if (m_dtCols.contains(sortColumn()))
                {
                    return (leftName.toDateTime() < rightName.toDateTime());
                }
    
                const int compare = QString::localeAwareCompare(leftName.toString(), rightName.toString());
    
                if(compare != 0) {
                    return compare < 0;
                }
            }
            else if (isLeftDir)
            {
                return true;
            }
    
            return false;
        }
    };
    

    But any improvement is appreciated

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

    @Jo-Jo
    Well, start by checking that goes through the toDateTime() path, what their values are and that is getting it right. I don't know what is wrong just by looking at it.

    Btw, check whether the QString::localeAwareCompare(0 is case insensitive or case sensitive? Windows, but not Linux, sorts case insensitively, yours might not.

    You have just updated your code: I'm not sure it is any different from what you first wrote, but if it is and works that's fine.

    J 1 Reply Last reply
    0
    • JonBJ JonB

      @Jo-Jo
      Well, start by checking that goes through the toDateTime() path, what their values are and that is getting it right. I don't know what is wrong just by looking at it.

      Btw, check whether the QString::localeAwareCompare(0 is case insensitive or case sensitive? Windows, but not Linux, sorts case insensitively, yours might not.

      You have just updated your code: I'm not sure it is any different from what you first wrote, but if it is and works that's fine.

      J Offline
      J Offline
      Jo Jo
      wrote on last edited by Jo Jo
      #15

      @JonB Everything worked except for the "Date Modified" column. It turned out that Qt returns this date as a QString. I had to convert this string to QDateTime. Now the code looks like this:

      class CustomSortFilterProxyModel : public QSortFilterProxyModel
      {
          QList<int> m_dtCols{3,4};
      public:
          explicit CustomSortFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
      
      protected:
          bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
          {
              auto model = (QFileSystemModel*)sourceModel();
              bool isLeftDir = model->isDir(left);
              bool isRightDir = model->isDir(right);
      
              if ((isLeftDir && isRightDir) || (!isLeftDir && !isRightDir))
              {
                  auto leftName  = model->data(left,  Qt::DisplayRole);
                  auto rightName = model->data(right, Qt::DisplayRole);
      
                  //return (leftName.toDateTime() < rightName.toDateTime()); // OK, works fine for dates
      
                  if (m_dtCols.contains(sortColumn()))
                  {
                      if (sortColumn() == 3)
                      {
                          QDateTime dt1 = QDateTime::fromString(leftName.toString(), "M/d/yyyy h:mm AP");
                          QDateTime dt2 = QDateTime::fromString(rightName.toString(), "M/d/yyyy h:mm AP");
                          return dt1 < dt2;
                      }
      
                      return (leftName.toDateTime() < rightName.toDateTime());
                  }
      
                  const int compare = QString::localeAwareCompare(leftName.toString(), rightName.toString());
      
                  if(compare != 0) {
                      return compare < 0;
                  }
              }
              else if (isLeftDir)
              {
                  return true;
              }
      
              return false;
          }
      };
      

      However, I'm not sure that I'm setting the date format correctly. It can change depending on the OS settings, or am I wrong?

      Christian EhrlicherC JonBJ 2 Replies Last reply
      0
      • J Jo Jo

        @JonB Everything worked except for the "Date Modified" column. It turned out that Qt returns this date as a QString. I had to convert this string to QDateTime. Now the code looks like this:

        class CustomSortFilterProxyModel : public QSortFilterProxyModel
        {
            QList<int> m_dtCols{3,4};
        public:
            explicit CustomSortFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
        
        protected:
            bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
            {
                auto model = (QFileSystemModel*)sourceModel();
                bool isLeftDir = model->isDir(left);
                bool isRightDir = model->isDir(right);
        
                if ((isLeftDir && isRightDir) || (!isLeftDir && !isRightDir))
                {
                    auto leftName  = model->data(left,  Qt::DisplayRole);
                    auto rightName = model->data(right, Qt::DisplayRole);
        
                    //return (leftName.toDateTime() < rightName.toDateTime()); // OK, works fine for dates
        
                    if (m_dtCols.contains(sortColumn()))
                    {
                        if (sortColumn() == 3)
                        {
                            QDateTime dt1 = QDateTime::fromString(leftName.toString(), "M/d/yyyy h:mm AP");
                            QDateTime dt2 = QDateTime::fromString(rightName.toString(), "M/d/yyyy h:mm AP");
                            return dt1 < dt2;
                        }
        
                        return (leftName.toDateTime() < rightName.toDateTime());
                    }
        
                    const int compare = QString::localeAwareCompare(leftName.toString(), rightName.toString());
        
                    if(compare != 0) {
                        return compare < 0;
                    }
                }
                else if (isLeftDir)
                {
                    return true;
                }
        
                return false;
            }
        };
        

        However, I'm not sure that I'm setting the date format correctly. It can change depending on the OS settings, or am I wrong?

        Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #16

        @Jo-Jo said in Custom sortable columns in QFileSystemModel:

        I had to convert this string to QDateTime

        You already converted the QVariant to a QDateTime above - so why do you use the way through QString now again?

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        J 1 Reply Last reply
        0
        • Christian EhrlicherC Christian Ehrlicher

          @Jo-Jo said in Custom sortable columns in QFileSystemModel:

          I had to convert this string to QDateTime

          You already converted the QVariant to a QDateTime above - so why do you use the way through QString now again?

          J Offline
          J Offline
          Jo Jo
          wrote on last edited by Jo Jo
          #17

          @Christian-Ehrlicher said in Custom sortable columns in QFileSystemModel:

          You already converted the QVariant to a QDateTime above - so why do you use the way through QString now again?

          Because "Date Modified" column is created by Qt and Qt using QString for this column. If I convert QVariant to QDateTime, in this case comparison does not work properly

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #18

            Then you should debug why ... e.g. with a qDebug() statement as @JonB already wrote some time ago....

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            0
            • J Jo Jo

              @JonB Everything worked except for the "Date Modified" column. It turned out that Qt returns this date as a QString. I had to convert this string to QDateTime. Now the code looks like this:

              class CustomSortFilterProxyModel : public QSortFilterProxyModel
              {
                  QList<int> m_dtCols{3,4};
              public:
                  explicit CustomSortFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
              
              protected:
                  bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
                  {
                      auto model = (QFileSystemModel*)sourceModel();
                      bool isLeftDir = model->isDir(left);
                      bool isRightDir = model->isDir(right);
              
                      if ((isLeftDir && isRightDir) || (!isLeftDir && !isRightDir))
                      {
                          auto leftName  = model->data(left,  Qt::DisplayRole);
                          auto rightName = model->data(right, Qt::DisplayRole);
              
                          //return (leftName.toDateTime() < rightName.toDateTime()); // OK, works fine for dates
              
                          if (m_dtCols.contains(sortColumn()))
                          {
                              if (sortColumn() == 3)
                              {
                                  QDateTime dt1 = QDateTime::fromString(leftName.toString(), "M/d/yyyy h:mm AP");
                                  QDateTime dt2 = QDateTime::fromString(rightName.toString(), "M/d/yyyy h:mm AP");
                                  return dt1 < dt2;
                              }
              
                              return (leftName.toDateTime() < rightName.toDateTime());
                          }
              
                          const int compare = QString::localeAwareCompare(leftName.toString(), rightName.toString());
              
                          if(compare != 0) {
                              return compare < 0;
                          }
                      }
                      else if (isLeftDir)
                      {
                          return true;
                      }
              
                      return false;
                  }
              };
              

              However, I'm not sure that I'm setting the date format correctly. It can change depending on the OS settings, or am I wrong?

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

              @Jo-Jo said in Custom sortable columns in QFileSystemModel:

              Everything worked except for the "Date Modified" column. It turned out that Qt returns this date as a QString.

              I am surprised at this, but untested. You are now talking about a "Date Modified" column inbuilt into QFileSystemModel, and not the "creation date" column you added for your birthTime()? But that is QDateTime QFileSystemModel::lastModified(). So I don't understand where you are getting any string for a datetime which you need to convert.

              J 1 Reply Last reply
              0
              • JonBJ JonB

                @Jo-Jo said in Custom sortable columns in QFileSystemModel:

                Everything worked except for the "Date Modified" column. It turned out that Qt returns this date as a QString.

                I am surprised at this, but untested. You are now talking about a "Date Modified" column inbuilt into QFileSystemModel, and not the "creation date" column you added for your birthTime()? But that is QDateTime QFileSystemModel::lastModified(). So I don't understand where you are getting any string for a datetime which you need to convert.

                J Offline
                J Offline
                Jo Jo
                wrote on last edited by
                #20

                @JonB said in Custom sortable columns in QFileSystemModel:

                You are now talking about a "Date Modified" column inbuilt into QFileSystemModel, and not the "creation date" column you added for your birthTime()?

                Yes. This column value is QString, not QDateTime. You may check sources: https://codebrowser.dev/qt5/qtbase/src/widgets/dialogs/qfilesystemmodel.cpp.html#808

                JonBJ 1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #21

                  Thast's why https://doc.qt.io/qt-6/qfilesystemmodel.html#lastModified is there.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  2
                  • J Jo Jo

                    @JonB said in Custom sortable columns in QFileSystemModel:

                    You are now talking about a "Date Modified" column inbuilt into QFileSystemModel, and not the "creation date" column you added for your birthTime()?

                    Yes. This column value is QString, not QDateTime. You may check sources: https://codebrowser.dev/qt5/qtbase/src/widgets/dialogs/qfilesystemmodel.cpp.html#808

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

                    @Jo-Jo
                    I now see that, and see from https://codebrowser.dev/qt5/qtbase/src/widgets/dialogs/qfilesystemmodel.cpp.html#737 that it is called in the implementation of QFileSystemModel::data() for column #3, which is what I needed to know.

                    I also see it is formatted as a string with QLocale::ShortFormat. I don't know what that looks like, I don't know how "precise" it is (e.g. down to, say, milliseconds or likely not?), I don't know what the locale-aware formatting does with it. Putting all these together it would not surprise me if it is unsuitable for sorting, and/or for converting back (accurately) to a datetime/comparing. Whereas the birthTime() you use for your extra column is indeed a datetime type and is suitable.

                    Hence, as both I and @Christian-Ehrlicher have said, I would use lastModified() just as you use birthDate() for this column in your own code for data() method.

                    1 Reply Last reply
                    1
                    • J Offline
                      J Offline
                      Jo Jo
                      wrote on last edited by
                      #23

                      @Christian-Ehrlicher @JonB agree with you guys about lastModified, thanks!

                      1 Reply Last reply
                      1

                      • Login

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