Сортировка и фильтрация в QSqlQueryModel не реализованы, что усложняет использование модели. Кроме того не реализовано редактирование вертикального заголовка (verticalHeader).
Большие проблемы возникали когда содержимое модели формируется по запросу QSqlQuery с условиями, по типу:
SELECT field1 FROM table1 WHERE field1=?;
SELECT count(*) from t1 where f1=? and f2=?
Приведенная ниже реализация QSqlQueryModelEx позволяет осуществлять сортировку, фильтрацию, изменение текста вертикального заголовка (verticalHeader).Причем в отличии от того, что мне встречалось, в приведенной реализации фильтрация и сортировка может осуществляться в любом порядке (сначала сортировка, потом фильтрация или наоборот).
#ifndef QSqlQueryModelEx_h
#define QSqlQueryModelEx_h
#include <QSqlQueryModel>
#include <QSqlQuery>
#include <QMap>
class QSqlQueryModelEx : public QSqlQueryModel
{
Q_OBJECT
public:
QMap<int, QString> vertical_header;
QSqlQueryModelEx(QObject *parent = 0):
QSqlQueryModel(parent)
{
str_filter.clear();
sort_column = -1;
sort_order = Qt::AscendingOrder;
}
QVariant QSqlQueryModelEx::headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Vertical && role == Qt::DisplayRole) {
return QVariant(vertical_header[section]);
} else {
return QSqlQueryModel::headerData(section, orientation, role);
}
}
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)
{
if(QSqlQueryModel::setHeaderData(section, orientation, value, role)) {
emit QSqlQueryModel::headerDataChanged(orientation, section, section);
return true;
} else {
if (orientation == Qt::Vertical) {
vertical_header[section] = value.toString();
emit QSqlQueryModel::headerDataChanged(orientation, section, section);
}
return false;
}
}
void setQuery(const QSqlQuery & query)
{
__query__ = query;
return QSqlQueryModel::setQuery(query);
}
public slots:
virtual void select()
{
if (__query__.lastQuery().isEmpty()) return;
QString str_query = __query__.lastQuery();
if (!str_filter.isEmpty()) {
qDebug("***FILTER***");
QString ch_where = QString(" where ").append(str_filter);
if (str_query.contains("order by ")) {
str_query.insert(str_query.indexOf("order by "),ch_where.append(" "));
} else {
str_query.append(ch_where);
}
}
if (sort_column >= 0) {
qDebug("***SORT***");
QString str_order;
if (str_query.contains("order by ")) {
str_query = str_query.left(str_query.indexOf("order by"));
} else {
str_order += " ";
}
str_order += "ORDER BY " + QString::number(sort_column+1) + ((sort_order == Qt::AscendingOrder) ? " ASC" : " DESC");
str_query.append(str_order);
}
QSqlQuery temp = QSqlQuery(str_query);
if (__query__.boundValues().size()) {
foreach (const QVariant& value, __query__.boundValues()) {
temp.addBindValue(i,value);
}
temp.exec();
}
QSqlQueryModel::setQuery(temp);
}
virtual void setSort(int column, Qt::SortOrder order)
{
sort_column = column;
sort_order = order;
}
virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder)
{
if (sort_column != column || sort_order != order) {
setSort(column, order);
select();
}
}
virtual void setFilter(const QString& string_filter)
{
str_filter = string_filter;
}
virtual void filter(const QString& string_filter)
{
if (str_filter != string_filter) {
setFilter(string_filter);
select();
}
}
private:
QSqlQuery __query__;
QString str_filter;
int sort_column;
Qt::SortOrder sort_order;
};
#endif // QSqlQueryModelEx_h