Initial commit

This commit is contained in:
oKcerG 2016-02-24 03:01:22 +01:00
commit d0d90c377f
4 changed files with 326 additions and 0 deletions

8
LICENSE Normal file
View File

@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2016 Pierre-Yves Siret
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

4
SortFilterProxyModel.pri Normal file
View File

@ -0,0 +1,4 @@
INCLUDEPATH += $$PWD
HEADERS += $$PWD/qqmlsortfilterproxymodel.h
SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp

View File

@ -0,0 +1,229 @@
#include "qqmlsortfilterproxymodel.h"
#include <QtQml>
#include <QDebug>
QQmlSortFilterProxyModel::QQmlSortFilterProxyModel(QObject *parent) :
QSortFilterProxyModel(parent),
m_filterExpression(0),
m_compareExpression(0)
{
connect(this, &QAbstractProxyModel::sourceModelChanged, this, &QQmlSortFilterProxyModel::updateRoles);
connect(this, &QAbstractItemModel::modelReset, this, &QQmlSortFilterProxyModel::updateRoles);
setDynamicSortFilter(true);
}
QString QQmlSortFilterProxyModel::filterRoleName() const
{
return m_filterRoleName;
}
void QQmlSortFilterProxyModel::setFilterRoleName(QString filterRoleName)
{
if (m_filterRoleName == filterRoleName)
return;
m_filterRoleName = filterRoleName;
updateRoles();
emit filterRoleNameChanged();
}
QString QQmlSortFilterProxyModel::filterPattern() const
{
return filterRegExp().pattern();
}
void QQmlSortFilterProxyModel::setFilterPattern(QString filterPattern)
{
QRegExp regExp = filterRegExp();
if (regExp.pattern() == filterPattern)
return;
regExp.setPattern(filterPattern);
QSortFilterProxyModel::setFilterRegExp(regExp);
emit filterPatternChanged();
}
QQmlSortFilterProxyModel::PatternSyntax QQmlSortFilterProxyModel::filterPatternSyntax() const
{
return static_cast<PatternSyntax>(filterRegExp().patternSyntax());
}
void QQmlSortFilterProxyModel::setFilterPatternSyntax(QQmlSortFilterProxyModel::PatternSyntax patternSyntax)
{
QRegExp regExp = filterRegExp();
QRegExp::PatternSyntax patternSyntaxTmp = static_cast<QRegExp::PatternSyntax>(patternSyntax);
if (regExp.patternSyntax() == patternSyntaxTmp)
return;
regExp.setPatternSyntax(patternSyntaxTmp);
QSortFilterProxyModel::setFilterRegExp(regExp);
emit filterPatternSyntaxChanged();
}
QVariant QQmlSortFilterProxyModel::filterValue() const
{
return m_filterValue;
}
void QQmlSortFilterProxyModel::setFilterValue(QVariant filterValue)
{
if (m_filterValue == filterValue)
return;
m_filterValue = filterValue;
invalidateFilter();
emit filterValueChanged();
}
QQmlScriptString QQmlSortFilterProxyModel::filterExpression() const
{
return m_filterScriptString;
}
void QQmlSortFilterProxyModel::setFilterExpression(QQmlScriptString filterScriptString)
{
if (m_filterScriptString == filterScriptString)
return;
m_filterScriptString = filterScriptString;
QQmlContext* context = new QQmlContext(qmlContext(this));
QVariantMap map;
Q_FOREACH (const QByteArray& roleName, roleNames().values())
map.insert(roleName, QVariant());
context->setContextProperty("model", map);
context->setContextProperty("index", -1);
delete(m_filterExpression);
m_filterExpression = new QQmlExpression(m_filterScriptString, context, 0, this);
connect(m_filterExpression, &QQmlExpression::valueChanged, this, &QQmlSortFilterProxyModel::invalidateFilter);
m_filterExpression->setNotifyOnValueChanged(true);
m_filterExpression->evaluate();
emit filterExpressionChanged();
}
QString QQmlSortFilterProxyModel::sortRoleName() const
{
return m_sortRoleName;
}
void QQmlSortFilterProxyModel::setSortRoleName(QString sortRoleName)
{
if (m_sortRoleName == sortRoleName)
return;
m_sortRoleName = sortRoleName;
updateRoles();
emit sortRoleNameChanged();
}
void QQmlSortFilterProxyModel::setSortOrder(Qt::SortOrder sortOrder)
{
sort(0, sortOrder);
}
QQmlScriptString QQmlSortFilterProxyModel::sortExpression() const
{
return m_compareScriptString;
}
void QQmlSortFilterProxyModel::setSortExpression(QQmlScriptString compareScriptString)
{
if (m_compareScriptString == compareScriptString)
return;
m_compareScriptString = compareScriptString;
QQmlContext* context = new QQmlContext(qmlContext(this));
QVariantMap map;
Q_FOREACH (const QByteArray& roleName, roleNames().values())
map.insert(roleName, QVariant());
context->setContextProperty("modelLeft", map);
context->setContextProperty("indexLeft", -1);
context->setContextProperty("modelRight", map);
context->setContextProperty("indexRight", -1);
delete(m_compareExpression);
m_compareExpression = new QQmlExpression(m_compareScriptString, context, 0, this);
connect(m_compareExpression, &QQmlExpression::valueChanged, this, &QQmlSortFilterProxyModel::invalidate);
m_compareExpression->setNotifyOnValueChanged(true);
m_compareExpression->evaluate();
emit sortExpressionChanged();
}
bool QQmlSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
{
QModelIndex modelIndex = sourceModel()->index(source_row, 0, source_parent);
bool valueAccepted = !m_filterValue.isValid() || ( m_filterValue == sourceModel()->data(modelIndex, filterRole()) );
bool baseAcceptsRow = valueAccepted && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
if (baseAcceptsRow && !m_filterScriptString.isEmpty())
{
QVariantMap map = modelDataMap(modelIndex);
QQmlContext context(qmlContext(this));
context.setContextProperty("model", map);
context.setContextProperty("index", source_row);
QQmlExpression expression(m_filterScriptString, &context, 0);
QVariant result = expression.evaluate();
if (!expression.hasError())
return result.toBool();
else
qWarning() << expression.error();
}
return baseAcceptsRow;
}
bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const
{
if (!m_compareScriptString.isEmpty())
{
QQmlContext context(qmlContext(this));
context.setContextProperty("modelLeft", modelDataMap(source_left));
context.setContextProperty("indexLeft", source_left.row());
context.setContextProperty("modelRight", modelDataMap(source_right));
context.setContextProperty("indexRight", source_right.row());
QQmlExpression expression(m_compareScriptString, &context, 0);
QVariant result = expression.evaluate();
if (!expression.hasError())
return result.toBool();
else
qWarning() << expression.error();
}
return QSortFilterProxyModel::lessThan(source_left, source_right);
}
void QQmlSortFilterProxyModel::invalidateFilter()
{
QSortFilterProxyModel::invalidateFilter();
}
void QQmlSortFilterProxyModel::updateRoles()
{
setFilterRole(roleNames().key(m_filterRoleName.toUtf8()));
setSortRole(roleNames().key(m_sortRoleName.toUtf8()));
}
QVariantMap QQmlSortFilterProxyModel::modelDataMap(const QModelIndex& modelIndex) const
{
QVariantMap map;
QHash<int, QByteArray> roles = roleNames();
for (QHash<int, QByteArray>::const_iterator it = roles.begin(); it != roles.end(); ++it)
map.insert(it.value(), sourceModel()->data(modelIndex, it.key()));
return map;
}
struct QQmlSortFilterProxyModelRegisterHelper {
QQmlSortFilterProxyModelRegisterHelper() {
qmlRegisterType<QAbstractItemModel>();
qmlRegisterType<QQmlSortFilterProxyModel>("SortFilterProxyModel", 0, 1, "SortFilterProxyModel");
}
};
static QQmlSortFilterProxyModelRegisterHelper registerHelper;

View File

@ -0,0 +1,85 @@
#ifndef QQMLSORTFILTERPROXYMODEL_H
#define QQMLSORTFILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
#include <QQmlExpression>
class QQmlSortFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(QString filterRoleName READ filterRoleName WRITE setFilterRoleName NOTIFY filterRoleNameChanged)
Q_PROPERTY(QString filterPattern READ filterPattern WRITE setFilterPattern NOTIFY filterPatternChanged)
Q_PROPERTY(PatternSyntax filterPatternSyntax READ filterPatternSyntax WRITE setFilterPatternSyntax NOTIFY filterPatternSyntaxChanged)
Q_PROPERTY(QVariant filterValue READ filterValue WRITE setFilterValue NOTIFY filterValueChanged)
Q_PROPERTY(QQmlScriptString filterExpression READ filterExpression WRITE setFilterExpression NOTIFY filterExpressionChanged)
Q_PROPERTY(QString sortRoleName READ sortRoleName WRITE setSortRoleName NOTIFY sortRoleNameChanged)
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder)
Q_PROPERTY(QQmlScriptString sortExpression READ sortExpression WRITE setSortExpression NOTIFY sortExpressionChanged)
public:
enum PatternSyntax {
RegExp = QRegExp::RegExp,
Wildcard = QRegExp::Wildcard,
FixedString = QRegExp::FixedString,
RegExp2 = QRegExp::RegExp2,
WildcardUnix = QRegExp::WildcardUnix,
W3CXmlSchema11 = QRegExp::W3CXmlSchema11 };
Q_ENUMS(PatternSyntax)
QQmlSortFilterProxyModel(QObject* parent = 0);
QString filterRoleName() const;
QString filterPattern() const;
PatternSyntax filterPatternSyntax() const;
QVariant filterValue() const;
QQmlScriptString filterExpression() const;
QString sortRoleName() const;
QQmlScriptString sortExpression() const;
public slots:
void setFilterRoleName(QString filterRoleName);
void setFilterPattern(QString filterPattern);
void setFilterPatternSyntax(PatternSyntax patternSyntax);
void setFilterValue(QVariant filterValue);
void setFilterExpression(QQmlScriptString filterScriptString);
void setSortRoleName(QString sortRoleName);
void setSortOrder(Qt::SortOrder sortOrder);
void setSortExpression(QQmlScriptString compareScriptString);
signals:
void filterRoleNameChanged();
void filterPatternSyntaxChanged();
void filterPatternChanged();
void filterValueChanged();
void filterExpressionChanged();
void sortRoleNameChanged();
void sortExpressionChanged();
protected:
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
private slots:
void invalidateFilter();
void updateRoles();
private:
QVariantMap modelDataMap(const QModelIndex& modelIndex) const;
QString m_filterRoleName;
QString m_sortRoleName;
QQmlScriptString m_filterScriptString;
QQmlExpression* m_filterExpression;
QQmlScriptString m_compareScriptString;
QQmlExpression* m_compareExpression;
QVariant m_filterValue;
};
#endif // QQMLSORTFILTERPROXYMODEL_H