KUserFeedback

surveytargetexpressionevaluator.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include "surveytargetexpressionevaluator.h"
8#include "surveytargetexpression.h"
9
10using namespace KUserFeedback;
11
12SurveyTargetExpressionDataProvider::SurveyTargetExpressionDataProvider()
13{
14}
15
16SurveyTargetExpressionDataProvider::~SurveyTargetExpressionDataProvider()
17{
18}
19
20SurveyTargetExpressionEvaluator::SurveyTargetExpressionEvaluator()
21 : m_provider(nullptr)
22{
23}
24
25SurveyTargetExpressionEvaluator::~SurveyTargetExpressionEvaluator()
26{
27}
28
29void SurveyTargetExpressionEvaluator::setDataProvider(const SurveyTargetExpressionDataProvider* provider)
30{
31 m_provider = provider;
32}
33
34static bool variantLess(const QVariant &lhs, const QVariant &rhs)
35{
36#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
37 return QVariant::compare(lhs, rhs) == QPartialOrdering::Less;
38#else
39 return lhs < rhs;
40#endif
41}
42
43static bool variantLessOrEqual(const QVariant &lhs, const QVariant &rhs)
44{
45#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
46 const auto order = QVariant::compare(lhs, rhs);
47 return order == QPartialOrdering::Less || order == QPartialOrdering::Equivalent;
48#else
49 return lhs <= rhs;
50#endif
51}
52
53bool SurveyTargetExpressionEvaluator::evaluate(SurveyTargetExpression* expression)
54{
55 // logical operations
56 switch (expression->type()) {
57 case SurveyTargetExpression::OpLogicAnd:
58 return evaluate(expression->left()) && evaluate(expression->right());
59 case SurveyTargetExpression::OpLogicOr:
60 return evaluate(expression->left()) || evaluate(expression->right());
61 default:
62 break;
63 }
64
65 // comparison operations:
66 const auto lhs = value(expression->left());
67 const auto rhs = value(expression->right());
68 if (lhs.type() == QVariant::Invalid || rhs.type() == QVariant::Invalid) // invalid element access can never succeed
69 return false;
70 if ((lhs.type() == QVariant::String && rhs.type() != QVariant::String)
71 || (lhs.type() != QVariant::String && rhs.type() == QVariant::String))
72 return false; // strings can only be compared to strings
73
74 switch (expression->type()) {
75 case SurveyTargetExpression::OpEqual:
76 return lhs == rhs;
77 case SurveyTargetExpression::OpNotEqual:
78 return lhs != rhs;
79 case SurveyTargetExpression::OpGreater:
80 return variantLess(rhs, lhs);
81 case SurveyTargetExpression::OpGreaterEqual:
82 return variantLessOrEqual(rhs, lhs);
83 case SurveyTargetExpression::OpLess:
84 return variantLess(lhs, rhs);
85 case SurveyTargetExpression::OpLessEqual:
86 return variantLessOrEqual(lhs, rhs);
87 default:
88 break;
89 }
90
91 return false;
92}
93
94QVariant SurveyTargetExpressionEvaluator::value(SurveyTargetExpression* expression)
95{
96 switch (expression->type()) {
97 case SurveyTargetExpression::Value:
98 return expression->value();
99 case SurveyTargetExpression::ScalarElement:
100 {
101 const auto v = value(expression->source());
102 if (v.canConvert<QVariantList>() && expression->sourceElement() == QLatin1String("size"))
103 return v.value<QVariantList>().size();
104 const auto m = v.toMap();
105 const auto it = m.find(expression->sourceElement());
106 if (it != m.end() && !it.value().canConvert<QVariantMap>())
107 return it.value();
108 if (expression->sourceElement() == QLatin1String("size"))
109 return m.size();
110 return QVariant();
111 }
112 case SurveyTargetExpression::ListElement:
113 {
114 const auto v = value(expression->source()).value<QVariantList>().value(expression->value().toInt());
115 return v.toMap().value(expression->sourceElement());
116 }
117 case SurveyTargetExpression::MapElement:
118 {
119 const auto v = value(expression->source()).toMap().value(expression->value().toString());
120 qDebug() << v << value(expression->source()).toMap() << expression->value().toString();
121 return v.toMap().value(expression->sourceElement());
122 }
123 default:
124 break;
125 }
126
127 Q_ASSERT(false);
128 return QVariant();
129}
130
131QVariant SurveyTargetExpressionEvaluator::value(const QString& source)
132{
133 Q_ASSERT(m_provider);
134 const auto it = m_dataCache.constFind(source);
135 if (it != m_dataCache.constEnd())
136 return it.value();
137
138 const auto v = m_provider->sourceData(source);
139 m_dataCache.insert(source, v);
140 return v;
141}
Classes for integrating telemetry collection, survey targeting, and contribution encouragenemt and co...
const_iterator constEnd() const const
const_iterator constFind(const Key &key) const const
iterator insert(const Key &key, const T &value)
QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs)
int toInt(bool *ok) const const
QMap< QString, QVariant > toMap() const const
QString toString() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:57:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.