Skip to content

Commit eb391e3

Browse files
committed
core/scriptmodel: add objectProp, allowing js objects to be compared
1 parent 34c0b4c commit eb391e3

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

src/core/scriptmodel.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
1818
auto iter = this->mValues.begin();
1919
auto newIter = newValues.begin();
2020

21+
// TODO: cache this
22+
auto getCmpKey = [&](const QVariant& v) {
23+
if (v.canConvert<QVariantMap>()) {
24+
auto vMap = v.value<QVariantMap>();
25+
if (vMap.contains(this->cmpKey)) {
26+
return vMap.value(this->cmpKey);
27+
}
28+
}
29+
30+
return v;
31+
};
32+
33+
auto variantCmp = [&](const QVariant& a, const QVariant& b) {
34+
if (!this->cmpKey.isEmpty()) return getCmpKey(a) == getCmpKey(b);
35+
else return a == b;
36+
};
37+
38+
auto eqPredicate = [&](const QVariant& b) {
39+
return [&](const QVariant& a) { return variantCmp(a, b); };
40+
};
41+
2142
while (true) {
2243
if (newIter == newValues.end()) {
2344
if (iter == this->mValues.end()) break;
@@ -40,18 +61,19 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
4061
this->endInsertRows();
4162

4263
break;
43-
} else if (*newIter != *iter) {
44-
auto oldIter = std::find(iter, this->mValues.end(), *newIter);
64+
} else if (!variantCmp(*newIter, *iter)) {
65+
auto oldIter = std::find_if(iter, this->mValues.end(), eqPredicate(*newIter));
4566

4667
if (oldIter != this->mValues.end()) {
47-
if (std::find(newIter, newValues.end(), *iter) == newValues.end()) {
68+
if (std::find_if(newIter, newValues.end(), eqPredicate(*iter)) == newValues.end()) {
4869
// Remove any entries we would otherwise move around that aren't in the new list.
4970
auto startIter = iter;
5071

5172
do {
5273
++iter;
5374
} while (iter != this->mValues.end()
54-
&& std::find(newIter, newValues.end(), *iter) == newValues.end());
75+
&& std::find_if(newIter, newValues.end(), eqPredicate(*iter)) == newValues.end()
76+
);
5577

5678
auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
5779
auto startIndex = static_cast<qint32>(std::distance(this->mValues.begin(), startIter));
@@ -66,7 +88,7 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
6688
++oldIter;
6789
++newIter;
6890
} while (oldIter != this->mValues.end() && newIter != newValues.end()
69-
&& *oldIter == *newIter);
91+
&& variantCmp(*oldIter, *newIter));
7092

7193
auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
7294
auto oldStartIndex =
@@ -90,7 +112,8 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
90112
do {
91113
newIter++;
92114
} while (newIter != newValues.end()
93-
&& std::find(iter, this->mValues.end(), *newIter) == this->mValues.end());
115+
&& std::find_if(iter, this->mValues.end(), eqPredicate(*newIter))
116+
== this->mValues.end());
94117

95118
auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
96119
auto newIndex = static_cast<qint32>(std::distance(newValues.begin(), newIter));
@@ -123,6 +146,13 @@ void ScriptModel::setValues(const QVariantList& newValues) {
123146
emit this->valuesChanged();
124147
}
125148

149+
void ScriptModel::setObjectProp(const QString& objectProp) {
150+
if (objectProp == this->cmpKey) return;
151+
this->cmpKey = objectProp;
152+
this->updateValuesUnique(this->mValues);
153+
emit this->objectPropChanged();
154+
}
155+
126156
qint32 ScriptModel::rowCount(const QModelIndex& parent) const {
127157
if (parent != QModelIndex()) return 0;
128158
return static_cast<qint32>(this->mValues.length());

src/core/scriptmodel.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ class ScriptModel: public QAbstractListModel {
6767
/// > }
6868
/// > ```
6969
Q_PROPERTY(QVariantList values READ values WRITE setValues NOTIFY valuesChanged);
70+
/// The property that javascript objects passed into the model will be compared with.
71+
///
72+
/// For example, if `objectProp` is `"myprop"` then `{ myprop: "a", other: "y" }` and
73+
/// `{ myprop: "a", other: "z" }` will be considered equal.
74+
///
75+
/// Defaults to `""`, meaning no key.
76+
Q_PROPERTY(QString objectProp READ objectProp WRITE setObjectProp NOTIFY objectPropChanged);
7077
QML_ELEMENT;
7178

7279
public:
@@ -79,15 +86,20 @@ class ScriptModel: public QAbstractListModel {
7986

8087
void setValues(const QVariantList& newValues);
8188

89+
[[nodiscard]] QString objectProp() const { return this->cmpKey; }
90+
void setObjectProp(const QString& objectProp);
91+
8292
[[nodiscard]] qint32 rowCount(const QModelIndex& parent) const override;
8393
[[nodiscard]] QVariant data(const QModelIndex& index, qint32 role) const override;
8494
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
8595

8696
signals:
8797
void valuesChanged();
98+
void objectPropChanged();
8899

89100
private:
90101
QVariantList mValues;
102+
QString cmpKey;
91103
bool hasActiveIterators = false;
92104

93105
void updateValuesUnique(const QVariantList& newValues);

0 commit comments

Comments
 (0)