diff options
author | Dominik Holland <dominik.holland@pelagicore.com> | 2018-11-28 14:14:23 +0100 |
---|---|---|
committer | Robert Griebl <robert.griebl@pelagicore.com> | 2018-11-29 12:58:56 +0000 |
commit | 1ec7e3a9c84b4f15a7ea5dc74c870919183bc7c8 (patch) | |
tree | fbe25287299e195d5743101b723753e92e8c4137 | |
parent | 529ead91c4ffbe868d7d607666ea649af7bd3467 (diff) |
Add support for overriding the simulation/data-file at runtime
The QIviSimulationEngine can now take an extra identifier in the constructor
which is used to identify override settings for this simulation engine.
Using the following environment variable schema it is possible to set
and override which the simulation engine will use instead of the compiled
in simulation/data-file.
QTIVI_SIMULATION_OVERRIDE=<identifier>=<QML-file>
QTIVI_SIMULATION_DATA_OVERRIDE=<identifier>=<JSON-file>
Change-Id: Id2a921d8b74c619ea9662d413f0a7296de949b91
Fixes: AUTOSUITE-703
Reviewed-by: Robert Griebl <robert.griebl@pelagicore.com>
-rw-r--r-- | src/ivicore/qivisimulationengine.cpp | 92 | ||||
-rw-r--r-- | src/ivicore/qivisimulationengine.h | 4 | ||||
-rw-r--r-- | src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl | 2 |
3 files changed, 91 insertions, 7 deletions
diff --git a/src/ivicore/qivisimulationengine.cpp b/src/ivicore/qivisimulationengine.cpp index 12bc04b..b83e387 100644 --- a/src/ivicore/qivisimulationengine.cpp +++ b/src/ivicore/qivisimulationengine.cpp @@ -48,9 +48,71 @@ #include <QDebug> #include <QQmlContext> #include <QLoggingCategory> +#include <QRegularExpression> QT_BEGIN_NAMESPACE +namespace qtivi_helper { + static const QString qrcUrlLiteral = QStringLiteral("qrc:"); + static const QString qrcLiteral = QStringLiteral("qrc"); + static const QString resourceLiteral = QStringLiteral(":/"); + + QUrl toQmlUrl(const QString &path) { + if (path.startsWith(qrcUrlLiteral)) + return path; + else if (path.startsWith(resourceLiteral)) + return QString(path).prepend(qrcLiteral); + return path; + } + + class QIviSimulationOverrideParser { + public: + static QIviSimulationOverrideParser* instance() { + static QIviSimulationOverrideParser* s_parser = new QIviSimulationOverrideParser(); + return s_parser; + } + + QHash<QString, QString> simulationOverrides; + QHash<QString, QString> simulationDataOverrides; + + private: + QIviSimulationOverrideParser() { + parseEnv(qgetenv("QTIVI_SIMULATION_OVERRIDE"), simulationOverrides); + parseEnv(qgetenv("QTIVI_SIMULATION_DATA_OVERRIDE"), simulationDataOverrides); + } + + void parseEnv(const QByteArray &rulesSrc, QHash<QString, QString> &hash) { + const QString content = QString::fromLocal8Bit(rulesSrc); + const auto lines = content.splitRef(QLatin1Char(';')); + for (auto line : lines) { + // Remove whitespace at start and end of line: + line = line.trimmed(); + + int equalPos = line.indexOf(QLatin1Char('=')); + if (equalPos != -1) { + if (line.lastIndexOf(QLatin1Char('=')) == equalPos) { + const auto key = line.left(equalPos).trimmed(); + const auto valueStr = line.mid(equalPos + 1).trimmed(); + + auto fixedStr = valueStr; + if (fixedStr.startsWith(qrcUrlLiteral)) + fixedStr = fixedStr.mid(3); + + if (QFile::exists(fixedStr.toString())) + hash.insert(key.toString(), valueStr.toString()); + else + qCWarning(qLcIviSimulationEngine, "Ignoring malformed override: File does not exist: '%s'", fixedStr.toUtf8().constData()); + } else { + qCWarning(qLcIviSimulationEngine, "Ignoring malformed override: '%s'", line.toUtf8().constData()); + } + } + } + } + }; +} + +using namespace qtivi_helper; + /*! \class QIviSimulationEngine \inmodule QtIviCore @@ -221,19 +283,31 @@ QT_BEGIN_NAMESPACE */ QIviSimulationEngine::QIviSimulationEngine(QObject *parent) + : QIviSimulationEngine(QString(), parent) +{ +} + +QIviSimulationEngine::QIviSimulationEngine(const QString &identifier, QObject *parent) : QQmlApplicationEngine (parent) , m_globalObject(new QIviSimulationGlobalObject) + , m_identifier(identifier) { rootContext()->setContextProperty(QStringLiteral("IviSimulator"), m_globalObject); } void QIviSimulationEngine::loadSimulationData(const QString &dataFile) { - qCDebug(qLcIviSimulationEngine) << "loading SimulationData" << dataFile; + QString filePath = dataFile; + if (!m_identifier.isEmpty() && QIviSimulationOverrideParser::instance()->simulationDataOverrides.contains(m_identifier)) { + filePath = QIviSimulationOverrideParser::instance()->simulationDataOverrides.value(m_identifier); + qCWarning(qLcIviSimulationEngine, "Detected matching simulation data override: %s=%s", qPrintable(m_identifier), qPrintable(filePath)); + } - QFile file(dataFile); + qCDebug(qLcIviSimulationEngine, "loading SimulationData for engine %s: %s", qPrintable(m_identifier), qPrintable(filePath)); + + QFile file(filePath); if (!file.open(QFile::ReadOnly)) { - qCCritical(qLcIviSimulationEngine, "Cannot open the simulation data file %s: %s", qPrintable(dataFile), qPrintable(file.errorString())); + qCCritical(qLcIviSimulationEngine, "Cannot open the simulation data file %s: %s", qPrintable(filePath), qPrintable(file.errorString())); return; } @@ -241,7 +315,7 @@ void QIviSimulationEngine::loadSimulationData(const QString &dataFile) QByteArray data = file.readAll(); QJsonDocument document = QJsonDocument::fromJson(data, &pe); if (pe.error != QJsonParseError::NoError) { - qCCritical(qLcIviSimulationEngine, "Error parsing the simulation data in %s: %s", qPrintable(dataFile), qPrintable(pe.errorString())); + qCCritical(qLcIviSimulationEngine, "Error parsing the simulation data in %s: %s", qPrintable(filePath), qPrintable(pe.errorString())); qCCritical(qLcIviSimulationEngine, "Error context:\n %s", data.mid(qMax(pe.offset - 20, 0), 40).data()); } m_globalObject->setSimulationData(document.toVariant()); @@ -255,7 +329,15 @@ void QIviSimulationEngine::loadSimulationData(const QString &dataFile) */ void QIviSimulationEngine::loadSimulation(const QUrl &file) { - load(file); + QUrl filePath = file.toLocalFile(); + if (!m_identifier.isEmpty() && QIviSimulationOverrideParser::instance()->simulationOverrides.contains(m_identifier)) { + filePath = toQmlUrl(QIviSimulationOverrideParser::instance()->simulationOverrides.value(m_identifier)); + qCWarning(qLcIviSimulationEngine, "Detected matching simulation override: %s=%s", qPrintable(m_identifier), qPrintable(filePath.toString())); + } + + qCDebug(qLcIviSimulationEngine, "loading simulation for engine %s: %s", qPrintable(m_identifier), qPrintable(filePath.toString())); + + load(filePath); } /*! diff --git a/src/ivicore/qivisimulationengine.h b/src/ivicore/qivisimulationengine.h index a79d269..f0cea30 100644 --- a/src/ivicore/qivisimulationengine.h +++ b/src/ivicore/qivisimulationengine.h @@ -55,7 +55,8 @@ class Q_QTIVICORE_EXPORT QIviSimulationEngine : public QQmlApplicationEngine { Q_OBJECT public: - QIviSimulationEngine(QObject *parent = nullptr); + explicit QIviSimulationEngine(QObject *parent = nullptr); + explicit QIviSimulationEngine(const QString &identifier, QObject *parent = nullptr); template <typename T> void registerSimulationInstance(T* instance, const char *uri, int versionMajor, int versionMinor, const char *qmlName) { @@ -69,6 +70,7 @@ public: private: QIviSimulationGlobalObject *m_globalObject; + QString m_identifier; }; QT_END_NAMESPACE diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl b/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl index 39b67ae..446e07e 100644 --- a/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl +++ b/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl @@ -63,7 +63,7 @@ extern {{class}}::InterfaceBuilder {{module.tags.config.interfaceBuilder}}; /*! \internal */ {{class}}::{{class}}(QObject *parent) : QObject(parent) - , m_simulationEngine(new QIviSimulationEngine(this)) + , m_simulationEngine(new QIviSimulationEngine("{{module.name|lower}}", this)) { {% if module.tags.config.interfaceBuilder %} m_interfaces = {{module.tags.config.interfaceBuilder}}(this); |