Russian Qt Forum

Qt => Дополнительные компоненты => Тема начата: Пантер от Декабрь 15, 2009, 18:02



Название: QSortFilterProxyModel с сортировкой по нескольким столбцам.
Отправлено: Пантер от Декабрь 15, 2009, 18:02
Всем доброго. Не заметил, что уже ранее на форуме выкладывали решение, и сделал своё. Вроде, получилось немного попроще, судить вам.

newsortfilterproxymodel.h
Код
C++ (Qt)
#ifndef NEWSORTFILTERPROXYMODEL_H
#define NEWSORTFILTERPROXYMODEL_H
 
#include <QtGui/QSortFilterProxyModel>
 
class NewSortFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
 
private:
QList<QPair<int, Qt::SortOrder> > m_sortedColumns;
Qt::SortOrder m_sortOrder;
 
public:
NewSortFilterProxyModel(QObject *parent = 0);
virtual ~NewSortFilterProxyModel()
{}
 
QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
 
QList<QPair<int, Qt::SortOrder> > sortedColumns()
{return m_sortedColumns;}
void setSortedColumns(QList<QPair<int, Qt::SortOrder> > sortedColumns)
{
m_sortedColumns = sortedColumns;
sort();
}
 
void addSortedColumn(int column, Qt::SortOrder order);
void removeSortedColumn(int column);
void changeSortedColumn(int column, Qt::SortOrder order);
 
Qt::SortOrder sortOrder() const
{return m_sortOrder;}
Qt::SortOrder sortOrder(int column) const;
 
bool isColumnInSort(int column) const;
 
protected:
void sort();
bool lessThan ( const QModelIndex & left, const QModelIndex & right ) const;
 
public Q_SLOTS:
void clearSort();
};
 
#endif //NEWSORTFILTERPROXYMODEL_H
 

newsortfilterproxymodel.cpp

Код
C++ (Qt)
#include <QtCore/QVariant>
 
#include "newsortfilterproxymodel.h"
 
NewSortFilterProxyModel::NewSortFilterProxyModel(QObject *parent)
:QSortFilterProxyModel(parent), m_sortOrder(Qt::AscendingOrder)
{
 
}
 
QVariant NewSortFilterProxyModel::headerData ( int section, Qt::Orientation orientation, int role) const
{
if(role == Qt::DisplayRole) {
if(orientation == Qt::Horizontal) {
for (int i = 0; i < m_sortedColumns.size(); i++) {
if (m_sortedColumns.at(i).first == section) {
QString sortIndicator = m_sortedColumns.at(i).second == Qt::AscendingOrder ? QString(0x2193) : QString(0x2191);
if (i > 0)
sortIndicator += QString::number(i + 1);
return sortIndicator + " " + sourceModel()->headerData(section, orientation, role).toString();
}
}
}
}
return sourceModel()->headerData(section, orientation, role);
}
 
void NewSortFilterProxyModel::addSortedColumn(int column, Qt::SortOrder order)
{
m_sortOrder = order;
QPair<int, Qt::SortOrder> pair;
pair.first = column;
pair.second = order;
m_sortedColumns << pair;
sort();
}
 
void NewSortFilterProxyModel::removeSortedColumn(int column)
{
for (int i = 0; i < m_sortedColumns.size(); i++) {
if (m_sortedColumns.at(i).first == column) {
m_sortedColumns.removeAt(i);
sort();
break;
}
}
}
 
void NewSortFilterProxyModel::changeSortedColumn(int column, Qt::SortOrder order)
{
for (int i = 0; i < m_sortedColumns.size(); i++) {
if (m_sortedColumns.at(i).first == column) {
m_sortOrder = order;
m_sortedColumns[i].second = order;
sort();
break;
}
}
}
 
void NewSortFilterProxyModel::clearSort()
{
m_sortedColumns.clear();
reset();
sort();
}
 
void NewSortFilterProxyModel::sort()
{
int column = m_sortedColumns.isEmpty() ? -1 : 0;
QSortFilterProxyModel::sort(column, Qt::AscendingOrder);
}
 
bool NewSortFilterProxyModel::lessThan ( const QModelIndex & left, const QModelIndex & right ) const
{
for (int i = 0; i < m_sortedColumns.size(); i++) {
QVariant leftData = sourceModel()->index(left.row(), m_sortedColumns.at(i).first).data(Qt::DisplayRole);
QVariant rightData = sourceModel()->index(right.row(), m_sortedColumns.at(i).first).data(Qt::DisplayRole);
Qt::SortOrder order = m_sortedColumns.at(i).second;
 
if (leftData == rightData)
continue;
 
switch (leftData.type()) {
case QVariant::Int:
return (leftData.toInt() < rightData.toInt()) ^ order;
break;
case QVariant::UInt:
return (leftData.toUInt() < rightData.toUInt()) ^ order;
break;
case QVariant::LongLong:
return (leftData.toLongLong() < rightData.toLongLong()) ^ order;
break;
case QVariant::ULongLong:
return (leftData.toULongLong() < rightData.toULongLong()) ^ order;
break;
case QVariant::Double:
return (leftData.toDouble() < rightData.toDouble()) ^ order;
break;
case QVariant::Char:
return (leftData.toChar() < rightData.toChar()) ^ order;
break;
case QVariant::Date:
return (leftData.toDate() < rightData.toDate()) ^ order;
break;
case QVariant::Time:
return (leftData.toTime() < rightData.toTime()) ^ order;
break;
case QVariant::DateTime:
return (leftData.toDateTime() < rightData.toDateTime()) ^ order;
break;
case QVariant::String: default:
return (QString::localeAwareCompare(leftData.toString(), rightData.toString()) < 0) ^ order;
break;
}
}
return false;
}
 
Qt::SortOrder NewSortFilterProxyModel::sortOrder(int column) const
{
for (int i = 0; i < m_sortedColumns.size(); i++) {
if (m_sortedColumns.at(i).first == column) {
return m_sortedColumns.at(i).second;
}
}
}
 
bool NewSortFilterProxyModel::isColumnInSort(int column) const
{
for (int i = 0; i < m_sortedColumns.size(); i++) {
if (m_sortedColumns.at(i).first == column) {
return true;
}
}
return false;
}
 

Пример использования:
Код
C++ (Qt)
....................................................
model = new NewSortFilterProxyModel(this);
model->setSourceModel (sourceModel);
view = new QTableView(this);
view->setModel(model);
connect(view->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(sort(int)));
....................................................
void DBFRedactorMainWindow::sort(int section)
{
Qt::SortOrder order = model->sortOrder();
if (model->sortColumn() == section)
order = model->sortOrder() == Qt::AscendingOrder
? Qt::DescendingOrder
: Qt::AscendingOrder;
 
if (qApp->keyboardModifiers() & Qt::CTRL) {
if (model->isColumnInSort(section)) {
Qt::SortOrder order = model->sortOrder(section) == Qt::AscendingOrder
 ? Qt::DescendingOrder
 : Qt::AscendingOrder;
model()->changeSortedColumn(section, order);
} else {
model()->addSortedColumn(section, model->sortOrder());
}
} else {
Qt::SortOrder order = model->sortOrder();
if (model->isColumnInSort(section)) {
order = model()->sortOrder(section) == Qt::AscendingOrder
? Qt::DescendingOrder
: Qt::AscendingOrder;
}
model->clearSort();
model->addSortedColumn(section, order);
}
}
 


Название: Re: QSortFilterProxyModel с сортировкой по нескольким столбцам.
Отправлено: masterlan от Март 25, 2010, 13:14
Спасибо за хорошую работу.