aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Holland <dominik.holland@pelagicore.com>2018-10-16 11:21:27 +0200
committerDominik Holland <dominik.holland@pelagicore.com>2018-10-29 10:47:51 +0000
commite65f8d9783de9b0f24719c8299bc69382c6e9a67 (patch)
treebea6f02a94978bb76aa685a565726ad3fc517870
parent3c44b7c2e68bb8df12e7317c3e094732019cba2b (diff)
Add a way to load and parse the data to the QIviSimulationEngine
The new loadSimulationData() function can load a JSON file and store it's content in the IviSimulator singelton. The IviSimulator singleton provides functions to interpret the JSON values and other helpers e.g. checking for min/max/domain values. Task-number: AUTOSUITE-629 Change-Id: I2832cc0b29379144845a8ed295fc2d988273ff0c Reviewed-by: Robert Griebl <robert.griebl@pelagicore.com>
-rw-r--r--src/ivicore/ivicore.pro6
-rw-r--r--src/ivicore/qiviqmlconversion_helper.cpp70
-rw-r--r--src/ivicore/qiviqmlconversion_helper.h2
-rw-r--r--src/ivicore/qivisimulationengine.cpp22
-rw-r--r--src/ivicore/qivisimulationengine.h7
-rw-r--r--src/ivicore/qivisimulationglobalobject.cpp189
-rw-r--r--src/ivicore/qivisimulationglobalobject_p.h85
-rw-r--r--src/tools/ivigenerator/templates_frontend/struct.cpp.tpl27
-rw-r--r--src/tools/ivigenerator/templates_frontend/struct.h.tpl7
9 files changed, 409 insertions, 6 deletions
diff --git a/src/ivicore/ivicore.pro b/src/ivicore/ivicore.pro
index f0c640c..ead09d6 100644
--- a/src/ivicore/ivicore.pro
+++ b/src/ivicore/ivicore.pro
@@ -58,7 +58,8 @@ HEADERS += \
qivipendingreply_p.h \
qivisimulationengine.h \
qivisimulationproxy.h \
- qtivicoremodule.h
+ qtivicoremodule.h \
+ qivisimulationglobalobject_p.h
SOURCES += \
qiviservicemanager.cpp \
@@ -83,7 +84,8 @@ SOURCES += \
qivipendingreply.cpp \
qivisimulationengine.cpp \
qivisimulationproxy.cpp \
- qtivicoremodule.cpp
+ qtivicoremodule.cpp \
+ qivisimulationglobalobject.cpp
include(queryparser/queryparser.pri)
diff --git a/src/ivicore/qiviqmlconversion_helper.cpp b/src/ivicore/qiviqmlconversion_helper.cpp
index 66381b9..0372b6b 100644
--- a/src/ivicore/qiviqmlconversion_helper.cpp
+++ b/src/ivicore/qiviqmlconversion_helper.cpp
@@ -49,6 +49,13 @@
QT_BEGIN_NAMESPACE
+namespace qtivi_helper {
+ static const QString valueLiteral = QStringLiteral("value");
+ static const QString typeLiteral = QStringLiteral("type");
+}
+
+using namespace qtivi_helper;
+
void qtivi_qmlOrCppWarning(const QObject *obj, const char *errorString)
{
qtivi_qmlOrCppWarning(obj, QLatin1String(errorString));
@@ -84,4 +91,67 @@ void qtivi_qmlOrCppWarning(const QObject *obj, const QString &errorString)
v4->throwError(errorString);
}
+QVariant convertFromJSON(const QVariant &val)
+{
+ QVariant value = val;
+ // First try to convert the values to a Map or a List
+ // This is needed as it could also store a QStringList or a Hash
+ if (value.canConvert(QVariant::Map))
+ value.convert(QVariant::Map);
+ if (value.canConvert(QVariant::List))
+ value.convert(QVariant::List);
+
+ if (value.type() == QVariant::Map) {
+ const QVariantMap map = value.toMap();
+ if (map.contains(typeLiteral) && map.contains(valueLiteral)) {
+ const QString type = map.value(typeLiteral).toString();
+ const QVariant value = map.value(valueLiteral);
+
+ if (type == QStringLiteral("enum")) {
+ QString enumValue = value.toString();
+ const int lastIndex = enumValue.lastIndexOf(QStringLiteral("::"));
+ const QString className = enumValue.left(lastIndex - 1 );
+ enumValue = enumValue.right(enumValue.count() - lastIndex - 2);
+ const QMetaObject *mo = QMetaType::metaObjectForType(QMetaType::type(className.toLatin1()));
+ if (!mo)
+ return QVariant();
+
+ for (int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) {
+ QMetaEnum me = mo->enumerator(i);
+ bool ok = false;
+ int value = me.keysToValue(enumValue.toLatin1(), &ok);
+ if (ok)
+ return value;
+ }
+ qWarning() << "Couldn't parse the enum definition" << map;
+ return QVariant();
+ } else {
+ int typeId = QMetaType::type(type.toLatin1());
+ const QMetaObject *mo = QMetaType::metaObjectForType(typeId);
+ if (!mo)
+ return QVariant();
+
+ QVariantList values = value.toList();
+ for (auto i = values.begin(); i != values.end(); ++i)
+ *i = convertFromJSON(*i);
+
+ void *gadget = mo->newInstance(Q_ARG(QVariant, QVariant(values)));
+ return QVariant(typeId, gadget);
+ }
+ }
+
+ QVariantMap convertedValues;
+ for (auto i = map.constBegin(); i != map.constEnd(); ++i)
+ convertedValues.insert(i.key(), convertFromJSON(i.value()));
+ return convertedValues;
+ } else if (value.type() == QVariant::List) {
+ QVariantList values = value.toList();
+ for (auto i = values.begin(); i != values.end(); ++i)
+ *i = convertFromJSON(*i);
+ return values;
+ }
+
+ return value;
+}
+
QT_END_NAMESPACE
diff --git a/src/ivicore/qiviqmlconversion_helper.h b/src/ivicore/qiviqmlconversion_helper.h
index d6685ee..2c30772 100644
--- a/src/ivicore/qiviqmlconversion_helper.h
+++ b/src/ivicore/qiviqmlconversion_helper.h
@@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE
Q_QTIVICORE_EXPORT void qtivi_qmlOrCppWarning(const QObject *obj, const char *errorString);
Q_QTIVICORE_EXPORT void qtivi_qmlOrCppWarning(const QObject *obj, const QString& errorString);
+Q_QTIVICORE_EXPORT QVariant convertFromJSON(const QVariant &val);
+
template <typename T> QVariant qtivi_convertValue(const T &val)
{
QVariant var;
diff --git a/src/ivicore/qivisimulationengine.cpp b/src/ivicore/qivisimulationengine.cpp
index fa10d3b..69a0ddb 100644
--- a/src/ivicore/qivisimulationengine.cpp
+++ b/src/ivicore/qivisimulationengine.cpp
@@ -40,8 +40,13 @@
****************************************************************************/
#include "qivisimulationengine.h"
+#include <qivisimulationglobalobject_p.h>
+#include <QDir>
#include <QFile>
+#include <QJsonDocument>
+#include <QDebug>
+#include <QQmlContext>
QT_BEGIN_NAMESPACE
@@ -216,7 +221,24 @@ QT_BEGIN_NAMESPACE
QIviSimulationEngine::QIviSimulationEngine(QObject *parent)
: QQmlApplicationEngine (parent)
+ , m_globalObject(new QIviSimulationGlobalObject)
{
+ rootContext()->setContextProperty(QStringLiteral("IviSimulator"), m_globalObject);
+}
+
+void QIviSimulationEngine::loadSimulationData(const QString &dataFile)
+{
+ if (!QFile::exists(dataFile))
+ return;
+
+ QFile file(QDir::current().absoluteFilePath(dataFile));
+ if (file.open(QFile::ReadOnly)) {
+ QJsonParseError pe;
+ QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &pe);
+ if (pe.error != QJsonParseError::NoError)
+ qCritical() << "Error parsing the provided simulation data: " << pe.errorString();
+ m_globalObject->setSimulationData(document.toVariant());
+ }
}
/*!
diff --git a/src/ivicore/qivisimulationengine.h b/src/ivicore/qivisimulationengine.h
index 9e23a4b..a79d269 100644
--- a/src/ivicore/qivisimulationengine.h
+++ b/src/ivicore/qivisimulationengine.h
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
+class QIviSimulationGlobalObject;
+
class Q_QTIVICORE_EXPORT QIviSimulationEngine : public QQmlApplicationEngine
{
Q_OBJECT
@@ -59,11 +61,14 @@ public:
{
//pass engine here to check that it's only used in this engine
qtivi_private::QIviSimulationProxy<T>::registerInstance(this, instance);
- //@uri BridgetTest
qmlRegisterType< qtivi_private::QIviSimulationProxy<T> >(uri, versionMajor, versionMinor, qmlName);
}
+ void loadSimulationData(const QString &dataFile);
void loadSimulation(const QUrl &file);
+
+private:
+ QIviSimulationGlobalObject *m_globalObject;
};
QT_END_NAMESPACE
diff --git a/src/ivicore/qivisimulationglobalobject.cpp b/src/ivicore/qivisimulationglobalobject.cpp
new file mode 100644
index 0000000..c1b2161
--- /dev/null
+++ b/src/ivicore/qivisimulationglobalobject.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtIvi module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include "qivisimulationglobalobject_p.h"
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qtivi_helper {
+ static const QString unsupportedLiteral = QStringLiteral("unsupported");
+ static const QString minLiteral = QStringLiteral("min");
+ static const QString maxLiteral = QStringLiteral("max");
+ static const QString domainLiteral = QStringLiteral("domain");
+}
+
+using namespace qtivi_helper;
+
+QIviSimulationGlobalObject::QIviSimulationGlobalObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QVariant QIviSimulationGlobalObject::simulationData() const
+{
+ return m_simulationData;
+}
+
+void QIviSimulationGlobalObject::setSimulationData(const QVariant &simulationData)
+{
+ m_simulationData = simulationData;
+}
+
+QVariantMap QIviSimulationGlobalObject::findData(const QVariantMap &data, const QString &interface)
+{
+ QString key = interface;
+ forever {
+ if (data.contains(key))
+ return data.value(key).toMap();
+
+ int index = key.indexOf('.');
+ if (index == -1)
+ break;
+ key = key.right(key.count() - index);
+ }
+
+ return QVariantMap();
+}
+
+void QIviSimulationGlobalObject::initializeDefault(const QVariantMap &data, QObject *object)
+{
+ for (auto i = data.constBegin(); i != data.constEnd(); ++i) {
+ const QVariant defVal = defaultValue(i.value().toMap());
+ if (defVal.isValid()) {
+ QVariant currentValue = object->property(i.key().toLatin1());
+ if (QIviPagingModelInterface *model = currentValue.value<QIviPagingModelInterface*>()) {
+ QVariantList list = defVal.toList();
+ for (auto i = list.crbegin(); i != list.crend(); ++i)
+ QMetaObject::invokeMethod(model, "insert", Q_ARG(int, 0), createArgument(*i));
+ } else {
+ object->setProperty(i.key().toLatin1(), defVal);
+ }
+ }
+
+ QVariant currentValue = object->property("zones");
+ QQmlPropertyMap *map = currentValue.value<QQmlPropertyMap*>();
+ if (!map)
+ continue;
+ const QStringList zones = data.value(QStringLiteral("zones")).toStringList();
+ for (const QString &zone : zones) {
+ const QVariant defVal = defaultValue(i.value().toMap(), zone);
+ if (defVal.isValid()) {
+ QObject *zoneObject = map->value(zone).value<QObject*>();
+ if (zoneObject)
+ zoneObject->setProperty(i.key().toLatin1(), defVal);
+ }
+ }
+ }
+}
+
+QVariant QIviSimulationGlobalObject::defaultValue(const QVariantMap &data, const QString &zone)
+{
+ return parseDomainValue(data, QStringLiteral("default"), zone);
+}
+
+QString QIviSimulationGlobalObject::constraint(const QVariantMap &data, const QString &zone)
+{
+ const QVariant unsupportedDomain = parseDomainValue(data, unsupportedLiteral, zone);
+ const QVariant minDomain = parseDomainValue(data, minLiteral, zone);
+ const QVariant maxDomain = parseDomainValue(data, maxLiteral, zone);
+ const QVariant domainDomain = parseDomainValue(data, domainLiteral, zone);
+
+ if (unsupportedDomain.isValid())
+ return unsupportedLiteral;
+ if (minDomain.isValid() && maxDomain.isValid())
+ return QStringLiteral("[") + minDomain.toString() + QStringLiteral("-") + maxDomain.toString() + QStringLiteral("]") ;
+ if (minDomain.isValid())
+ return QStringLiteral(">= ") + minDomain.toString();
+ if (maxDomain.isValid())
+ return QStringLiteral("<= ") + maxDomain.toString();
+ if (domainDomain.isValid())
+ return domainDomain.toString();
+
+ return QString();
+}
+
+bool QIviSimulationGlobalObject::checkSettings(const QVariantMap &data, const QVariant &value, const QString &zone)
+{
+ const QVariant unsupportedDomain = parseDomainValue(data, unsupportedLiteral, zone);
+ const QVariant minDomain = parseDomainValue(data, minLiteral, zone);
+ const QVariant maxDomain = parseDomainValue(data, maxLiteral, zone);
+ const QVariant domainDomain = parseDomainValue(data, domainLiteral, zone);
+
+ if (unsupportedDomain.isValid())
+ return unsupportedDomain.toBool();
+ if (minDomain.isValid() && maxDomain.isValid())
+ return !(value < minDomain || value > maxDomain);
+ if (minDomain.isValid())
+ return value >= minDomain;
+ if (maxDomain.isValid())
+ return value <= maxDomain;
+ if (domainDomain.isValid())
+ return domainDomain.toList().contains(value);
+
+ return true;
+}
+
+QVariant QIviSimulationGlobalObject::parseDomainValue(const QVariantMap &data, const QString &domain, const QString &zone)
+{
+ if (!data.contains(domain))
+ return QVariant();
+
+ const QVariant domainData = data.value(domain);
+ if (domainData.type() == QVariant::Map) {
+ const QVariantMap domainMap = domainData.toMap();
+ QString z = zone;
+ if (zone.isEmpty())
+ z = QStringLiteral("=");
+
+ if (domainMap.contains(zone))
+ return convertFromJSON(domainMap.value(zone));
+ }
+
+ return convertFromJSON(domainData);
+}
+
+QGenericArgument QIviSimulationGlobalObject::createArgument(const QVariant &variant)
+{
+ return QGenericArgument(variant.typeName(), variant.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/ivicore/qivisimulationglobalobject_p.h b/src/ivicore/qivisimulationglobalobject_p.h
new file mode 100644
index 0000000..3ba9807
--- /dev/null
+++ b/src/ivicore/qivisimulationglobalobject_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtIvi module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#ifndef QIVISIMULATIONGLOBALOBJECT_P_H
+#define QIVISIMULATIONGLOBALOBJECT_P_H
+
+#include <qiviqmlconversion_helper.h>
+#include <QIviPagingModelInterface>
+
+#include <QtCore/QObject>
+#include <QtCore/QVariantMap>
+#include <QtCore/QMetaType>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaEnum>
+#include <QJSValue>
+#include <QQmlPropertyMap>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+class QIviSimulationGlobalObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant simulationData READ simulationData CONSTANT)
+
+public:
+ explicit QIviSimulationGlobalObject(QObject *parent = nullptr);
+
+ QVariant simulationData() const;
+ void setSimulationData(const QVariant &simulationData);
+
+ Q_INVOKABLE QVariantMap findData(const QVariantMap &data, const QString &interface);
+ Q_INVOKABLE void initializeDefault(const QVariantMap &data, QObject *object);
+ Q_INVOKABLE QVariant defaultValue(const QVariantMap &data, const QString &zone = QString());
+ Q_INVOKABLE QString constraint(const QVariantMap &data, const QString &zone = QString());
+ Q_INVOKABLE bool checkSettings(const QVariantMap &data, const QVariant &value, const QString &zone = QString());
+ Q_INVOKABLE QVariant parseDomainValue(const QVariantMap &data, const QString &domain, const QString &zone = QString());
+
+private:
+ QGenericArgument createArgument(const QVariant &variant);
+ QVariant m_simulationData;
+};
+
+QT_END_NAMESPACE
+
+#endif // QIVISIMULATIONGLOBALOBJECT_P_H
diff --git a/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl b/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl
index 43ec933..488f1a9 100644
--- a/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl
+++ b/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl
@@ -43,6 +43,8 @@
#include "{{class|lower}}.h"
+#include <qiviqmlconversion_helper.h>
+
QT_BEGIN_NAMESPACE
class {{class}}Private : public QSharedData
@@ -105,6 +107,31 @@ public:
{
}
+{{class}}::{{class}}(const QVariant &variant)
+ : {{class}}()
+{
+ QVariant value = convertFromJSON(variant);
+ // First try to convert the values to a Map or a List
+ // This is needed as it could also store a QStringList or a Hash
+ if (value.canConvert(QVariant::Map))
+ value.convert(QVariant::Map);
+ if (value.canConvert(QVariant::List))
+ value.convert(QVariant::List);
+
+ if (value.type() == QVariant::Map) {
+ QVariantMap map = value.toMap();
+{% for field in struct.fields %}
+ if (map.contains(QStringLiteral("{{field}}")))
+ d->m_{{field}} = map.value(QStringLiteral("{{field}}")).value<{{field|return_type}}>();
+{% endfor %}
+ } else if (value.type() == QVariant::List) {
+ QVariantList values = value.toList();
+{% for field in struct.fields %}
+ d->m_{{field}} = values.value({{loop.index0}}).value<{{field|return_type}}>();
+{% endfor %}
+ }
+}
+
/*! \internal */
{{class}}::~{{class}}()
{
diff --git a/src/tools/ivigenerator/templates_frontend/struct.h.tpl b/src/tools/ivigenerator/templates_frontend/struct.h.tpl
index ed85fef..da67518 100644
--- a/src/tools/ivigenerator/templates_frontend/struct.h.tpl
+++ b/src/tools/ivigenerator/templates_frontend/struct.h.tpl
@@ -71,10 +71,11 @@ class {{exportsymbol}} {{class}} : public QIviStandardItem
{% endfor %}
Q_CLASSINFO("IviPropertyDomains", "{{ struct.fields|json_domain|replace("\"", "\\\"") }}")
public:
- {{class}}();
- {{class}}(const {{class}} &rhs);
+ Q_INVOKABLE {{class}}();
+ Q_INVOKABLE {{class}}(const {{class}} &rhs);
{{class}} &operator=(const {{class}} &);
- {{class}}({% for field in struct.fields %}{% if not loop.first %}, {% endif %}{{field|return_type}} {{field}}{% endfor %});
+ Q_INVOKABLE {{class}}({% for field in struct.fields %}{% if not loop.first %}, {% endif %}{{field|return_type}} {{field}}{% endfor %});
+ Q_INVOKABLE {{class}}(const QVariant &variant);
~{{class}}();
QString type() const override;