Обновление:
Пересматривая проблему, я наконец-то пришел к окончательному решению, поэтому решил добавить некоторые обновления.Во-первых, соответствующий код:
void set_filter(QJSValue f) {
if (f != m_filter) {
m_filter = f;
filterChanged();
invalidate();
}
}
void set_sorter(QJSValue f) {
if (f != m_sort) {
m_sort = f;
sorterChanged();
sort(0, Qt::DescendingOrder);
}
}
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const {
if (!m_filter.isCallable()) return true;
QJSValueList l;
l.append(_engine->newQObject(sourceModel()->index(sourceRow, 0, sourceParent).data().value<QObject*>()));
return m_filter.call(l).toBool();
}
bool lessThan(const QModelIndex & left, const QModelIndex & right) const {
if (!m_sort.isCallable()) return false;
QJSValueList l;
l.append(_engine->newQObject(sourceModel()->data(left).value<QObject*>()));
l.append(_engine->newQObject(sourceModel()->data(right).value<QObject*>()));
return m_sort.call(l).toBool();
}
Я обнаружил, что это решение проще, безопаснее и эффективнее, чем дуэт QQmlScriptString & QQmlExpression, который предлагает автоматическое обновление уведомлений, но, как уже было сказано в комментариях нижеОтвет GrecKo был довольно странным и не стоил того.
Чтобы получить автообновления для изменений свойств внешнего контекста, нужно просто сослаться на них перед возвратом фактического функтора:
filter: { expanded; SS.showHidden; o => expanded && (SS.showHidden ? true : !o.hidden) }
Вот простое выражение, использующее новый синтаксис сокращенной функции, оно ссылается на expanded; SS.showHidden;
, чтобы вызвать переоценки, если они изменяются, а затем неявно возвращает функтор
o => expanded && (SS.showHidden ? true : !o.hidden)
, который аналогичен:
return function(o) { return expanded && (SS.showHidden ? true : !o.hidden) }
, который отфильтровывает объекты на основе того, развернут ли родительский узел, скрыт ли дочерний узел и по-прежнему отображаются скрытые объекты.
ЭтоРешение не может автоматически реагировать на изменения o.hidden
, так как o
вставленов функтор после оценки, и на него нельзя ссылаться в выражении привязки, но это легко реализовать в делегатах представлений, которым необходимо динамически реагировать на такие изменения:
Connections {
target: obj
onHiddenChanged: triggerExplicitEvaluation()
}
Помните, что вариант использованиявключает в себя схему без схемы / одиночная QObject*
роль модель , которая облегчает метаморфическую модель данных, в которой данные элемента модели реализуются через свойства QML, поэтому ни один из механизмов фильтрации ролей или регулярных выражений здесь не применим, но прив то же время это дает универсальность в использовании единого механизма для реализации сортировки и фильтрации на основе любых критериев и данных произвольных элементов, и производительность очень хорошая, несмотря на мои первоначальные опасения.Он не реализует порядок сортировки, который легко достижим, просто перевернув результат выражения сравнения.