Skip to content
This repository was archived by the owner on Feb 5, 2026. It is now read-only.

Commit 5176c19

Browse files
authored
Merge pull request #4 from MenloSystems/ExpressionRole-caching
Expression role caching
2 parents 33faea0 + c2cc5ce commit 5176c19

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

proxyroles/expressionrole.cpp

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,40 @@ void ExpressionRole::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyMo
6262
updateContext(proxyModel);
6363
}
6464

65-
QVariant ExpressionRole::data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel)
65+
bool ExpressionRole::isCached() const
6666
{
67-
if (!m_scriptString.isEmpty()) {
68-
QVariantMap modelMap;
69-
QHash<int, QByteArray> roles = proxyModel.roleNames();
67+
return m_cached;
68+
}
7069

71-
QQmlContext context(qmlContext(this));
72-
auto addToContext = [&] (const QString &name, const QVariant& value) {
73-
context.setContextProperty(name, value);
74-
modelMap.insert(name, value);
75-
};
70+
void ExpressionRole::setCached(bool cached)
71+
{
72+
if (m_cached == cached) {
73+
return;
74+
}
75+
76+
m_cached = cached;
77+
emit cachedChanged(m_cached);
78+
}
79+
80+
void ExpressionRole::invalidateCache()
81+
{
82+
m_cache.clear();
83+
}
7684

77-
for (auto it = roles.cbegin(); it != roles.cend(); ++it)
78-
addToContext(it.value(), proxyModel.sourceData(sourceIndex, it.key()));
79-
addToContext("index", sourceIndex.row());
85+
QVariant ExpressionRole::data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel)
86+
{
87+
if (isCached()) {
88+
const auto it = m_cache.constFind(sourceIndex);
89+
if (it != m_cache.constEnd()) {
90+
return *it;
91+
}
92+
}
8093

94+
if (!m_scriptString.isEmpty()) {
95+
const QVariant modelMap = proxyModel.sourceData(sourceIndex);
96+
QQmlContext context(qmlContext(this));
97+
context.setContextProperty("index", sourceIndex.row());
98+
context.setContextProperty("modelIndex", sourceIndex);
8199
context.setContextProperty("model", modelMap);
82100

83101
QQmlExpression expression(m_scriptString, &context);
@@ -87,6 +105,11 @@ QVariant ExpressionRole::data(const QModelIndex& sourceIndex, const QQmlSortFilt
87105
qWarning() << expression.error();
88106
return true;
89107
}
108+
109+
if (isCached()) {
110+
m_cache[sourceIndex] = result;
111+
}
112+
90113
return result;
91114
}
92115
return QVariant();
@@ -99,16 +122,13 @@ void ExpressionRole::updateContext(const QQmlSortFilterProxyModel& proxyModel)
99122
// what about roles changes ?
100123
QVariantMap modelMap;
101124

102-
auto addToContext = [&] (const QString &name, const QVariant& value) {
103-
m_context->setContextProperty(name, value);
104-
modelMap.insert(name, value);
105-
};
106-
107-
for (const QByteArray& roleName : proxyModel.roleNames().values())
108-
addToContext(roleName, QVariant());
109-
110-
addToContext("index", -1);
125+
const auto roleNames = proxyModel.roleNames().values();
126+
for (const QByteArray& roleName : roleNames) {
127+
modelMap[roleName] = QVariant();
128+
}
111129

130+
m_context->setContextProperty("index", -1);
131+
m_context->setContextProperty("modelIndex", QModelIndex());
112132
m_context->setContextProperty("model", modelMap);
113133
updateExpression();
114134
}
@@ -120,7 +140,10 @@ void ExpressionRole::updateExpression()
120140

121141
delete m_expression;
122142
m_expression = new QQmlExpression(m_scriptString, m_context, 0, this);
123-
connect(m_expression, &QQmlExpression::valueChanged, this, &ExpressionRole::invalidate);
143+
connect(m_expression, &QQmlExpression::valueChanged, this, [=] {
144+
invalidateCache();
145+
invalidate();
146+
});
124147
m_expression->setNotifyOnValueChanged(true);
125148
m_expression->evaluate();
126149
}

proxyroles/expressionrole.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#define EXPRESSIONROLE_H
33

44
#include "singlerole.h"
5+
#include <QMap>
6+
#include <QPersistentModelIndex>
57
#include <QQmlScriptString>
68

79
class QQmlExpression;
@@ -12,17 +14,24 @@ class ExpressionRole : public SingleRole
1214
{
1315
Q_OBJECT
1416
Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged)
17+
Q_PROPERTY(bool cached READ isCached WRITE setCached NOTIFY cachedChanged)
1518

1619
public:
1720
using SingleRole::SingleRole;
1821

1922
const QQmlScriptString& expression() const;
2023
void setExpression(const QQmlScriptString& scriptString);
24+
bool isCached() const;
2125

2226
void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override;
2327

28+
public slots:
29+
void setCached(bool cached);
30+
void invalidateCache();
31+
2432
Q_SIGNALS:
2533
void expressionChanged();
34+
void cachedChanged(bool cached);
2635

2736
private:
2837
QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override;
@@ -32,6 +41,9 @@ class ExpressionRole : public SingleRole
3241
QQmlScriptString m_scriptString;
3342
QQmlExpression* m_expression = nullptr;
3443
QQmlContext* m_context = nullptr;
44+
45+
QHash<QPersistentModelIndex, QVariant> m_cache;
46+
bool m_cached = false;
3547
};
3648

3749
}

0 commit comments

Comments
 (0)