Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QML How to sort a tableView just by clicking on the header of the column



  • 0

    so in my project I'm using a tableview which has model: tableModel fopm Qt.labs.qmlmodels 1.0; so I want sort it using some methods , I find the class QAbsructProxyModel , I dont know if I used it well but I found problems on filtring and sorting here is below my code, thanks in advance` neeed help please```

    import QtQuick 2.15
    import QtQuick.Window 2.12
    import Qt.labs.qmlmodels 1.0
    import QtQuick.Controls 2.15
    import QtQml.Models 2.15

    import org.qtproject.example 1.0

    ApplicationWindow {
    width: 1000
    height: 400
    visible: true

     header: ToolBar {
        TextField {
            id: searchBox
    
    
            placeholderText: "Search..."
            inputMethodHints: Qt.ImhNoPredictiveText
    
            //width: window.width / 5 * 2
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
        }
    }
    
    
    
    TableView {
        id:tableView
        anchors.fill: parent
        //sortIndicatorVisible: true
    
        //anchors.topMargin: 30
        columnSpacing: 1
        rowSpacing: 3
        anchors.topMargin:30
        //boundsBehavior: Flickable.StopAtBounds
    
    
    
        model:SortFilterProxyModel {
            id: proxyModel
            source: sourceModel.rowCount> 0 ? sourceModel : null
            onSourceChanged: console.log(source+" source")
    
            sortOrder: Qt.AscendingOrder//tableView.sortIndicatorOrder
    
            sortCaseSensitivity: Qt.CaseInsensitive
            sortRole: sourceModel.rowCount > 0 ? " nomdetrame": ""
            onSortRoleChanged: console.log(" role")
            filterString: "*" + searchBox.text + "*"
            //onFilterStringChanged: console.log(filterString)
            filterSyntax: SortFilterProxyModel.Wildcard
            filterCaseSensitivity: Qt.CaseInsensitive
        }
    
            TableModel {
            id:sourceModel
    
    
            TableModelColumn{ display: " teta"}
            TableModelColumn { display: "visibilite" }
            TableModelColumn { display: "couleur" }
            TableModelColumn{ display: "chaine_can"}
            TableModelColumn{ display: "nomdetrame" }
            TableModelColumn{ display: "nondusignal"}
            TableModelColumn { display: "valeurDec" }
            TableModelColumn { display: "valeurHex" }
            TableModelColumn { display: "TxouRx" }
    
    
            // Each row is one type of fruit that can be ordered
            rows: [
                {
                    // Each property is one cell/column.
                    teta:"+",
                    visibilite: false,
                    couleur: "red",
                    chaine_can: "CAN 4",
                    nomdetrame: "rRX",
                    nondusignal: "1.50",
                    valeurDec: "CAN 4",
                    valeurHex: "rRX",
                    TxouRx: "Tx"
                },
                {   teta:"+",
                    visibilite: false,
                    couleur: "grey",
                    chaine_can: "CAN 1",
                    nomdetrame: "rRX",
                    nondusignal: "1.5",
                    valeurDec: "CAN 4",
                    valeurHex: "rRX",
                    TxouRx: "Rx"
                },
                {   teta:"+",
                    visibilite: true,
                    couleur: "black",
                    chaine_can: "CAN 2",
                    nomdetrame: "rRX",
                    nondusignal: "1",
                    valeurDec: "CAN 4",
                    valeurHex: "RXE",
                    TxouRx: "Tx"
                }
            ]
    
    
    
        }
    
    
    
    
    
        delegate:  DelegateChooser {
    
            DelegateChoice{
                column: 0
                //width: 100
            delegate:Button{
                    id:teta
                    text:"+"
                    //anchors.fill: parent
                    onClicked:{tableView.sourceModel.appendRow({
                                                   // Each property is one cell/column.
                                                   teta:"+",
                                                   visibilite: false,
                                                   couleur: "red",
                                                   chaine_can: "CAN 4",
                                                   nomdetrame: "rRX",
                                                   nondusignal: "1.50",
                                                   valeurDec: "CAN 4",
                                                   valeurHex: "rRX",
                                                   TxouRx: "Tx"
                                               }
                                               )}
    
                }
                //z: -1
            }
    
            DelegateChoice{
                column: 1
            delegate:Rectangle{
                border.color: "black"
                implicitWidth: 80
                CheckBox{
                //anchors.fill: parent
                    anchors.centerIn: parent
                checked: model.display
    
    
            }
        }
            }
            DelegateChoice{
                column: 2
            delegate:Rectangle {
                implicitWidth: 80
                //anchors.fill: parent
                 border.color: "black"
                color: model.display
                //z: -1
            }
        }
            DelegateChoice{
                column: 3
            delegate:Rectangle{
                border.color:"black"
                implicitWidth: 80
    
                Button{
                    anchors.fill: parent
                    onClicked: console.log(currentIndex)
    

    // TextInput {
    // //textRole: "display"
    // anchors.fill: parent
    // text:model.display
    // //z: -1
    // }
    }

        }
            }
            DelegateChoice{
                column: 4
           delegate:Rectangle{
               border.color: "black"
               implicitWidth: 80
               TextInput {
                //anchors.fill: parent
                   anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 5
            delegate:Rectangle{
                border.color: "black"
                implicitWidth: 80
                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 6
            delegate:Rectangle{
                implicitWidth: 80
                border.color: "black"
                TextInput {
    

    // anchors.fill: parent
    anchors.centerIn: parent
    text:model.display
    //z: -1
    }
    }
    }
    DelegateChoice{
    column: 7
    delegate:Rectangle{
    implicitWidth: 80
    border.color: "black"

                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
                //z: -1
            }
        }
            }
            DelegateChoice{
                column: 8
            delegate:Rectangle{
                implicitWidth: 80
                border.color: "black"
                TextInput {
                //anchors.fill: parent
                    anchors.centerIn: parent
                text:model.display
    
                //z: -1
            }
            }
        }
    
    
    }
        Component.onCompleted: {
            console.log(searchBox.text)
            //console.log(tableView.model.getRow(0).couleur)}
    

    }
    }
    HorizontalHeaderView{
    id:headerView
    anchors.left: tableView.left
    syncView: tableView
    model:[" ","Visible","Couleur","Chaine_Can","NomTrame","NomSignal","ValeurDec","ValeurHex","TX/RX"]

        MouseArea{
            id:ms
            anchors.fill: parent
            hoverEnabled: true
    
    
        }
    
    }
    

    }

    
    c++
    
    include "sortfilterproxymodel.h"
    #include <QtDebug>
    #include <QtQml>
    
    SortFilterProxyModel::SortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_complete(false)
    {
        connect(this, &QSortFilterProxyModel::rowsInserted, this, &SortFilterProxyModel::countChanged);
        connect(this, &QSortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged);
        qDebug()<<"je suis entré chez moi";
    }
    
    int SortFilterProxyModel::count() const
    {
        return rowCount();
    }
    
    QObject *SortFilterProxyModel::source() const
    {
        return sourceModel();
    }
    
    void SortFilterProxyModel::setSource(QObject *source)
    {
        setSourceModel(qobject_cast<QAbstractItemModel *>(source));
        emit sourceChanged();
    }
    
    QByteArray SortFilterProxyModel::sortRole() const
    {
        return m_sortRole;
    }
    
    void SortFilterProxyModel::setSortRole(const QByteArray &role)
    {
        if (m_sortRole != role) {
            m_sortRole = role;
            if (m_complete)
                QSortFilterProxyModel::setSortRole(roleKey(role));
        }
    }
    
    void SortFilterProxyModel::setSortOrder(Qt::SortOrder order)
    {
        QSortFilterProxyModel::sort(0, order);
    }
    
    QByteArray SortFilterProxyModel::filterRole() const
    {
        return m_filterRole;
    }
    
    void SortFilterProxyModel::setFilterRole(const QByteArray &role)
    {
        if (m_filterRole != role) {
            m_filterRole = role;
            if (m_complete)
                QSortFilterProxyModel::setFilterRole(roleKey(role));
        }
    }
    
    QString SortFilterProxyModel::filterString() const
    {
        return filterRegExp().pattern();
    }
    
    void SortFilterProxyModel::setFilterString(const QString &filter)
    {
    
        setFilterRegExp(QRegExp(filter, filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(filterSyntax())));
        emit filterStringChanged();
    }
    
    
    SortFilterProxyModel::FilterSyntax SortFilterProxyModel::filterSyntax() const
    {
        return static_cast<FilterSyntax>(filterRegExp().patternSyntax());
    }
    
    void SortFilterProxyModel::setFilterSyntax(SortFilterProxyModel::FilterSyntax syntax)
    {
        setFilterRegExp(QRegExp(filterString(), filterCaseSensitivity(), static_cast<QRegExp::PatternSyntax>(syntax)));
    }
    
    QJSValue SortFilterProxyModel::get(int idx) const
    {
        QJSEngine *engine = qmlEngine(this);
        QJSValue value = engine->newObject();
        if (idx >= 0 && idx < count()) {
            QHash<int, QByteArray> roles = roleNames();
            for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it)
                value.setProperty(QString::fromUtf8(it.value()), data(index(idx, 0), it.key()).toString());
        }
        return value;
    }
    
    void SortFilterProxyModel::classBegin()
    {
    }
    
    void SortFilterProxyModel::componentComplete()
    {
        m_complete = true;
    
        if (!m_sortRole.isEmpty())
            QSortFilterProxyModel::setSortRole(roleKey(m_sortRole));
    
        if (!m_filterRole.isEmpty())
            QSortFilterProxyModel::setFilterRole(roleKey(m_filterRole));
    
    }
    
    int SortFilterProxyModel::roleKey(const QByteArray &role) const
    {
        return roleNames().key(role, -1);
    
    }
    
    QHash<int, QByteArray> SortFilterProxyModel::roleNames() const
    {
        qDebug()<<"RoleNames";
        if (QAbstractItemModel *source = sourceModel()){
            qDebug()<<"RoleNames";
            //qDebug()<< source->roleNames();
                        //qDebug()<<roleNames().key(0)<< " keys";
            return source->roleNames();}
        return QHash<int, QByteArray>();
    }
    
    bool SortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
    {
        QRegExp rx = filterRegExp();
        if (rx.isEmpty())
            return true;
        QAbstractItemModel *model = sourceModel();
        if (filterRole().isEmpty()) {
            QHash<int, QByteArray> roles = roleNames();
            for (auto it = roles.cbegin(), end = roles.cend(); it != end; ++it) {
                QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
                QString key = model->data(sourceIndex, it.key()).toString();
                if (key.contains(rx))
                    return true;
            }
            return false;
        }
        QModelIndex sourceIndex = model->index(sourceRow, 0, sourceParent);
        if (!sourceIndex.isValid())
            return true;
        QString key = model->data(sourceIndex, roleKey(filterRole())).toString();
        qDebug()<<rx;
        return key.contains(rx);
    }
    
    


  • Pleeeease neeed help



  • @ENSAO_CHEIKH Have a look at this example.
    https://github.com/albertino80/bppgrid

    I hope this will help you.


Log in to reply