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. Table model , header data is getting sorted
Forum Updated to NodeBB v4.3 + New Features

Table model , header data is getting sorted

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 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.
  • ashajgA Offline
    ashajgA Offline
    ashajg
    wrote on last edited by
    #1

    Hi guys

    I am working on a Table and I want to implement sort functionality.
    I have implemented sorting but table's header is also getting sorted with my data. How can I avoid my header getting sorted along with data?

    code:

    tablemodel.h
    
    #ifndef TABLEMODEL_H
    #define TABLEMODEL_H
    #include <QDebug>
    #include <QObject>
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QAbstractTableModel>
    #include <QThread>
    #include <copydata.h>
    #include <QtCore/qsortfilterproxymodel.h>
    #include <QtQml/qjsvalue.h>
    #include <QSortFilterProxyModel>
    class TableModel :  public QAbstractTableModel
    {
        Q_OBJECT
    public:
            explicit TableModel(QObject *parent = nullptr);
    
            int rowCount(const QModelIndex & = QModelIndex()) const override;
    
            int columnCount(const QModelIndex & = QModelIndex()) const override;
    
            QVariant data(const QModelIndex &index, int role) const override;
    
            QHash<int, QByteArray> roleNames() const override;
    
            Q_INVOKABLE void updateTable(QString firstName,QString lastName,QString age);
            Q_INVOKABLE void createCopyThread();
            void addInitialData();
            static TableModel *getStaticInstance();
            QSortFilterProxyModel *getProxyModelInstance();
            enum  TableContentRole {
                TableDataRole = Qt::UserRole + 1,
                HeaderRole
            };
           Q_INVOKABLE void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
    
    private:
    
    signals:void countChanged();
    
    public slots:
    public: QString name;
            QString last_name;
            QString age_x;
    private :
            QVector<QVector<QString>>table;
            static TableModel   *m_staticInstance;
            QSortFilterProxyModel *proxyModel;
    };
    
    #endif // TABLEMODEL_H
    

    tablemodel.cpp

    #include "tablemodel.h"
    
    TableModel *TableModel::m_staticInstance = nullptr;
    
    TableModel::TableModel(QObject *parent) :QAbstractTableModel (parent)
    {
    //    m_staticInstance = new TableModel();
    }
    
    int TableModel::rowCount(const QModelIndex &) const
    {
        return table.size();
    }
    
    int TableModel::columnCount(const QModelIndex &) const
    {
        return table.at(0).size();
    }
    
    QVariant TableModel::data(const QModelIndex &index, int role) const
    { if (role != TableDataRole && role != HeaderRole)
            return QVariant();
    
        if(role == TableDataRole) {
            return table.at(index.row()).at(index.column());
        }
        else if(role == HeaderRole) {
            if(index.row() == 0)
                return true;
            else
                return false;
        }
    
        qDebug()<<"count";
    
        return QVariant();
    }
    
    
    QHash<int, QByteArray> TableModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
        roles[TableDataRole] = "tableData";
        roles[HeaderRole] = "headerData";
        return roles;
    }
    
    void TableModel::updateTable(QString firstName, QString lastName, QString age)
    {
        name = firstName;
        last_name = lastName;
        age_x = age;
        qDebug()<<"FIRSTNAME IS "<<name<<"\n"<<"LASTNAME IS"<<last_name<<"\n"<<"AGE IS "<<age_x<<"\n";
        qDebug()<<"INDEX : "<<table.size();
       // table.append({name,last_name,age_x});
         QModelIndex indexPos=index(5,0);
         QModelIndex indexPosLast=index(5,2);
         qDebug() << "TableModel:" << table;
       //  emit dataChanged(indexPos,indexPosLast);
    
    
    
    
    
         beginInsertRows(QModelIndex(), table.size(),table.size());
    
         table.append({name,last_name,age_x});
         endInsertRows();
    
    
    
    }
    
    void TableModel::createCopyThread()
    {
        QThread *workerthread = new QThread();
        CopyData *worker = new CopyData(table);
        worker->moveToThread(workerthread);
    
        //STARTED
        QObject::connect(workerthread,SIGNAL(started()),worker,SLOT(copyTable()));
        QObject::connect(worker,SIGNAL(workFinished()),workerthread,SLOT(quit()));
        QObject::connect(workerthread,SIGNAL(finished()),worker,SLOT(deleteLater()));
        QObject::connect(workerthread,SIGNAL(finished()),workerthread,SLOT(deleteLater()));
        //FINISHED
        workerthread->start();
    }
    
    void TableModel::addInitialData()
    {
        table.append({"TIME","TYPE","MESSAGE"});
        table.append({"31-Oct-2018 11:34","Event","Service mode"});
        table.append({"8-Oct-2018 12:30","Event","System On"});
        table.append({"6-Oct-2018 12:40","Alarm","Ppeak low inactive"});
        table.append({"20-Oct-2018 13:50","Alarm","Apnea inactive"});
        table.append({"22-Oct-2018 11:34","Event","Service mode"});
        table.append({"3-Oct-2018 12:30","Event","System On"});
        table.append({"4-Oct-2018 12:40","Alarm","Ppeak low inactive"});
        table.append({"1-Oct-2018 13:50","Alarm","Apnea inactive"});
        table.append({"31-Oct-2018 17:34","Event","Service mode"});
        table.append({"31-Oct-2018 18:30","Event","System On"});
        table.append({"31-Oct-2018 12:40","Alarm","Ppeak low inactive"});
        table.append({"31-Oct-2018 13:50","Alarm","Apnea inactive"});
    }
    
    TableModel *TableModel::getStaticInstance()
    {
            if(m_staticInstance == nullptr)
            m_staticInstance = new TableModel();
            return m_staticInstance;
    }
    
    QSortFilterProxyModel *TableModel::getProxyModelInstance()
    {
        proxyModel = new QSortFilterProxyModel();
        return proxyModel;
    }
    
    void TableModel::sort(int column, Qt::SortOrder order)
    {
              proxyModel->sort(0,Qt::AscendingOrder);  //hard coded just for testing 
               qDebug("Sorting by column %d", column);
    
    }
    

    defined in main.cpp

    TableModel *t1 = TableModel::getStaticInstance();//Model
         QSortFilterProxyModel  *proxyModel =t1 ->getProxyModelInstance();
         proxyModel->setSourceModel(t1);
         proxyModel->setSortRole(TableModel::TableDataRole);
    

    I am calling sort() function from qml.

    MouseArea
            {
                anchors.fill:parent
                onClicked:
                {
                tableModelController.sort(0,Qt.AscendingOrder)
    
                }
            }
    
        
    

    Before sort Result:0_1562155604812_Beforesort.PNG

    after sort result:

    0_1562155634627_aftersort.PNG

    
    So how can I fix header to first row only?
    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Simply reimplement headerData() instead returning the header data in data() - data() is only there to return the content, not the header data.

      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
      3
      • ashajgA Offline
        ashajgA Offline
        ashajg
        wrote on last edited by
        #3

        Hi @Christian-Ehrlicher

        Thanks for help!!

        I have implemented headerData like this:

        QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
        {
        
                 qDebug()<<"header called";
                if (orientation == Qt::Horizontal && role == HeaderRole) {
                    if (section == 0) {
                        return tr("TIME");
                    } else if (section == 1) {
                        return tr("EVENT");
                    }
                    else if(section == 2)
                    {
                         return tr("MESSAGE");
        
                    }
                }
                return QVariant();
        }
        
        
        QVariant TableModel::data(const QModelIndex &index, int role) const
        { if (role != TableDataRole && role != HeaderRole)
                return QVariant();
        
            if(role == TableDataRole) {
                return table.at(index.row()).at(index.column());
            }
          //  else if(role == HeaderRole) {
          //      if(index.row() == 0)
               //     return true;
            //    else
               //     return false;
            //}
        
        
            qDebug()<<"count";
        
            return QVariant();
        }
        

        but I am unable to get header data.
        Do I have to call this function?

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

          You have to return something for Qt::DisplayRole: https://doc.qt.io/qt-5/qt.html#ItemDataRole-enum

          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
          4
          • ashajgA Offline
            ashajgA Offline
            ashajg
            wrote on last edited by ashajg
            #5

            hi @Christian-Ehrlicher

            I didn't got what I have to return.

            when I went through the documentation (table ) it was showing Qt::DisplayRole 0.

            JonBJ 1 Reply Last reply
            0
            • ashajgA ashajg

              hi @Christian-Ehrlicher

              I didn't got what I have to return.

              when I went through the documentation (table ) it was showing Qt::DisplayRole 0.

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

              @ashajg
              When a Qt view such as QTableView wants to display what's in your table model, it calls data() and headerData() with role == Qt::DisplayRole. I don't really see where your data() is handling that, but you seem to be saying the data is coming out OK but not the header. For headerData() at least you need to ditch HeaderRole and have something more like:

              if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
                  return ...
              
              1 Reply Last reply
              4
              • ashajgA Offline
                ashajgA Offline
                ashajg
                wrote on last edited by
                #7

                Hi @JonB

                Thanks for help!!! I ll remove headerData role and assign Display role so that these functions will work.

                1 Reply Last reply
                0
                • ashajgA Offline
                  ashajgA Offline
                  ashajg
                  wrote on last edited by
                  #8

                  Hi @Christian-Ehrlicher @JonB

                  one more question for the same code as sorting I am able to do. Now I want that sorted table should revert back to its previous order on a button click so is there any functionality that QT provides so that I can use it to revert my table back to original order.

                  JonBJ 1 Reply Last reply
                  0
                  • ashajgA ashajg

                    Hi @Christian-Ehrlicher @JonB

                    one more question for the same code as sorting I am able to do. Now I want that sorted table should revert back to its previous order on a button click so is there any functionality that QT provides so that I can use it to revert my table back to original order.

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

                    @ashajg
                    You are doing your sorting via QSortFilterProxyModel. Does https://doc.qt.io/qt-5/qsortfilterproxymodel.html#invalidate do what you want ("cancel" the sorting), or does it just cause it to re-sort? [But see https://stackoverflow.com/a/28107562, including the comment there.] If it's the latter it may be that you have to sort when using a QSortFilterProxyModel. In that case read https://stackoverflow.com/questions/18637727/restore-original-order-in-qtableview-qsortfilterproxy for various possibilities.

                    P.S.
                    Your code has:

                    #include <QtCore/qsortfilterproxymodel.h>
                    #include <QSortFilterProxyModel>
                    

                    I don't do Qt C++, but do you really need the first of those two includes? Looks odd to me.

                    ashajgA 1 Reply Last reply
                    3
                    • JonBJ JonB

                      @ashajg
                      You are doing your sorting via QSortFilterProxyModel. Does https://doc.qt.io/qt-5/qsortfilterproxymodel.html#invalidate do what you want ("cancel" the sorting), or does it just cause it to re-sort? [But see https://stackoverflow.com/a/28107562, including the comment there.] If it's the latter it may be that you have to sort when using a QSortFilterProxyModel. In that case read https://stackoverflow.com/questions/18637727/restore-original-order-in-qtableview-qsortfilterproxy for various possibilities.

                      P.S.
                      Your code has:

                      #include <QtCore/qsortfilterproxymodel.h>
                      #include <QSortFilterProxyModel>
                      

                      I don't do Qt C++, but do you really need the first of those two includes? Looks odd to me.

                      ashajgA Offline
                      ashajgA Offline
                      ashajg
                      wrote on last edited by
                      #10

                      @JonB I am using sort function from QSortFilterProxyModel

                      JonBJ 1 Reply Last reply
                      0
                      • ashajgA ashajg

                        @JonB I am using sort function from QSortFilterProxyModel

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

                        @ashajg

                        I am using sort function from QSortFilterProxyModel

                        I assume that relates to why you are including <QtCore/qsortfilterproxymodel.h>(?). But if it's not exposed from <QSortFilterProxyModel>(?) then maybe you're not supposed to use it that way? Anyway, as I said, I leave it to you.

                        The important stuff to your situation is in my first paragraph.

                        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