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.
  • JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by
    #12

    I'm not sure what "not workiing properly" means? What does not work right? Have you put a break or qDebug() statements here to see/verify what it is comparing and returning?

    J 1 Reply Last reply
    0
    • JonBJ JonB

      I'm not sure what "not workiing properly" means? What does not work right? Have you put a break or qDebug() statements here to see/verify what it is comparing and returning?

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

      @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 1 Reply Last reply
      0
      • 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 Online
        JonBJ Online
        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 Online
            Christian EhrlicherC Online
            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 Online
                Christian EhrlicherC Online
                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 Online
                  JonBJ Online
                  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 Online
                      Christian EhrlicherC Online
                      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 Online
                        JonBJ Online
                        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