Sort and Filter a QSqlQueryModel

From Qt Wiki
Revision as of 09:36, 24 February 2015 by Maintenance script (talk | contribs)
Jump to navigation Jump to search



[toc align_right="yes" depth="2"]

Sort and Filter a QSqlQueryModel

QSortFilterSqlQueryModel is a QSqlQueryModel subclass that allows server-side sorting and filtering.

Feel free to download and test it.

Example usage

<br />QSortFilterSqlQueryModel '''model = new QSortFilterSqlQueryModel(this);<br />model-&gt;setQuery(&quot;SELECT u.id, u.name, c.name FROM users AS u LEFT JOIN cities AS c ON (u.city_id = c.id)&quot;);<br />model-&gt;setFilterColumn(&quot;u.name&amp;quot;); // will filter by user name<br />model-&gt;setFilterFlags(Qt::MatchStartsWith);<br />model-&gt;setFilter(&quot;Iv&amp;quot;);<br />model-&gt;select();
<br />/''' executes this query:<br />SELECT u.id, u.name, c.name FROM users AS u LEFT JOIN cities AS c ON (u.city_id = c.id)<br />WHERE u.name LIKE 'Iv%'<br />*/<br />

You can connect a QLineEdit's textChanged signal to the filter slot:
filter is the same as setFilter, but it also call select();

<br />// dynamic filtering on user input<br />QLineEdit '''search = new QLineEdit(this);<br />connect(search, SIGNAL (textChanged(QString)), model, SLOT (filter(QString)));<br />


Sorting is done automatically by the view, using the sort implementation. You can also use setSort to set a sort order before select()ing.
h2. Warnings
It has only been tested in Windows using MySQL
* It won't work using setQuery(QSqlQuery). I didn't needed it so you have to reimplement it yourself.
* Works for me. May not work for you. :P

Code

QSortFilterSqlQueryModel.h

<br />#ifndef QSORTFILTERSQLQUERYMODEL_H<br />#define QSORTFILTERSQLQUERYMODEL_H

#include &lt;QSqlQueryModel&amp;gt;<br />#include &lt;QSqlRecord&amp;gt;

class QSortFilterSqlQueryModel : public QSqlQueryModel<br />{<br /> Q_OBJECT

public:

explicit QSortFilterSqlQueryModel(QObject *parent = 0);

//void setQuery(const QSqlQuery &amp;query);<br /> void setQuery(const QString &amp; query, const QSqlDatabase &amp; db = QSqlDatabase::database() );

public slots:

void setFilterColumn (const QString &amp; column);<br /> void setFilterFlags (const Qt::MatchFlag flags);<br /> void setFilter( const QString &amp; filter );<br /> void filter( const QString &amp; filter );

void select();

virtual void setSort (int column, Qt::SortOrder order);<br /> virtual void sort (int column, Qt::SortOrder order);

private:

QSqlDatabase queryDB;<br /> QString queryClause;<br /> Qt::MatchFlag filterFlags;<br /> QString filterString;<br /> QString filterColumn;<br /> int sortKeyColumn;<br /> Qt::SortOrder sortOrder;

signals:

};

#endif // QSORTFILTERSQLQUERYMODEL_H<br />

QSortFilterSqlQueryModel.cpp


#include "QSortFilterSqlQueryModel.h&quot;
#include <QtSql&gt;
#include <QString&gt;

QSortFilterSqlQueryModel::QSortFilterSqlQueryModel(QObject parent) :
QSqlQueryModel(parent)
{

}
void QSortFilterSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db)
{
queryClause = query;
queryDB = db;
filterString.clear();
//filterColumn.clear();
filterFlags = Qt::MatchStartsWith;
sortKeyColumn = –1;
sortOrder = Qt::AscendingOrder;
}
void QSortFilterSqlQueryModel::select()
{
if (queryClause.isEmpty() || (!queryDB.isValid()))
return;
QString query = queryClause;
if (!filterString.isEmpty() && !filterColumn.isEmpty()) {
QString whereClause;
QString esFilterString = filterString;
QString esFilterColumn = filterColumn;
if (filterFlags & Qt::MatchExactly) {
whereClause = "WHERE %1 = %2&quot;;
} else if (filterFlags & Qt::MatchStartsWith) {
whereClause = "WHERE %1 LIKE %2&quot;;
esFilterString.append("");
} else if (filterFlags & Qt::MatchEndsWith) {
whereClause = "WHERE %1 LIKE %2&quot;;
esFilterString.prepend("*");
} else if (filterFlags & Qt::MatchRegExp) {
whereClause = "WHERE %1 REGEXP %2&quot;;
} else if (filterFlags & Qt::MatchWildcard) {
whereClause = "WHERE %1 LIKE %2&quot;;
} else if (filterFlags & Qt::MatchContains) {
whereClause = "WHERE %1 LIKE 2&quot;;
esFilterString.append("
");
esFilterString.prepend("");
} else { return; } // unhandled filterflag

QSqlDriver driver = queryDB.driver();
esFilterColumn = driver->escapeIdentifier(filterColumn, QSqlDriver::FieldName);
QSqlField field; field.setType(QVariant::String); field.setValue(esFilterString);
esFilterString = driver->formatValue(field);
if (filterFlags & Qt::MatchStartsWith || Qt::MatchEndsWith || Qt::MatchWildcard) {
esFilterString = esFilterString.replace("", "");
//if (filterFlags & Qt::MatchWildcard)
esFilterString = esFilterString.replace("
", "");
}

//whereClause.arg(esFilterColumn).arg(esFilterString); // don't know why it doesn't work
whereClause = whereClause.replace("%1&quot;, esFilterColumn).replace("%2&quot;, esFilterString);
query.append(" " + whereClause);
}

if (sortKeyColumn >= 0) {
QString orderClause;
orderClause = "ORDER BY " + QString::number(sortKeyColumn+1) + " " + ((sortOrder == Qt::AscendingOrder) ? "ASC&quot; : "DESC&quot;);
query.append(" " + orderClause);
}

QSqlQueryModel::setQuery(query, queryDB);

}

void QSortFilterSqlQueryModel::setSort(int column, Qt::SortOrder order)
{
sortKeyColumn = column;
sortOrder = order;
}

void QSortFilterSqlQueryModel::sort(int column, Qt::SortOrder order)
{
if ((sortKeyColumn != column) || (sortOrder != order)) {
setSort(column, order);
select();
}
}

void QSortFilterSqlQueryModel::setFilterColumn(const QString &column)
{
filterColumn = column;
}

void QSortFilterSqlQueryModel::setFilter(const QString &filter) {
filterString = filter;
}

void QSortFilterSqlQueryModel::setFilterFlags(const Qt::MatchFlag flags)
{
filterFlags = flags;
}

void QSortFilterSqlQueryModel::filter(const QString &filter)
{
if (filterString != filter) {
setFilter(filter);
select();
}
}