It exposes QSFPM in a usable way from QML, referring to roles by name
and exposing a way to perform JS callbacks as an advanced filter method.
Details
Diff Detail
- Repository
- R275 KItemModels
- Branch
- arcpatch-D25326
- Lint
No Linters Available - Unit
No Unit Test Coverage - Build Status
Buildable 21802 Build 21820: arc lint + arc unit
+1: i found myself many times wanting to use this but not being able because of plasma dep.
the code is used a lot in plasmoids and seems quite robust
src/qml/sortfiltermodel.h | ||
---|---|---|
63 ↗ | (On Diff #69800) | This (and sortRole below) hides the properties from QSortFilterProxy with the same name. Maybe it is a better idea to use filterRoleName/sortRoleName? |
74 ↗ | (On Diff #69800) | Having a sortColumn property would also be useful, since that is apparently missing from QSortFilterProxy. I seem to recall that was added to the Plasma version a while ago. |
src/qml/sortfiltermodel.h | ||
---|---|---|
63 ↗ | (On Diff #69800) | Or potentially we could just kill our handling of it? |
src/qml/sortfiltermodel.cpp | ||
---|---|---|
84 ↗ | (On Diff #69800) | Can we also just have it send source_row and source_parent since we have proper QModelIndex handling now? |
97 ↗ | (On Diff #69800) | QRegExp is deprecated, use setFilterRegularExpression taking a QRegularExpression |
src/qml/sortfiltermodel.h | ||
43 ↗ | (On Diff #69800) | Can this be a QRegularExpression? |
48 ↗ | (On Diff #69800) | Given this is a new class/import, remove REVISION |
56 ↗ | (On Diff #69800) | Could this use a RESET method instead of telling people to assign null? |
78 ↗ | (On Diff #69800) | Is this needed? |
80 ↗ | (On Diff #69800) | Remove |
117 ↗ | (On Diff #69800) | I don't like this. We have proper QModelIndex handling in QML now, this is a hack imho |
119 ↗ | (On Diff #69800) | Remove, QAbstractProxyModel::mapToSource (and fromSource) is Q_INVOKABLE and we have proper QModelIndex handling in QML now |
138 ↗ | (On Diff #69800) | Does this need a d pointer or is it just for use in QML? Perhaps rename the header to _p.h then? |
src/qml/sortfiltermodel.cpp | ||
---|---|---|
84 ↗ | (On Diff #69800) | We could. Though means everyone doing a lookup immediately, handling columns and roles properly. More powerful, but slightly more complex for the user There's also the option of having two proxies with different behaviours? @mart thoughts? |
src/qml/sortfiltermodel.h | ||
43 ↗ | (On Diff #69800) | It's not listed in https://doc.qt.io/qt-5/qtqml-cppintegration-data.html We need to test |
63 ↗ | (On Diff #69800) | Did some investigation we have our handling just to emit a signal when the property changes! Another good thing to try to upstream. Keeping the same name allows us to subtly drop the API in the future and keep clients working. |
78 ↗ | (On Diff #69800) | I think so. We've implemented it in a lot of plasma models, presumably for some reason. Would be a good thing to try and upstream though. |
138 ↗ | (On Diff #69800) | I don't see why we would need a d pointer. We may as well self an allocation.
We haven't done that universally in all frameworks, but sure I could. |
src/qml/sortfiltermodel.h | ||
---|---|---|
43 ↗ | (On Diff #69800) | Bummer. I tried, a JS RegExp (both new RegExp() and /literal syntax/) get turned into a QRegExp. It does *not* work with QRegularExpression :( There's a RegularExpressionValidator which uses QRegularExpression but it's in Qt 5.14. Maybe they fixed that recently - doesn't really help us here, though. |
63 ↗ | (On Diff #69800) |
+1 given they're all QObjects already anyway |
78 ↗ | (On Diff #69800) |
Either because someone was too lazy to use the respective property on the Repeater or ListView or before rowCount() was Q_INVOKABLE. Not sure it's upstreamable since it assumes it's a flast list. Maybe something for QAbstract*List*Model rather than QAbstract*Item*Model |
138 ↗ | (On Diff #69800) | Was just wondering but if it's only to be used from QML and not exported, doesn't need one I suppose. |
src/qml/sortfiltermodel.h | ||
---|---|---|
78 ↗ | (On Diff #69800) | rowCount being invokable seems enough in the cases I've found in Plasma, will drop this. |
Implement new arguments for filterAcceptsRow passing source_row, source_parent.
It makes for slightly heavier messier JS, but it also allows for super flexibility
beyond just having the value retried and it's familiar for Qt programmers.
Maybe we should add an invokable
sourceData(int source_row, int source_column, QModelIndex source_parent) to save a
bit of boilerplate?
src/qml/ksortfilterproxymodel.h | ||
---|---|---|
3 | *Martin | |
45 | Did you try that QRegularExpression vs QRegExp thing? | |
59 | "but you can set it to null" - I think this thing needs a RESET method | |
81 | needs NOTIFY signals, as do the ones below | |
100 | override? | |
119 | Shouldn't this be an int and then you can drop all of that role names stuff? |
src/qml/ksortfilterproxymodel.h | ||
---|---|---|
45 | We did some research
That doesn't help draw a conclusion. Though is there any benefit to creating a reg exp in JS space rather than here? | |
59 | what do we gain doing that? You would use that with which is the same as now. I think RESET is only usable if you can't represent null in the passed data type. | |
119 | roleNames are always exported. Some people expose the roles as an enum, but not that many I certainly don't want to encourage magic numbers being used in QML. |
Huge cleanup
Drop all the filter properties
Implement other changes
Extend unit tests
src/qml/ksortfilterproxymodel.cpp | ||
---|---|---|
102 | In setFilterRegExp(), QSortFilterProxyModel::setFilterRegularExpression(QRegularExpression &) is used, so IIUC here it should be : | |
src/qml/ksortfilterproxymodel.h | ||
104 | Hello. Since you're using QRegularExpression, maybe rename to setFilterRegex() or setFitlerRegularExpression() (the latter matches QSortFilterProxyModel naming schema) to avoid QRegExp vs QRegularExpression confusion? (Another pro for renaming setFilterRegExp() to setFilterRegularExpression()). |
src/qml/ksortfilterproxymodel.cpp | ||
---|---|---|
102 | I'm not sure your comments are still valid, we switched to using the superclass QSortFilterProxyModel's methods, and don't shadow that part here. |
src/qml/ksortfilterproxymodel.cpp | ||
---|---|---|
102 | Right, I was looking at an old revision of this diff. Sorry about the noise. |
Few comments from someone who was recently using PlasmaCore.SortFilterModel and had trouble understanding sorting :)
autotests/ksortfilterproxymodel_qml.cpp | ||
---|---|---|
112 | Can you add a test for sortColumn? It might be useful for newcomers (like me) to understand how it works. I had real trouble understanding when it is needed and when not (ConfigEntries.qml) | |
src/qml/ksortfilterproxymodel.cpp | ||
166 | When using PlasmaCore.SortFilterModel sortColumn is sometimes set to -1 and sorting is not working when sortColumn is not set. If I remember correctly, -1 is the default in QSortFilterProxyModel. Is std::max(sortColumn(), 0) added to fix that? What will happen in this situation: KSortFilterProxyModel { sourceModel: testModel sortColumn: -1 sortRole: "user" } Maybe is should be documented in sortRole and sortOrder properties that these two set sortColumn to 0 (or -1 in case of empty role)? | |
176 | Which is preferred: emit or Q_EMIT? | |
src/qml/ksortfilterproxymodel.h | ||
68 | can we have something similar for sorting? sortColumnCallback and use it in overridden lessThan? |
autotests/ksortfilterproxymodel_qml.cpp | ||
---|---|---|
112 | I don't think a unit test is the right place for example code. It's probably better to either improve the documentation of the property or add an example somewhere where it makes sense. | |
src/qml/ksortfilterproxymodel.cpp | ||
166 | In that example, you'd be sorting on the "user" role of column 0, which seems like a reasonable default to me. I would actually suggest to make sortColumn always at least 0, I don't think there really is much of a use case for -1 as default. | |
src/qml/ksortfilterproxymodel.h | ||
68 | Let's keep this a bit constrained, if we add a stub implementation of lessThan(), we can later on add a property to expose a JS callback for it somehow. |
autotests/ksortfilterproxymodel_qml.cpp | ||
---|---|---|
112 | Sure, you are right, documentation first. Logic of sortRole uses sortColumn, unit test would be a nice addition :) | |
src/qml/ksortfilterproxymodel.cpp | ||
166 | sortColumn = -1 comes directly from QSortFilterProxyModel and it has use case (disables sorting). I added separate comment for documenting this. | |
src/qml/ksortfilterproxymodel.h | ||
68 | Agree, you are right. | |
87 | Please add: The default value is -1. If \a sortRole is set, the default value is 0. |
Something I noticed just now while trying to use this: the filterString property has disappeared. PlasmaCore.SortFilterProxy does have this. I think we should restore it, otherwise you need to manually call QSFPM::setFilterFixedString or hope that you can set it as a regular expression.
src/qml/ksortfilterproxymodel.cpp | ||
---|---|---|
86 | This is using the wrong callback, it should be using m_filterColumnCallback |
src/qml/ksortfilterproxymodel.cpp | ||
---|---|---|
75 | Suggestion: Instead of directly returning the value, do this: (Also for filterAcceptsColumn below) auto result = const_cast<KSortFilterProxyModel *>(this)->m_filterCallback.call(args); if (result.isError()) { qCWarning(KITEMMODELS_LOG) << "Row filter callback produced an error:"; qCWarning(KITEMMODELS_LOG) << result.toString(); } else { return result.toBool(); } That way at least some error will be displayed when the callback fails. |