diff --git a/src/declarativeimports/core/datamodel.cpp b/src/declarativeimports/core/datamodel.cpp index 8bdfd1743..1c83bc54f 100644 --- a/src/declarativeimports/core/datamodel.cpp +++ b/src/declarativeimports/core/datamodel.cpp @@ -20,6 +20,8 @@ #include "datamodel.h" #include "datasource.h" +#include +#include #include #include @@ -90,6 +92,22 @@ void SortFilterModel::setModel(QAbstractItemModel *model) emit sourceModelChanged(model); } +bool SortFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const +{ + if (m_filterCallback.isCallable()) { + QJSValueList args; + args << QJSValue(source_row); + + const QModelIndex idx = sourceModel()->index(source_row, filterKeyColumn(), source_parent); + QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine(); + args << engine->toScriptValue(idx.data(m_roleIds.value(m_filterRole))); + + return const_cast(this)->m_filterCallback.call(args).toBool(); + } + + return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); +} + void SortFilterModel::setFilterRegExp(const QString &exp) { if (exp == filterRegExp()) { @@ -119,6 +137,26 @@ QString SortFilterModel::filterString() const return m_filterString; } +QJSValue SortFilterModel::filterCallback() const +{ + return m_filterCallback; +} + +void SortFilterModel::setFilterCallback(const QJSValue& callback) +{ + if (m_filterCallback.strictlyEquals(callback)) { + return; + } + + if (!callback.isNull() && !callback.isCallable()) { + return; + } + + m_filterCallback = callback; + + emit filterCallbackChanged(callback); +} + void SortFilterModel::setFilterRole(const QString &role) { QSortFilterProxyModel::setFilterRole(roleNameToId(role)); diff --git a/src/declarativeimports/core/datamodel.h b/src/declarativeimports/core/datamodel.h index 0001b4bbf..cec93b7b8 100644 --- a/src/declarativeimports/core/datamodel.h +++ b/src/declarativeimports/core/datamodel.h @@ -21,6 +21,7 @@ #define DATAMODEL_H #include +#include #include #include @@ -56,6 +57,16 @@ class SortFilterModel : public QSortFilterProxyModel */ Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged REVISION 1) + /** + * A JavaScript callable that is passed the source model row index as first argument and the value + * of filterRole as second argument. The callable's return value is evaluated as boolean to determine + * whether the row is accepted (true) or filtered out (false). It overrides the default implementation + * that uses filterRegExp or filterString; while filterCallable is set those two properties are + * ignored. Attempts to write a non-callable to this property are silently ignored, but you can set + * it to null. + */ + Q_PROPERTY(QJSValue filterCallback READ filterCallback WRITE setFilterCallback NOTIFY filterCallbackChanged REVISION 1) + /** * The role of the sourceModel on which filterRegExp must be applied. */ @@ -90,6 +101,9 @@ public: void setFilterString(const QString &filterString); QString filterString() const; + void setFilterCallback(const QJSValue &callback); + QJSValue filterCallback() const; + void setFilterRole(const QString &role); QString filterRole() const; @@ -121,9 +135,11 @@ Q_SIGNALS: void sourceModelChanged(QObject *); void filterRegExpChanged(const QString &); Q_REVISION(1) void filterStringChanged(const QString &); + Q_REVISION(1) void filterCallbackChanged(const QJSValue &); protected: int roleNameToId(const QString &name); + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; protected Q_SLOTS: void syncRoleNames(); @@ -132,6 +148,7 @@ private: QString m_filterRole; QString m_sortRole; QString m_filterString; + QJSValue m_filterCallback; QHash m_roleIds; };