通过QML函子对C ++模型进行排序和过滤? [英] Sort and filter a C++ model via QML functors?

查看:112
本文介绍了通过QML函子对C ++模型进行排序和过滤?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多态(如担任任意角色)QObject模型,该模型主要是从QML声明式实例化的,如本答案所述,并且我希望能够有自定义数据视图",该视图可以通过任意方式对模型进行排序和过滤,并且有可能-运行时由代码字符串JS仿函数生成,诸如此类:

I have a polymorphic (as in arbitrary roles) QObject model that is mostly instantiated declaratively from QML, as in this answer, and I would like to be able to have custom data "views" that sort and filter the model via arbitrary, and potentially - runtime generated from code strings JS functors, something like that:

  DataView {
    sourceModel: model
    filter: function(o) { return o.size > 3 }
    sort: function(a, b) { return a.size > b.size }
  }

QSortFilterProxyModel界面似乎并不特别适合该任务,而是固定在静态角色和预编译的规则上.

The QSortFilterProxyModel interface doesn't seem to be particularly well suited to the task, instead being fixated on static roles and pre-compiled rules.

我尝试在C ++端使用QJSValue属性,但似乎不可能,C ++代码只是无法使用该属性类型进行编译.如果将属性类型设置为QVariant,我将从QML收到错误消息,该函数只能绑定到var属性.显然,从varQVariant的转换并没有像返回值那样在这里启动.

I tried using QJSValue properties on the C++ side, but it seems like it is not possible, the C++ code just doesn't compile with that property type. And if I set the property type to QVariant I get error messages from QML that functions can only be bound to var properties. Evidently, var to QVariant conversion doesn't kick in here as it does for return values.

推荐答案

更新:

回顾这个问题,我终于有了一个最终的解决方案,所以我决定添加一些更新.首先,相关代码:

Revisiting the issue, I finally came with a finalized solution, so I decided to drop in some updates. First, the relevant code:

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的回答下面的评论所详细说明的那样,这有点不可靠,并不值得.

I found this solution to be simpler, safer and better performing than the QQmlScriptString & QQmlExpression duo, which does offer automatic updates on notifications, but as already elaborated in the comments below GrecKo's answer, was kinda flaky and not really worth it.

获取外部上下文属性更改的自动更新的方法是在返回实际的函子之前简单地引用它们:

The hack to get auto-updates for external context property changes is to simply reference them before returning the actual functor:

filter: { expanded; SS.showHidden; o => expanded && (SS.showHidden ? true : !o.hidden) }

这是使用新的速记函数语法的简单表达式,它引用expanded; SS.showHidden;以触发重新评估(如果这些改变),然后隐式返回函子

Here is a simple expression using the new shorthand function syntax, it references expanded; SS.showHidden; in order to trigger reevaluations if those change, then implicitly returns the functor

o => expanded && (SS.showHidden ? true : !o.hidden)

类似于:

return function(o) { return expanded && (SS.showHidden ? true : !o.hidden) }

根据父节点是否展开,子节点是否隐藏以及是否仍显示隐藏的对象来过滤对象.

which filters out objects based on whether the parent node is expanded, whether the child node is hidden and whether hidden objects are still displayed.

该解决方案无法自动响应对o.hidden的更改,因为o会在求值时插入到函子中,并且不能在绑定表达式中引用,但这可以在的委托中轻松实现.需要动态响应此类更改的视图:

This solution has no way to automatically respond to changes to o.hidden, as o is inserted into the functor upon evaluation and can't be referenced in the binding expression, but this can easily be implemented in the delegates of views that need to dynamically respond to such changes:

Connections {
      target: obj
      onHiddenChanged: triggerExplicitEvaluation()
}

请记住,该用例涉及一个无模式/单个QObject*角色

Remember that the use case involves a schema-less / single QObject* role model that facilitates a metamorphic data model where model item data is implemented via QML properties, so none of the role or regex stock filtering mechanisms are applicable here, but at the same time, this gives the genericity to use a single mechanism to implement sorting and filtering based on any criteria and arbitrary item data, and performance is very good, despite my initial concerns. It doesn't implement a sorting order, that is easily achievable by simply flipping the comparison expression result.

这篇关于通过QML函子对C ++模型进行排序和过滤?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆