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. Shuffling the items on QtableView

Shuffling the items on QtableView

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 2.2k Views 2 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.
  • S Offline
    S Offline
    samdol
    wrote on last edited by
    #1

    I made the following model/view structure.
    mymodel=new QAbstractTableModel;
    proxyModel = new StarSortFilterProxyModel();
    proxyModel->setDynamicSortFilter(true);
    tableView=new QTableView(this);
    tableView->setModel(proxyModel);

    I want to shuffle the order of items on tableview without changing the order of items on base model(mymodel). Can anyone explain how I can randomly order it? It seems I need to shuffle the order of indexes of proxyModel. Thank you.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      You need to implement your own QSortFilterProxyModel that will do the shuffling.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • S Offline
        S Offline
        samdol
        wrote on last edited by
        #3

        Which member functions of QSortFilterProxyModel should I reimplement to create shuffling function?

        thamT 1 Reply Last reply
        0
        • S samdol

          Which member functions of QSortFilterProxyModel should I reimplement to create shuffling function?

          thamT Offline
          thamT Offline
          tham
          wrote on last edited by tham
          #4

          @samdol

          protected:
              bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
          

          You can use std::random to determine false and true randomly.

          bool some_class::lessThan(const QModelIndex&, const QModelIndex&) const
          {
              return dis(gen) < 1;
          }
          

          The example of std::random(full version locate at here)

          #include <random>
          #include <iostream>
           
          int main()
          {
              std::random_device rd;
              std::mt19937 gen(rd());
              std::uniform_int_distribution<> dis(0, 1);
           
              for (int n=0; n<10; ++n)
                  std::cout << dis(gen) << ' ';
              std::cout << '\n';
          }
          

          random_device may or may not generate random seed(unless it do not work for mingw5.3), in this case qrand() could be a replacement.

          S 1 Reply Last reply
          2
          • M Offline
            M Offline
            mjsurette
            wrote on last edited by mjsurette
            #5

            I had a similar problem a couple of months ago and @VRonin suggested I take a look at the KDE API. https://api.kde.org/frameworks/kitemmodels/html/classKExtraColumnsProxyModel.html. While I did not use it directly, I did use the techniques in there to build a custom class that did just what you ask.

            // reorderColProxyModel.h
            #pragma once
            
            #include "constants.h"
            
            #include <QObject>
            #include <QIdentityProxyModel>
            
            class ReOrderColProxyModel : public QIdentityProxyModel
            {
            public:
                ReOrderColProxyModel(QObject *parent = Q_NULLPTR);
                ~ReOrderColProxyModel() = default;
            
                QVariant data(const QModelIndex &proxyIndex, int role) const;
                QVariant headerData(int section, Qt::Orientation orientation, int role) const;
            
            protected:
                int columnCount(const QModelIndex &) const;
            
            private:
                constexpr static int _size= 15;
                // list columns in order to be seen
                REPAIR_STATUS_COLUMN _forwardLookup[_size]
                {
                    REPAIR_STATUS_COLUMN::RMA_NUMBER,
                    REPAIR_STATUS_COLUMN::WORKDAYS,
                    REPAIR_STATUS_COLUMN::CUSTOMER_NAME,
                    REPAIR_STATUS_COLUMN::LOCATION,
                    REPAIR_STATUS_COLUMN::MODEL,
            
                    REPAIR_STATUS_COLUMN::RMA_ISSUE_DATE,
                    REPAIR_STATUS_COLUMN::RCVD_DATE,
                    REPAIR_STATUS_COLUMN::DONE_DATE,
                    REPAIR_STATUS_COLUMN::SHIP_DATE,
                    REPAIR_STATUS_COLUMN::CURRENT_STATUS,
            
                    REPAIR_STATUS_COLUMN::SPECIAL_NOTES,
                    REPAIR_STATUS_COLUMN::TECH,
                    REPAIR_STATUS_COLUMN::QB_NOTES,
                    REPAIR_STATUS_COLUMN::RMA_NOTES,
                    REPAIR_STATUS_COLUMN::RMA_UNIT_NOTES
                };
            };
            
            
            // reorderColProxyModel.cpp
            #include "reorderColProxyModel.h"
            
            //----------------------------------------------------------------------
            ReOrderColProxyModel::ReOrderColProxyModel(QObject *parent)
                :QIdentityProxyModel(parent)
            {}
            
            //----------------------------------------------------------------------
            QVariant ReOrderColProxyModel::data(const QModelIndex &proxyIndex, int role) const
            {
                int row= proxyIndex.row();
                int col= proxyIndex.column();
                QModelIndex ix= sourceModel()->index(row,static_cast<int>(_forwardLookup[col]));
                return ix.data(role);
            }
            
            //----------------------------------------------------------------------
            QVariant ReOrderColProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
            {
                return sourceModel()->headerData(static_cast<int>(_forwardLookup[section]),orientation,role);
            }
            
            //----------------------------------------------------------------------
            int ReOrderColProxyModel::columnCount(const QModelIndex &) const
            {
                return _size;
            }
            
            

            Where REPAIR_STATUS_COLUMN is an enum of the columns in the table. _forwardLookup is in the order that you want the columns to appear. Being a proxymodel, you just set the source model and use it to display the columns in the order you like.

            You should look at the code in the link. It is much more generalised and capable than this and just good code to learn from.

            Edit:
            The above link is not the solution to your problem. My original problem was two-fold. First I had to add a computed column which wouldn't reflect back into the original model then I had to reorder the columns. The link to the class which did the re-ordering is here: https://api.kde.org/frameworks/kitemmodels/html/classKRearrangeColumnsProxyModel.html

            You will notice that it subclasses QIdentityProxyModel which is a better fit than QSortFilterProxyModel.

            I ended up using a simplified version of each class, implementing only the bare necessities, but I only had a single use. YMMV

            Mike

            1 Reply Last reply
            1
            • thamT tham

              @samdol

              protected:
                  bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
              

              You can use std::random to determine false and true randomly.

              bool some_class::lessThan(const QModelIndex&, const QModelIndex&) const
              {
                  return dis(gen) < 1;
              }
              

              The example of std::random(full version locate at here)

              #include <random>
              #include <iostream>
               
              int main()
              {
                  std::random_device rd;
                  std::mt19937 gen(rd());
                  std::uniform_int_distribution<> dis(0, 1);
               
                  for (int n=0; n<10; ++n)
                      std::cout << dis(gen) << ' ';
                  std::cout << '\n';
              }
              

              random_device may or may not generate random seed(unless it do not work for mingw5.3), in this case qrand() could be a replacement.

              S Offline
              S Offline
              samdol
              wrote on last edited by
              #6

              @tham

              Thank you very much. It works.
              I created extra shuffle_colmun in base model.
              Instead of std::random() I simply used rand() to generate integer between 0-20. So the result rand()%20 < 10 is half true and half false. It means if I sort contents by shuffle_colmun, it shuffles the contents without changing the order of original base model.

              class MySortFilterProxyModel : public QSortFilterProxyModel
              {
              Q_OBJECT

              public:
              MySortFilterProxyModel(){}

              protected:
              bool lessThan(const QModelIndex &left, const QModelIndex &right) const
              {
              if(left.column()== shuffle_column)
              return rand()%20 < 10;
              else
              return QSortFilterProxyModel::lessThan(left, right);
              }
              };

              void shuffling()
              {
              if(tableView->horizontalHeader()->sortIndicatorOrder()==Qt::DescendingOrder)
              tableView->sortByColumn(shuffle_column, Qt::AscendingOrder);
              else
              tableView->sortByColumn(shuffle_column, Qt::DescendingOrder);
              }

              1 Reply Last reply
              1
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                You can simplify the shuffling function:

                void shuffling()
                {
                tableView->sortByColumn(shuffle_column, tableView->horizontalHeader()->sortIndicatorOrder());
                }
                

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                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