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. Sort QTableView by several criteria
Forum Update on Monday, May 27th 2025

Sort QTableView by several criteria

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 4 Posters 780 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 Offline
    M Offline
    Mogli123
    wrote on last edited by Mogli123
    #1

    Hello every one.

    I'm at Qt and c++ since 3 months.
    I have the following table like this picture.
    0_1542105261334_Unbenannt.PNG

    I'm trying to sort my table on the same way as you can see in the picture.
    At first all red rows which are sorted from the highest to the lowest time.
    After that the yellow and the green rows which ever are sortet from the lowest to the highest number of "Pts".

    I have the following database and fill it with an array.

    db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(":memory:");
        if (!db.open())
        {
            QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
                QObject::tr("Unable to establish a database connection.\n"
                            "This example needs SQLite support. Please read "
                            "the Qt SQL driver documentation for information how "
                            "to build it.\n\n"
                            "Click Cancel to exit."), QMessageBox::Cancel);
    
    query = new QSqlQuery;
        query->exec("Create Table CustomiseToolChange (COLOR varchar(20),"
                   "TOOLNR, TIME int, POCKETSTATUS varchar(20))");
        query->prepare("INSERT INTO CustomiseToolChange (COLOR, TOOLNR, TIME, POCKETSTATUS) "
                       "VALUES (:COLOR, :TOOLNR, :TIME, :POCKETSTATUS)");
        query->bindValue(":COLOR", "");
            return;
    ...
    
    void test_screen::fillDatabaseTableCustomiseToolChange()
    {
        for (int i = 0; i < (30 / 3); i++)
        {
            query->bindValue(":TOOLNR", arrayCustomiseToolChange[i * 3 + 0]);
            query->bindValue(":TIME", arrayCustomiseToolChange[i * 3 + 1]);
            query->bindValue(":POCKETSTATUS", arrayCustomiseToolChange[i * 3 + 2]);
            query->exec();
         }
    }
    
    

    The number of rows (for example from the yellow rows) can vary.
    Furthermore it is possible that one color not exist for an moment.

    How can I solve that problem.
    I hope you understand what I'm trying to do. (my english is not the best)

    Thank you very much.

    Regards Mogli.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      Slawomir_Piernikowski
      wrote on last edited by
      #2

      Hi
      What depends on the color of the cells?

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

        Did you already take a look at the QSortFilterProxyModel and the examples mentioned 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
        1
        • M Offline
          M Offline
          Mogli123
          wrote on last edited by Mogli123
          #4

          Hi,
          thank you for your answers.

          @Slawomir_Piernikowski
          The color stands in a hidden column from the table, for example like this. (but there is the order not correct)
          0_1542176956338_Unbenannt.PNG

          @Christian-Ehrlicher
          Yes, I looked already at the docu but I'm not shure how can I manage that.
          I hope someone can give me a tip or a smal example, for better understanding.

          VRoninV 1 Reply Last reply
          0
          • M Mogli123

            Hi,
            thank you for your answers.

            @Slawomir_Piernikowski
            The color stands in a hidden column from the table, for example like this. (but there is the order not correct)
            0_1542176956338_Unbenannt.PNG

            @Christian-Ehrlicher
            Yes, I looked already at the docu but I'm not shure how can I manage that.
            I hope someone can give me a tip or a smal example, for better understanding.

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

            @Mogli123 said in Sort QTableView by several criteria:

            but I'm not shure how can I manage that.
            I hope someone can give me a tip or a smal example, for better understanding.

            class ToolSorter : public QSortFilterProxyModel {
            Q_OBJECT
            Q_DISABLE_COPY(ToolSorter)
            public:
            explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){}
            protected:
            // this method is used by the proxy to determine if the index source_left should come before the index source_right*/
            bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{
            const int leftRow = source_left.row(); // get the rows of the indexes
            const int rightRow= source_right.row();
            const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data
            const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString();
            switch(colorCompare(leftColor,rightColor)){ // compare the colours
            case 1: return true; 
            case -1: return false;
            default:
            return // if colours are the same comapre the time
            sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
            < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data()
            ;
            }
            }
            private:
            /* Compares the strings with colous:
            returns 0 if the colours are the same
            returns 1 if the colour left should go above colour right
            returns -1 if the colour right should go above colour left
            */
            char colorCompare(const QString& left, const QString& right) const{
            if(left==right) return 0;
            if(left == QLatin1String("yellow")) return 1;
            if(right== QLatin1String("yellow")) return -1;
            if(left == QLatin1String("red")) return 1;
            if(right== QLatin1String("red")) return -1;
            Q_UNREACHABLE();
            return -2;
            }
            };
            

            "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 2 Replies Last reply
            3
            • VRoninV VRonin

              @Mogli123 said in Sort QTableView by several criteria:

              but I'm not shure how can I manage that.
              I hope someone can give me a tip or a smal example, for better understanding.

              class ToolSorter : public QSortFilterProxyModel {
              Q_OBJECT
              Q_DISABLE_COPY(ToolSorter)
              public:
              explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){}
              protected:
              // this method is used by the proxy to determine if the index source_left should come before the index source_right*/
              bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{
              const int leftRow = source_left.row(); // get the rows of the indexes
              const int rightRow= source_right.row();
              const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data
              const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString();
              switch(colorCompare(leftColor,rightColor)){ // compare the colours
              case 1: return true; 
              case -1: return false;
              default:
              return // if colours are the same comapre the time
              sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
              < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data()
              ;
              }
              }
              private:
              /* Compares the strings with colous:
              returns 0 if the colours are the same
              returns 1 if the colour left should go above colour right
              returns -1 if the colour right should go above colour left
              */
              char colorCompare(const QString& left, const QString& right) const{
              if(left==right) return 0;
              if(left == QLatin1String("yellow")) return 1;
              if(right== QLatin1String("yellow")) return -1;
              if(left == QLatin1String("red")) return 1;
              if(right== QLatin1String("red")) return -1;
              Q_UNREACHABLE();
              return -2;
              }
              };
              
              M Offline
              M Offline
              Mogli123
              wrote on last edited by Mogli123
              #6

              @VRonin
              Thank you for your answer.

              Can you explain your code step by step, please?
              I'm not sure how it works.
              Sorry I'm a noob.

              1 Reply Last reply
              0
              • VRoninV VRonin

                @Mogli123 said in Sort QTableView by several criteria:

                but I'm not shure how can I manage that.
                I hope someone can give me a tip or a smal example, for better understanding.

                class ToolSorter : public QSortFilterProxyModel {
                Q_OBJECT
                Q_DISABLE_COPY(ToolSorter)
                public:
                explicit ToolSorter(QObject* parent = Q_NULLPTR) : QSortFilterProxyModel(parent){}
                protected:
                // this method is used by the proxy to determine if the index source_left should come before the index source_right*/
                bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE{
                const int leftRow = source_left.row(); // get the rows of the indexes
                const int rightRow= source_right.row();
                const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data
                const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString();
                switch(colorCompare(leftColor,rightColor)){ // compare the colours
                case 1: return true; 
                case -1: return false;
                default:
                return // if colours are the same comapre the time
                sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
                < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data()
                ;
                }
                }
                private:
                /* Compares the strings with colous:
                returns 0 if the colours are the same
                returns 1 if the colour left should go above colour right
                returns -1 if the colour right should go above colour left
                */
                char colorCompare(const QString& left, const QString& right) const{
                if(left==right) return 0;
                if(left == QLatin1String("yellow")) return 1;
                if(right== QLatin1String("yellow")) return -1;
                if(left == QLatin1String("red")) return 1;
                if(right== QLatin1String("red")) return -1;
                Q_UNREACHABLE();
                return -2;
                }
                };
                
                M Offline
                M Offline
                Mogli123
                wrote on last edited by
                #7

                @VRonin

                At first thank you very much for helping :).

                I have implement your code but it is not completly correct (If I copied it correctly) and I not understand it realy.
                I see you tried to make it understanderbel through inserting coments but I still did not understand it completely.

                Which value get the right- and leftRow?
                The same with the QStrings right- and leftColor

                thats "my" code and the result:

                .h

                class sorter : public QSortFilterProxyModel
                {
                    Q_OBJECT
                    Q_DISABLE_COPY(sorter)
                
                public:
                
                    explicit sorter(QObject* parent = Q_NULLPTR);
                
                protected:
                    bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE;
                
                private:
                    char colorCompare(const QString& left, const QString& right) const;
                };
                
                

                .cpp

                sorter::sorter(QObject *parent) : QSortFilterProxyModel(parent)
                {
                
                }
                
                //Methoden
                
                bool sorter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
                {
                // get the rows of the indexes
                    const int leftRow = source_left.row();
                    const int rightRow= source_right.row();
                    const QString leftColor = sourceModel()->index(leftRow,0/*column with the colour*/,source_left.parent()).data().toString(); // get the colour data
                    const QString rightColor = sourceModel()->index(rightRow,0/*column with the colour*/,source_right.parent()).data().toString();
                // compare the colours
                    switch(colorCompare(leftColor,rightColor))
                    {
                        case 1: return true;
                        case -1: return false;
                        default:
                // if colours are the same comapre the time
                        return
                        sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
                        < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data();
                    }
                }
                
                char sorter::colorCompare(const QString& left, const QString& right) const
                {
                    if(left==right)
                    {
                        return 0;
                    }
                    if(left == QLatin1String("yellow"))
                    {
                        return 1;
                    }
                    if(right== QLatin1String("yellow"))
                    {
                        return -1;
                    }
                    if(left == QLatin1String("red"))
                    {
                        return 1;
                    }
                    if(right== QLatin1String("red"))
                    {
                        return -1;
                    }
                //wenn keines der Bedingungen eintrift wird -2 zurückgegeben
                    Q_UNREACHABLE();
                    return -2;
                }
                

                table.cpp

                    mySorter = new sorter(this);
                    mySorter->setSourceModel(myTableCustomiseToolChange);
                    myTableview->setModel(mySorter);
                    //Tabelle wird sortiert
                    myTableview->setSortingEnabled(true);
                

                0_1542192034029_Unbenannt.PNG

                The green rows should be below the yellow rows and the green and yellow rows should sort from the lowest to the highest number.
                The sorting from the red rows are correct.

                If you could explain the methodes more in detail I will try it by my self.
                Sorry for the many questions.

                Regards mogli.

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

                  Everything seems fine, it's just sorted in descending order, you can call myTableview->model()->sort(0,Qt::AscendingOrder); to change the order to ascending

                  "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

                    Everything seems fine, it's just sorted in descending order, you can call myTableview->model()->sort(0,Qt::AscendingOrder); to change the order to ascending

                    M Offline
                    M Offline
                    Mogli123
                    wrote on last edited by
                    #9

                    @VRonin

                    Now it works!!!

                    thank you very much!!!

                    I changed it following :
                    .cpp

                            if (leftColor == "red")
                            {
                                return
                                sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
                                < sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data();
                            }
                            else
                            {
                                return
                                sourceModel()->index(leftRow,2/*column with the time*/,source_left.parent()).data()
                                > sourceModel()->index(rightRow,2/*column with the time*/,source_left.parent()).data();
                            }
                    ...
                    
                    char sorter::colorCompare(const QString& left, const QString& right) const
                    {
                        if(left==right)
                        {
                            return 0;
                        }
                    
                    
                    
                        if(left == QLatin1String("green"))
                        {
                            return 1;
                        }
                        if(right== QLatin1String("green"))
                        {
                            return -1;
                        }
                        if(left == QLatin1String("yellow"))
                        {
                            return 1;
                        }
                        if(right== QLatin1String("yellow"))
                        {
                            return -1;
                        }
                    //wenn keines der Bedingungen eintrift wird -2 zurückgegeben
                        Q_UNREACHABLE();
                        return -2;
                    }
                    

                    table.cpp

                        mySorter = new sorter(this);
                        mySorter->setSourceModel(myTableCustomiseToolChange);
                        myTableview->setModel(mySorter);
                        //Tabelle wird sortiert
                        myTableview->setSortingEnabled(true);
                        myTableview->model()->sort(0,Qt::DescendingOrder);
                    
                    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