PDA

View Full Version : QSortFilterProxyModel lessThan is never called.



atomic
11th April 2015, 09:01
Hi,
I have a subclass QSortFilterProxyModel with custom lessThan function to provide sort by specific columns but this function is never called. Maybe You know why?




#ifndef CUSTOMSORTFILTERPROXYMODEL_H
#define CUSTOMSORTFILTERPROXYMODEL_H

#include <QObject>
#include <QSortFilterProxyModel>
#include <QDebug>

class CustomSortFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT

enum Column {
Title,
Authors,
ReleaseDate,
About,
Format,
Image
};

public:
CustomSortFilterProxyModel();
~CustomSortFilterProxyModel();

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

private:
QList< Column > selectedColumns;
};

#endif // CUSTOMSORTFILTERPROXYMODEL_H




#include "customsortfilterproxymodel.h"

CustomSortFilterProxyModel::CustomSortFilterProxyM odel()
{

}

CustomSortFilterProxyModel::~CustomSortFilterProxy Model()
{

}

bool CustomSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
// never called, why?
qDebug()<< "Custom Sort Filter Proxy Model :: lessThan";
qDebug()<< "colums size: " << selectedColumns.size();

return false;
}


and in mainwindow


proxyModel.setSourceModel( &customTableModel );
ui->tableView->setModel( &proxyModel );

ChrisW67
11th April 2015, 21:35
The customTableModel and proxyModel are both stack allocated by the look of it. Are both objects staying in scope for the life of the view?

atomic
12th April 2015, 08:27
The customTableModel and proxyModel are both stack allocated by the look of it. Are both objects staying in scope for the life of the view?


Yes, this is my MainWindow .h



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QProgressDialog>
#include <QDesktopServices>
#include <QSortFilterProxyModel>

#include <QDebug>
#include <customtablemodel.h>
#include <inputdialog.h>
#include <sortdialog.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void insertItem();
void removeItem();
void editItem( const QModelIndex & index );

void sort();

void about();


private:
Ui::MainWindow *ui;
CustomTableModel customTableModel;
QSortFilterProxyModel proxyModel;

};

#endif // MAINWINDOW_H


Other functions from QSortFilterProxyModel like setFilterRegExp() works properly.
And sort by column



proxyModel.sort( 0 );


too, but lessThan is never called and I do not know why. When this function should be called?

Important - I use QSortFilterProxyModel with my custom model class, which inherits QAbstractTableModel so maybe I should implement some specific functions? This is my custom model class




#ifndef CUSTOMTABLEMODEL_H
#define CUSTOMTABLEMODEL_H

#include <QObject>
#include <QAbstractTableModel>

#include <QDebug>
#include <book.h>

class CustomTableModel : public QAbstractTableModel
{
Q_OBJECT

enum HeaderLabelsId {
Title,
Authors,
ReleaseDate,
About,
Format,
Image
};

public:
explicit CustomTableModel( QObject * parent = 0 );
~CustomTableModel();

int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;

QVariant data(const QModelIndex& index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex& index) const override;

void setHorizontalHeaderLabels(const QStringList &horizontalHeaderLabels);
void insertRow( const Book & book );
void removeRow(int row );
void updateRow(int editingRow , const Book & book);
const Book &row( int row );


private:
QList< Book > mBooks;
const unsigned int mColumns = 6;
QStringList mHorizontalHeaderLabels;
};

#endif // CUSTOMTABLEMODEL_H

atomic
12th April 2015, 15:46
I tested this code with QStandardItemModel and it works fine, lessThan is called properly so I think that problem is in my CustomTableModel. Maybe I forgot about some important function which should be reimplemented?

atomic
12th April 2015, 18:55
Very stupid mistake =-=. And you can see it in my code, exactly in mainwindow.h.
First I tested sorting data with QSortFilterProxyModel and when I wrote my CustomSortFilterProxyModel I forgot to change the definitions of these classes in mainwindow.h....

Sorry for that.

But I have one more question - it is a good way for sort table by multiple column? or in Qt we have better way for this?

anda_skoa
13th April 2015, 07:11
You can always sort inside your model.
I usually prefer that over using a proxy if the sorting gets more complicated.

Cheers,
_

d_stranz
13th April 2015, 19:24
But I have one more question - it is a good way for sort table by multiple column?

QSortFilterProxyModel only supports sorting on a single column. You could probably write a lessThan() method that would do a multi-level sort for a custom QSortFilterProxyModel, but the proxy is still going to maintain its state under the assumption that it is a single-column sort. As anda_skoa says, it is usually easier to do this in the source model if the sorting is complex.

yeye_olive
14th April 2015, 10:20
There is a reason for the focus on single-column sorting. If each sort is stable (which is usually expected in a UI), then you can get the lexicographic order on columns c1..cn by sorting by cn, then cn-1, ..., then c1. E.g. to sort files by date, then name, you can first click on the "name" column, then on the "date" column.

d_stranz
15th April 2015, 17:09
to sort files by date, then name, you can first click on the "name" column, then on the "date" column.

I don't think that works in a custom model (or even in the off-the-shelf QSortFilterProxyModel) - unless the model (or proxy) implements such multi-column sort behavior. How does a standard QSortFilterProxyModel know to maintain the sort on one column that contains duplicates while sorting a second column with respect to those duplicates? As far as I have seen, sorting on any column occurs independently of other columns and results in all rows being reordered solely on the sort order of the chosen column.