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

Sorting Numerical Values in QTableView with Widgets!



  • Hi,

    We are using QTableView to create a table for our desktop application.

    • Qt version : 5.9.7.
    • We have to use QTableView. (Not QTableWidget)
    • We have to use QStandardItemModel.
    • We do not want to use QItemDelegate, if possible.
    • We added checkboxes and pushbuttons into some columns using setIndexWidget() method.
    • Table contains strings and numerical values but they are all represented with QStrings inside the QStandardItemModel.

    We are trying to sort columns in the table with QStandardItemModel's sort() method; however, it sorts all of the values as strings as shown below.

    Sorted.png

    The sorting is not correct. First value should be : 2.982 and the last value should be : 5623.902.

    After that attempt, we have decided to use QSortFilterProxyModel. However, this time when we sort the table, the widgets such as checkboxes or pushbuttons are disappeared.

    SortedQProxy.png

    We think that checkboxes and pushbuttons are disappeared; because, they are not copyable.

    Is there any method to sort the table correctly without causing checkboxes and pushbuttons to disappear?



  • @Oktay-K When using setIndexWidget, you should keep using one model as the view's model, don't change.
    Actually, if you only want to sort the numbers properly and no further requirement on the display format, a simple way is that don't save the value in string.
    For example, instead of

    item->setText("12.12");
    

    using

    item->setData(12.12, Qt::DisplayRole);
    

    Then it will be sorted properly and there will be no need to use QSortFilterProxyModel.

    And if you have requirements on the display format / want to save a string to Qt::DisplayRole, you can also define a sort role.
    Then save the value both in string and in numerical value.

    #define SORT_ROLE Qt::UserRole + 1
    ...
    QStandardItem *item = new QStandardItem();
    item->setText("12.12");
    item->setData(12.12, SORT_ROLE);
    ...
    p_std_model->setSortRole(SORT_ROLE);
    

    I think it is simpler than using a proxy model.



  • Hi, did you call setIndexWidget with a mapped index?



  • @Bonnie

    QStandardItemModel *p_model = static_cast<QStandardItemModel *> (this->model());
    QCheckBox *p_check_box = new QCheckBox();
    setIndexWidget(p_model->index(row,in_column_pos), p_check_box);
    


  • @Oktay-K Since you said you are using QSortFilterProxyModel for the view, I think at least you should use indexes of QSortFilterProxyModel, not QStandardItemModel.
    In your code, this is the table view, right? How do you use QSortFilterProxyModel then?



  • @Bonnie
    Yes, this is QTableView. We created a class named SortModel which inherits from QSortFilterProxyModel. We used SortModel as shown in the below.

    SortModel *p_model = new SortModel(this);
    QStandardItemModel * p_std_model = static_cast<QStandardItemModel*>(this->model());
    if(Q_NULLPTR == p_model)
         return;   
    if(Q_NULLPTR == p_std_model)
         return;
    p_model->setSourceModel(p_std_model);
    p_model->setSortRole(Qt::ItemDataRole::DisplayRole);
    
    
    p_model->sort(column,Qt::AscendingOrder);
    QTableView::setModel(p_model);
    

    We tried your suggestion and widgets are still disappering.



  • @Oktay-K When using setIndexWidget, you should keep using one model as the view's model, don't change.
    Actually, if you only want to sort the numbers properly and no further requirement on the display format, a simple way is that don't save the value in string.
    For example, instead of

    item->setText("12.12");
    

    using

    item->setData(12.12, Qt::DisplayRole);
    

    Then it will be sorted properly and there will be no need to use QSortFilterProxyModel.

    And if you have requirements on the display format / want to save a string to Qt::DisplayRole, you can also define a sort role.
    Then save the value both in string and in numerical value.

    #define SORT_ROLE Qt::UserRole + 1
    ...
    QStandardItem *item = new QStandardItem();
    item->setText("12.12");
    item->setData(12.12, SORT_ROLE);
    ...
    p_std_model->setSortRole(SORT_ROLE);
    

    I think it is simpler than using a proxy model.



  • @Bonnie

    It works. Thank you for everything. Have a great day.


Log in to reply