-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added filter for Listview on mainpage.
- Loading branch information
1 parent
f3a25dd
commit e2846a6
Showing
61 changed files
with
3,534 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
!contains( CONFIG, c\+\+1[14] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro") | ||
|
||
INCLUDEPATH += $$PWD | ||
|
||
HEADERS += $$PWD/qqmlsortfilterproxymodel.h \ | ||
$$PWD/filters/filter.h \ | ||
$$PWD/filters/filtercontainer.h \ | ||
$$PWD/filters/rolefilter.h \ | ||
$$PWD/filters/valuefilter.h \ | ||
$$PWD/filters/indexfilter.h \ | ||
$$PWD/filters/regexpfilter.h \ | ||
$$PWD/filters/rangefilter.h \ | ||
$$PWD/filters/expressionfilter.h \ | ||
$$PWD/filters/filtercontainerfilter.h \ | ||
$$PWD/filters/anyoffilter.h \ | ||
$$PWD/filters/alloffilter.h \ | ||
$$PWD/sorters/sorter.h \ | ||
$$PWD/sorters/sortercontainer.h \ | ||
$$PWD/sorters/rolesorter.h \ | ||
$$PWD/sorters/stringsorter.h \ | ||
$$PWD/sorters/expressionsorter.h \ | ||
$$PWD/proxyroles/proxyrole.h \ | ||
$$PWD/proxyroles/proxyrolecontainer.h \ | ||
$$PWD/proxyroles/joinrole.h \ | ||
$$PWD/proxyroles/switchrole.h \ | ||
$$PWD/proxyroles/expressionrole.h | ||
|
||
SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \ | ||
$$PWD/filters/filter.cpp \ | ||
$$PWD/filters/filtercontainer.cpp \ | ||
$$PWD/filters/rolefilter.cpp \ | ||
$$PWD/filters/valuefilter.cpp \ | ||
$$PWD/filters/indexfilter.cpp \ | ||
$$PWD/filters/regexpfilter.cpp \ | ||
$$PWD/filters/rangefilter.cpp \ | ||
$$PWD/filters/expressionfilter.cpp \ | ||
$$PWD/filters/filtercontainerfilter.cpp \ | ||
$$PWD/filters/anyoffilter.cpp \ | ||
$$PWD/filters/alloffilter.cpp \ | ||
$$PWD/filters/filtersqmltypes.cpp \ | ||
$$PWD/sorters/sorter.cpp \ | ||
$$PWD/sorters/sortercontainer.cpp \ | ||
$$PWD/sorters/rolesorter.cpp \ | ||
$$PWD/sorters/stringsorter.cpp \ | ||
$$PWD/sorters/expressionsorter.cpp \ | ||
$$PWD/sorters/sortersqmltypes.cpp \ | ||
$$PWD/proxyroles/proxyrole.cpp \ | ||
$$PWD/proxyroles/proxyrolecontainer.cpp \ | ||
$$PWD/proxyroles/joinrole.cpp \ | ||
$$PWD/proxyroles/switchrole.cpp \ | ||
$$PWD/proxyroles/expressionrole.cpp \ | ||
$$PWD/proxyroles/proxyrolesqmltypes.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include "alloffilter.h" | ||
|
||
namespace qqsfpm { | ||
|
||
/*! | ||
\qmltype AllOf | ||
\inherits Filter | ||
\inqmlmodule SortFilterProxyModel | ||
\brief Filter container accepting rows accepted by all its child filters | ||
The AllOf type is a \l Filter container that accepts rows if all of its contained (and enabled) filters accept them, or if it has no filter. | ||
Using it as a top level filter has the same effect as putting all its child filters as top level filters. It can however be usefull to use an AllOf filter when nested in an AnyOf filter. | ||
*/ | ||
bool AllOfFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const | ||
{ | ||
//return true if all filters return false, or if there is no filter. | ||
return std::all_of(m_filters.begin(), m_filters.end(), | ||
[&sourceIndex, &proxyModel] (Filter* filter) { | ||
return filter->filterAcceptsRow(sourceIndex, proxyModel); | ||
} | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#ifndef ALLOFFILTER_H | ||
#define ALLOFFILTER_H | ||
|
||
#include "filtercontainerfilter.h" | ||
|
||
namespace qqsfpm { | ||
|
||
class AllOfFilter : public FilterContainerFilter { | ||
Q_OBJECT | ||
|
||
public: | ||
using FilterContainerFilter::FilterContainerFilter; | ||
|
||
protected: | ||
bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; | ||
}; | ||
|
||
} | ||
|
||
#endif // ALLOFFILTER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include "anyoffilter.h" | ||
|
||
namespace qqsfpm { | ||
|
||
/*! | ||
\qmltype AnyOf | ||
\inherits Filter | ||
\inqmlmodule SortFilterProxyModel | ||
\brief Filter container accepting rows accepted by at least one of its child filters | ||
The AnyOf type is a \l Filter container that accepts rows if any of its contained (and enabled) filters accept them. | ||
In the following example, only the rows where the \c firstName role or the \c lastName role match the text entered in the \c nameTextField will be accepted : | ||
\code | ||
TextField { | ||
id: nameTextField | ||
} | ||
SortFilterProxyModel { | ||
sourceModel: contactModel | ||
filters: AnyOf { | ||
RegExpFilter { | ||
roleName: "lastName" | ||
pattern: nameTextField.text | ||
caseSensitivity: Qt.CaseInsensitive | ||
} | ||
RegExpFilter { | ||
roleName: "firstName" | ||
pattern: nameTextField.text | ||
caseSensitivity: Qt.CaseInsensitive | ||
} | ||
} | ||
} | ||
\endcode | ||
*/ | ||
bool AnyOfFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const | ||
{ | ||
//return true if any of the enabled filters return true | ||
return std::any_of(m_filters.begin(), m_filters.end(), | ||
[&sourceIndex, &proxyModel] (Filter* filter) { | ||
return filter->enabled() && filter->filterAcceptsRow(sourceIndex, proxyModel); | ||
} | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#ifndef ANYOFFILTER_H | ||
#define ANYOFFILTER_H | ||
|
||
#include "filtercontainerfilter.h" | ||
|
||
namespace qqsfpm { | ||
|
||
class AnyOfFilter : public FilterContainerFilter { | ||
Q_OBJECT | ||
|
||
public: | ||
using FilterContainerFilter::FilterContainerFilter; | ||
|
||
protected: | ||
bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; | ||
}; | ||
|
||
} | ||
|
||
#endif // ANYOFFILTER_H |
124 changes: 124 additions & 0 deletions
124
libs/qmlsortfilterproxymodel/filters/expressionfilter.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include "expressionfilter.h" | ||
#include "qqmlsortfilterproxymodel.h" | ||
#include <QtQml> | ||
|
||
namespace qqsfpm { | ||
|
||
/*! | ||
\qmltype ExpressionFilter | ||
\inherits Filter | ||
\inqmlmodule SortFilterProxyModel | ||
\brief Filters row with a custom filtering | ||
An ExpressionFilter is a \l Filter allowing to implement custom filtering based on a javascript expression. | ||
*/ | ||
|
||
/*! | ||
\qmlproperty expression ExpressionFilter::expression | ||
An expression to implement custom filtering, it must evaluate to a boolean. | ||
It has the same syntax has a \l {http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html} {Property Binding} except it will be evaluated for each of the source model's rows. | ||
Rows that have their expression evaluating to \c true will be accepted by the model. | ||
Data for each row is exposed like for a delegate of a QML View. | ||
This expression is reevaluated for a row every time its model data changes. | ||
When an external property (not \c index or in \c model) the expression depends on changes, the expression is reevaluated for every row of the source model. | ||
To capture the properties the expression depends on, the expression is first executed with invalid data and each property access is detected by the QML engine. | ||
This means that if a property is not accessed because of a conditional, it won't be captured and the expression won't be reevaluted when this property changes. | ||
A workaround to this problem is to access all the properties the expressions depends unconditionally at the beggining of the expression. | ||
*/ | ||
const QQmlScriptString& ExpressionFilter::expression() const | ||
{ | ||
return m_scriptString; | ||
} | ||
|
||
void ExpressionFilter::setExpression(const QQmlScriptString& scriptString) | ||
{ | ||
if (m_scriptString == scriptString) | ||
return; | ||
|
||
m_scriptString = scriptString; | ||
updateExpression(); | ||
|
||
Q_EMIT expressionChanged(); | ||
invalidate(); | ||
} | ||
|
||
void ExpressionFilter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) | ||
{ | ||
updateContext(proxyModel); | ||
} | ||
|
||
bool ExpressionFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const | ||
{ | ||
if (!m_scriptString.isEmpty()) { | ||
QVariantMap modelMap; | ||
QHash<int, QByteArray> roles = proxyModel.roleNames(); | ||
|
||
QQmlContext context(qmlContext(this)); | ||
auto addToContext = [&] (const QString &name, const QVariant& value) { | ||
context.setContextProperty(name, value); | ||
modelMap.insert(name, value); | ||
}; | ||
|
||
for (auto it = roles.cbegin(); it != roles.cend(); ++it) | ||
addToContext(it.value(), proxyModel.sourceData(sourceIndex, it.key())); | ||
addToContext("index", sourceIndex.row()); | ||
|
||
context.setContextProperty("model", modelMap); | ||
|
||
QQmlExpression expression(m_scriptString, &context); | ||
QVariant variantResult = expression.evaluate(); | ||
|
||
if (expression.hasError()) { | ||
qWarning() << expression.error(); | ||
return true; | ||
} | ||
if (variantResult.canConvert<bool>()) { | ||
return variantResult.toBool(); | ||
} else { | ||
qWarning("%s:%i:%i : Can't convert result to bool", | ||
expression.sourceFile().toUtf8().data(), | ||
expression.lineNumber(), | ||
expression.columnNumber()); | ||
return true; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
void ExpressionFilter::updateContext(const QQmlSortFilterProxyModel& proxyModel) | ||
{ | ||
delete m_context; | ||
m_context = new QQmlContext(qmlContext(this), this); | ||
// what about roles changes ? | ||
QVariantMap modelMap; | ||
|
||
auto addToContext = [&] (const QString &name, const QVariant& value) { | ||
m_context->setContextProperty(name, value); | ||
modelMap.insert(name, value); | ||
}; | ||
|
||
for (const QByteArray& roleName : proxyModel.roleNames().values()) | ||
addToContext(roleName, QVariant()); | ||
|
||
addToContext("index", -1); | ||
|
||
m_context->setContextProperty("model", modelMap); | ||
updateExpression(); | ||
} | ||
|
||
void ExpressionFilter::updateExpression() | ||
{ | ||
if (!m_context) | ||
return; | ||
|
||
delete m_expression; | ||
m_expression = new QQmlExpression(m_scriptString, m_context, 0, this); | ||
connect(m_expression, &QQmlExpression::valueChanged, this, &ExpressionFilter::invalidate); | ||
m_expression->setNotifyOnValueChanged(true); | ||
m_expression->evaluate(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#ifndef EXPRESSIONFILTER_H | ||
#define EXPRESSIONFILTER_H | ||
|
||
#include "filter.h" | ||
#include <QQmlScriptString> | ||
|
||
class QQmlExpression; | ||
|
||
namespace qqsfpm { | ||
|
||
class ExpressionFilter : public Filter | ||
{ | ||
Q_OBJECT | ||
Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged) | ||
|
||
public: | ||
using Filter::Filter; | ||
|
||
const QQmlScriptString& expression() const; | ||
void setExpression(const QQmlScriptString& scriptString); | ||
|
||
void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; | ||
|
||
protected: | ||
bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; | ||
|
||
Q_SIGNALS: | ||
void expressionChanged(); | ||
|
||
private: | ||
void updateContext(const QQmlSortFilterProxyModel& proxyModel); | ||
void updateExpression(); | ||
|
||
QQmlScriptString m_scriptString; | ||
QQmlExpression* m_expression = nullptr; | ||
QQmlContext* m_context = nullptr; | ||
}; | ||
|
||
} | ||
|
||
#endif // EXPRESSIONFILTER_H |
Oops, something went wrong.