summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-01 03:07:06 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-01 03:07:06 +0100
commit657ed57293b0a12364747668d6afe6ded319956f (patch)
tree59d90e344ef55f353e9fee2f83c6913c4c885a0f
parent8bd6d9c71a88c294ea62b5f310471180706d0ce2 (diff)
parent89d3ea0c02f64173d47a7d1def16de22c3361158 (diff)
downloadqtivi-657ed57293b0a12364747668d6afe6ded319956f.tar.gz
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I8802ae6a42e8ceba42534759fb8be696ba56e4f6
-rw-r--r--examples/ivicore/qface-ivi-addressbook/backend_simulator/backend_simulator.pro2
-rw-r--r--examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro2
-rw-r--r--examples/ivicore/qface-ivi-remote/backend_qtro/backend_qtro.pro2
-rw-r--r--examples/ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro4
-rw-r--r--examples/ivimedia/mediaplayer/main.cpp4
-rw-r--r--examples/ivimedia/mediaplayer/mediaplayer.pro2
-rw-r--r--examples/ivimedia/tuner/main.cpp4
-rw-r--r--examples/ivimedia/tuner/tuner.pro2
-rw-r--r--examples/ivivehiclefunctions/climate_qml/climate_qml.pro2
-rw-r--r--examples/ivivehiclefunctions/climate_qml/main.cpp4
-rw-r--r--examples/ivivehiclefunctions/ivivehiclefunctions.pro3
-rw-r--r--examples/ivivehiclefunctions/window_qml/main.cpp4
-rw-r--r--examples/ivivehiclefunctions/window_qml/window_qml.pro2
-rw-r--r--mkspecs/features/ivigenerator.prf35
-rw-r--r--src/geniviextras/qdltregistration.cpp3
-rw-r--r--src/helper/remoteobjects/qivipagingmodel.rep14
-rw-r--r--src/helper/remoteobjects/qivipagingmodelqtroadapter.cpp73
-rw-r--r--src/helper/remoteobjects/qivipagingmodelqtroadapter.h78
-rw-r--r--src/helper/remoteobjects/remoteobjects.pro15
-rw-r--r--src/imports/core/plugins.qmltypes274
-rw-r--r--src/imports/media/plugins.qmltypes274
-rw-r--r--src/ivicore/doc/qtivi-project.qdocconf4
-rw-r--r--src/ivicore/doc/src/concepts.qdoc2
-rw-r--r--src/ivicore/doc/src/configuration.qdoc12
-rw-r--r--src/ivicore/doc/src/examples-qface-ivi-climate.qdoc4
-rw-r--r--src/ivicore/doc/src/examples-qface-tutorial.qdoc21
-rw-r--r--src/ivicore/doc/src/external-resources.qdoc5
-rw-r--r--src/ivicore/doc/src/ivigenerator/generator-usage.qdoc37
-rw-r--r--src/ivicore/doc/src/ivigenerator/ivigenerator.qdoc4
-rw-r--r--src/ivicore/doc/src/ivigenerator/qmake-integration.qdoc4
-rw-r--r--src/ivicore/doc/src/qtivi.qdoc3
-rw-r--r--src/ivicore/qiviabstractfeature.cpp26
-rw-r--r--src/ivicore/qiviabstractfeaturelistmodel.cpp2
-rw-r--r--src/ivicore/qivipagingmodel.cpp2
-rw-r--r--src/ivicore/qivipagingmodelinterface.cpp4
-rw-r--r--src/ivicore/qivipagingmodelinterface.h2
-rw-r--r--src/ivicore/qivipendingreply.cpp42
-rw-r--r--src/ivicore/qivipendingreply.h2
-rw-r--r--src/ivicore/qiviqmlconversion_helper.cpp38
-rw-r--r--src/ivicore/qiviserviceinterface.cpp2
-rw-r--r--src/ivicore/qiviservicemanager.cpp44
-rw-r--r--src/ivicore/qiviservicemanager_p.h2
-rw-r--r--src/ivicore/qivisimulationglobalobject.cpp18
-rw-r--r--src/ivicore/qivisimulationglobalobject_p.h2
-rw-r--r--src/ivicore/qtivicoremodule.cpp2
-rw-r--r--src/ivivehiclefunctions/doc/src/examples-climate_widget.qdoc2
-rw-r--r--src/plugins/ivimedia/media_qtro/media_qtro.pro2
-rw-r--r--src/plugins/ivimedia/media_qtro/mediaplugin.cpp6
-rw-r--r--src/plugins/ivimedia/media_qtro/mediaplugin.h4
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaplayerbackend.cpp4
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaplugin.cpp6
-rw-r--r--src/plugins/ivimedia/media_simulator/mediaplugin.h4
-rw-r--r--src/plugins/ivimedia/tuner_simulator/tunerplugin.cpp6
-rw-r--r--src/plugins/ivimedia/tuner_simulator/tunerplugin.h4
-rw-r--r--src/plugins/ivivehiclefunctions/vehiclefunctions_qtro/vehiclefunctions_qtro.pro2
-rw-r--r--src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/QIviConcreteWindowControlSimulation.qml77
-rw-r--r--src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/vehiclefunctions_simulator.pro2
-rw-r--r--src/tools/ivigenerator/common/pagingmodel.rep.tpl61
-rwxr-xr-xsrc/tools/ivigenerator/generate.py841
-rw-r--r--src/tools/ivigenerator/generator/builtin_config.py56
-rw-r--r--src/tools/ivigenerator/generator/filters.py734
-rw-r--r--src/tools/ivigenerator/generator/global_functions.py98
-rw-r--r--src/tools/ivigenerator/generator/rule_generator.py139
-rw-r--r--src/tools/ivigenerator/ivigenerator.pro162
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro.yaml12
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/backend.cpp.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/backend.cpp.tpl)19
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/backend.h.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/backend.h.tpl)4
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/pagingmodel.cpp.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/pagingmodel.cpp.tpl)18
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/pagingmodel.h.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/pagingmodel.h.tpl)12
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/plugin.cpp.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/plugin.cpp.tpl)8
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/plugin.h.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/plugin.h.tpl)2
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/plugin.json (renamed from src/tools/ivigenerator/templates_backend_qtro/plugin.json)0
-rw-r--r--src/tools/ivigenerator/templates/backend_qtro/plugin.pri.tpl (renamed from src/tools/ivigenerator/templates_backend_qtro/plugin.pri.tpl)5
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator.yaml19
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator/plugin.cpp.tpl (renamed from src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl)2
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator/plugin.h.tpl (renamed from src/tools/ivigenerator/templates_backend_simulator/plugin.h.tpl)2
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator/plugin.json (renamed from src/tools/ivigenerator/templates_backend_simulator/plugin.json)0
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator/plugin.pri.tpl (renamed from src/tools/ivigenerator/templates_backend_simulator/plugin.pri.tpl)4
-rw-r--r--src/tools/ivigenerator/templates/backend_simulator/plugin.pro (renamed from src/tools/ivigenerator/templates_backend_simulator/plugin.pro)0
-rw-r--r--src/tools/ivigenerator/templates/common/backend_simulation.cpp.tpl (renamed from src/tools/ivigenerator/common/backend_simulation.cpp.tpl)8
-rw-r--r--src/tools/ivigenerator/templates/common/backend_simulation.h.tpl (renamed from src/tools/ivigenerator/common/backend_simulation.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/backend_simulation.qml.tpl (renamed from src/tools/ivigenerator/common/backend_simulation.qml.tpl)28
-rw-r--r--src/tools/ivigenerator/templates/common/generated_comment.cpp.tpl (renamed from src/tools/ivigenerator/common/generated_comment.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/interface.rep.tpl (renamed from src/tools/ivigenerator/common/interface.rep.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/module_simulation.qml.tpl (renamed from src/tools/ivigenerator/common/module_simulation.qml.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/pagingmodel_simulation.cpp.tpl (renamed from src/tools/ivigenerator/common/pagingmodel_simulation.cpp.tpl)10
-rw-r--r--src/tools/ivigenerator/templates/common/pagingmodel_simulation.h.tpl (renamed from src/tools/ivigenerator/common/pagingmodel_simulation.h.tpl)5
-rw-r--r--src/tools/ivigenerator/templates/common/plugins.qmltypes.tpl (renamed from src/tools/ivigenerator/common/plugins.qmltypes.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/qmldir.tpl (renamed from src/tools/ivigenerator/common/qmldir.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/qtivi_macros.j2 (renamed from src/tools/ivigenerator/common/qtivi_macros.j2)0
-rw-r--r--src/tools/ivigenerator/templates/common/simulation.qmltypes.tpl (renamed from src/tools/ivigenerator/common/simulation.qmltypes.tpl)1
-rw-r--r--src/tools/ivigenerator/templates/common/simulation.qrc.tpl (renamed from src/tools/ivigenerator/common/simulation.qrc.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/common/simulation_data.json.tpl (renamed from src/tools/ivigenerator/common/simulation_data.json.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend.yaml23
-rw-r--r--src/tools/ivigenerator/templates/frontend/backendinterface.cpp.tpl (renamed from src/tools/ivigenerator/templates_frontend/backendinterface.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/backendinterface.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/backendinterface.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/global.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/global.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/interface.cpp.tpl (renamed from src/tools/ivigenerator/templates_frontend/interface.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/interface.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/interface.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/interface_p.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/interface_p.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/module.cpp.tpl (renamed from src/tools/ivigenerator/templates_frontend/module.cpp.tpl)19
-rw-r--r--src/tools/ivigenerator/templates/frontend/module.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/module.h.tpl)14
-rw-r--r--src/tools/ivigenerator/templates/frontend/module.pri.tpl (renamed from src/tools/ivigenerator/templates_frontend/module.pri.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/module_qml_enum.qdocinc.tpl (renamed from src/tools/ivigenerator/templates_frontend/module_qml_enum.qdocinc.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/modulefactory.cpp.tpl (renamed from src/tools/ivigenerator/templates_frontend/modulefactory.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/modulefactory.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/modulefactory.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/frontend/struct.cpp.tpl (renamed from src/tools/ivigenerator/templates_frontend/struct.cpp.tpl)49
-rw-r--r--src/tools/ivigenerator/templates/frontend/struct.h.tpl (renamed from src/tools/ivigenerator/templates_frontend/struct.h.tpl)14
-rw-r--r--src/tools/ivigenerator/templates/qmlplugin.yaml9
-rw-r--r--src/tools/ivigenerator/templates/qmlplugin/module.pri.tpl (renamed from src/tools/ivigenerator/templates_qmlplugin/module.pri.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/qmlplugin/plugin.cpp.tpl (renamed from src/tools/ivigenerator/templates_qmlplugin/plugin.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/qmlplugin/qmldir_plugin.tpl (renamed from src/tools/ivigenerator/templates_qmlplugin/qmldir_plugin.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/server_qtro.yaml9
-rw-r--r--src/tools/ivigenerator/templates/server_qtro/core.cpp.tpl (renamed from src/tools/ivigenerator/templates_server_qtro/core.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/server_qtro/core.h.tpl (renamed from src/tools/ivigenerator/templates_server_qtro/core.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/server_qtro/server.pri.tpl (renamed from src/tools/ivigenerator/templates_server_qtro/server.pri.tpl)1
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator.yaml22
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/adapter.cpp.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/adapter.cpp.tpl)53
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/adapter.h.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/adapter.h.tpl)26
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/core.cpp.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/core.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/core.h.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/core.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/main.cpp.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/main.cpp.tpl)9
-rw-r--r--src/tools/ivigenerator/templates/server_qtro_simulator/server.pri.tpl (renamed from src/tools/ivigenerator/templates_server_qtro_simulator/server.pri.tpl)1
-rw-r--r--src/tools/ivigenerator/templates/test.yaml9
-rw-r--r--src/tools/ivigenerator/templates/test/main.cpp.tpl (renamed from src/tools/ivigenerator/templates_test/main.cpp.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/test/module.pri.tpl (renamed from src/tools/ivigenerator/templates_test/module.pri.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/test/pagingmodel.h.tpl (renamed from src/tools/ivigenerator/templates_test/pagingmodel.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates/test/tst_test.cpp.tpl (renamed from src/tools/ivigenerator/templates_test/tst_test.cpp.tpl)1
-rw-r--r--src/tools/ivigenerator/templates/test/tst_test.h.tpl (renamed from src/tools/ivigenerator/templates_test/tst_test.h.tpl)0
-rw-r--r--src/tools/ivigenerator/templates_backend_qtro.yaml20
-rw-r--r--src/tools/ivigenerator/templates_backend_simulator.yaml33
-rw-r--r--src/tools/ivigenerator/templates_frontend.yaml36
-rw-r--r--src/tools/ivigenerator/templates_qmlplugin.yaml16
-rw-r--r--src/tools/ivigenerator/templates_server_qtro.yaml14
-rw-r--r--src/tools/ivigenerator/templates_server_qtro_simulator.yaml40
-rw-r--r--src/tools/ivigenerator/templates_test.yaml12
-rw-r--r--src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.cpp16
-rw-r--r--src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.h8
-rw-r--r--src/tools/media-simulation-server/qivimediaindexerqtroadapter.cpp13
-rw-r--r--src/tools/media-simulation-server/qivimediaindexerqtroadapter.h7
-rw-r--r--src/tools/media-simulation-server/qivimediaplayerqtroadapter.cpp12
-rw-r--r--src/tools/media-simulation-server/qivimediaplayerqtroadapter.h8
-rw-r--r--src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.cpp9
-rw-r--r--src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.h3
-rw-r--r--sync.profile4
-rw-r--r--tests/auto/core/core.pro1
-rw-r--r--tests/auto/core/ivigenerator/include-test.qface115
-rw-r--r--tests/auto/core/ivigenerator/ivigenerator.pro3
-rw-r--r--tests/auto/core/ivigenerator/org.example.echo.qface8
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/backend_qtro/backend_qtro.pro16
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/backend_simulator/backend_simulator.pro16
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/common/common.pro14
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/frontend/frontend.pro17
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/include-test.pro22
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/qmlplugin/qmlplugin.pro12
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/simulation_server_qtro/simulation_server_qtro.pro16
-rw-r--r--tests/auto/core/ivigenerator/projects/include-test/test/test.pro15
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_qtro/backend_qtro.pro2
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_simulator/backend_simulator.pro2
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-noprivate/backend_simulator/backend_simulator.pro2
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-qtro/backend_qtro/backend_qtro.pro2
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.cpp2
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.h4
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/tst_echoqtro.cpp1
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.cpp4
-rw-r--r--tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.pro2
-rw-r--r--tests/auto/core/ivigenerator/projects/projects.pro1
-rw-r--r--tests/auto/core/ivigenerator/qface imports/common.qface20
-rw-r--r--tests/auto/core/qivisimulationengine/invalid-data.json20
-rw-r--r--tests/auto/core/qivisimulationengine/qivisimulationengine.pro3
-rw-r--r--tests/auto/core/qivisimulationengine/resource.qrc7
-rw-r--r--tests/auto/core/qivisimulationengine/simple.json3
-rw-r--r--tests/auto/core/qivisimulationengine/simple.qml5
-rw-r--r--tests/auto/core/qivisimulationengine/tst_qivisimulationengine.cpp68
-rw-r--r--tests/auto/core/qivisimulationglobalobject/qivisimulationglobalobject.pro10
-rw-r--r--tests/auto/core/qivisimulationglobalobject/tst_qivisimulationglobalobject.cpp490
-rw-r--r--tests/auto/core/servicemanagertest/tst_servicemanagertest.cpp97
177 files changed, 3571 insertions, 1395 deletions
diff --git a/examples/ivicore/qface-ivi-addressbook/backend_simulator/backend_simulator.pro b/examples/ivicore/qface-ivi-addressbook/backend_simulator/backend_simulator.pro
index c1cc0e1..3ff067c 100644
--- a/examples/ivicore/qface-ivi-addressbook/backend_simulator/backend_simulator.pro
+++ b/examples/ivicore/qface-ivi-addressbook/backend_simulator/backend_simulator.pro
@@ -14,7 +14,7 @@ CONFIG += ivigenerator plugin
QFACE_FORMAT = backend_simulator
QFACE_SOURCES = ../example-ivi-addressbook.qface
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = AddressBookPlugin
+PLUGIN_CLASS_NAME = AddressBookSimulatorPlugin
CONFIG += install_ok # Do not cargo-cult this!
target.path = $$[QT_INSTALL_EXAMPLES]/ivicore/qface-ivi-addressbook/qtivi/
diff --git a/examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro b/examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro
index c38cb8c..7d2b1b9 100644
--- a/examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro
+++ b/examples/ivicore/qface-ivi-climate/backend_simulator/backend_simulator.pro
@@ -18,7 +18,7 @@ CONFIG += ivigenerator plugin
QFACE_FORMAT = backend_simulator
QFACE_SOURCES = ../example-ivi-climate.qface
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = ClimatePlugin
+PLUGIN_CLASS_NAME = ClimateSimulatorPlugin
#! [2]
CONFIG += install_ok # Do not cargo-cult this!
target.path = $$[QT_INSTALL_EXAMPLES]/ivicore/qface-ivi-climate/qtivi/
diff --git a/examples/ivicore/qface-ivi-remote/backend_qtro/backend_qtro.pro b/examples/ivicore/qface-ivi-remote/backend_qtro/backend_qtro.pro
index 7cee6be..e4bd712 100644
--- a/examples/ivicore/qface-ivi-remote/backend_qtro/backend_qtro.pro
+++ b/examples/ivicore/qface-ivi-remote/backend_qtro/backend_qtro.pro
@@ -18,7 +18,7 @@ CONFIG += ivigenerator plugin
QFACE_FORMAT = backend_qtro
QFACE_SOURCES = ../example-ivi-remote.qface
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = RemoteClientPlugin
+PLUGIN_CLASS_NAME = RemoteClientQtROPlugin
#! [2]
CONFIG += install_ok # Do not cargo-cult this!
target.path = $$[QT_INSTALL_EXAMPLES]/ivicore/qface-ivi-remote/qtivi/
diff --git a/examples/ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro b/examples/ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
index a80c220..48c0164 100644
--- a/examples/ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
+++ b/examples/ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
@@ -12,9 +12,9 @@ INCLUDEPATH += $$OUT_PWD/../frontend
QFACE_FORMAT = server_qtro_simulator
QFACE_SOURCES = ../instrument-cluster.qface
-RESOURCES += ../backend_simulator/simulation.qrc
-
QML_IMPORT_PATH = $$OUT_PWD/qml
+RESOURCES += ../backend_simulator/simulation.qrc
+
target.path = $$[QT_INSTALL_EXAMPLES]/ivicore/qface-tutorial/chapter5-ipc/simulation_server
INSTALLS += target
diff --git a/examples/ivimedia/mediaplayer/main.cpp b/examples/ivimedia/mediaplayer/main.cpp
index 192c982..eeffc04 100644
--- a/examples/ivimedia/mediaplayer/main.cpp
+++ b/examples/ivimedia/mediaplayer/main.cpp
@@ -51,12 +51,12 @@
**
****************************************************************************/
-#include <QApplication>
+#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
- QApplication app(argc, argv);
+ QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/ivimedia/mediaplayer/mediaplayer.pro b/examples/ivimedia/mediaplayer/mediaplayer.pro
index 29517aa..f8f527f 100644
--- a/examples/ivimedia/mediaplayer/mediaplayer.pro
+++ b/examples/ivimedia/mediaplayer/mediaplayer.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick widgets ivicore
+QT += qml quick ivicore
CONFIG += c++11
diff --git a/examples/ivimedia/tuner/main.cpp b/examples/ivimedia/tuner/main.cpp
index 192c982..eeffc04 100644
--- a/examples/ivimedia/tuner/main.cpp
+++ b/examples/ivimedia/tuner/main.cpp
@@ -51,12 +51,12 @@
**
****************************************************************************/
-#include <QApplication>
+#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
- QApplication app(argc, argv);
+ QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/ivimedia/tuner/tuner.pro b/examples/ivimedia/tuner/tuner.pro
index 510cf6e..5a2b6d0 100644
--- a/examples/ivimedia/tuner/tuner.pro
+++ b/examples/ivimedia/tuner/tuner.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick widgets ivicore
+QT += qml quick ivicore
CONFIG += c++11
diff --git a/examples/ivivehiclefunctions/climate_qml/climate_qml.pro b/examples/ivivehiclefunctions/climate_qml/climate_qml.pro
index 07ba83d..6c44293 100644
--- a/examples/ivivehiclefunctions/climate_qml/climate_qml.pro
+++ b/examples/ivivehiclefunctions/climate_qml/climate_qml.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick widgets
+QT += qml quick
SOURCES += main.cpp
diff --git a/examples/ivivehiclefunctions/climate_qml/main.cpp b/examples/ivivehiclefunctions/climate_qml/main.cpp
index 192c982..eeffc04 100644
--- a/examples/ivivehiclefunctions/climate_qml/main.cpp
+++ b/examples/ivivehiclefunctions/climate_qml/main.cpp
@@ -51,12 +51,12 @@
**
****************************************************************************/
-#include <QApplication>
+#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
- QApplication app(argc, argv);
+ QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/ivivehiclefunctions/ivivehiclefunctions.pro b/examples/ivivehiclefunctions/ivivehiclefunctions.pro
index 121e7e3..19ff424 100644
--- a/examples/ivivehiclefunctions/ivivehiclefunctions.pro
+++ b/examples/ivivehiclefunctions/ivivehiclefunctions.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
- climate_widget \
climate_qml \
window_qml
+
+qtHaveModule(widgets): SUBDIRS += climate_widget
diff --git a/examples/ivivehiclefunctions/window_qml/main.cpp b/examples/ivivehiclefunctions/window_qml/main.cpp
index 192c982..eeffc04 100644
--- a/examples/ivivehiclefunctions/window_qml/main.cpp
+++ b/examples/ivivehiclefunctions/window_qml/main.cpp
@@ -51,12 +51,12 @@
**
****************************************************************************/
-#include <QApplication>
+#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
- QApplication app(argc, argv);
+ QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/ivivehiclefunctions/window_qml/window_qml.pro b/examples/ivivehiclefunctions/window_qml/window_qml.pro
index 98368a3..19ec158 100644
--- a/examples/ivivehiclefunctions/window_qml/window_qml.pro
+++ b/examples/ivivehiclefunctions/window_qml/window_qml.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick widgets
+QT += qml quick
SOURCES += main.cpp
diff --git a/mkspecs/features/ivigenerator.prf b/mkspecs/features/ivigenerator.prf
index 90f04c5..ff01a28 100644
--- a/mkspecs/features/ivigenerator.prf
+++ b/mkspecs/features/ivigenerator.prf
@@ -79,23 +79,38 @@ IVI_GENERATOR_OPTIONS = --format=$$QFACE_FORMAT --force
for (ANNOTATION, QFACE_ANNOTATIONS) {
file = $$absolute_path($$ANNOTATION, $$_PRO_FILE_PWD_)
- IVI_GENERATOR_OPTIONS += -A $$system_path($$file)
+ IVI_GENERATOR_OPTIONS += -A $$system_quote($$system_path($$file))
qface_sources.depends += $$file
OTHER_FILES += $$file
}
+for (IMPORT, QFACE_IMPORT_PATH) {
+ dir = $$absolute_path($$IMPORT, $$_PRO_FILE_PWD_)
+
+ IVI_GENERATOR_OPTIONS += -I $$system_quote($$system_path($$dir))
+}
+
# Windows doesn't offer any other way to sleep for a time inside non-interactive scripts
-equals(QMAKE_HOST.os, Windows): SLEEP = ping -n 2 127.0.0.1 >nul
-else: SLEEP = sleep 1
+equals(QMAKE_HOST.os, Windows): {
+ SLEEP = ping -n 2 127.0.0.1 >nul
+ TOUCH = type nul >
+} else {
+ SLEEP = sleep 1
+ TOUCH = touch
+}
-qface_sources.target = $$relative_path($$PRI, $$OUT_PWD)
-qface_sources.commands = $$SLEEP && $$ENV $$system_path($$IVI_GENERATOR) $$IVI_GENERATOR_OPTIONS $$system_path($$QFACE_ABS_PWD/$${QFACE_FILE}) $$system_path($$QFACE_OUTPUT_DIR)
+qface_sources.target = $$relative_path(.stamp-ivigenerator, $$OUT_PWD)
+qface_sources.commands += $(DEL_FILE) $$system_quote($$system_path($$OUT_PWD/.stamp-ivigenerator)) &&
+qface_sources.commands += $$SLEEP && $$ENV $$system_path($$IVI_GENERATOR) $$IVI_GENERATOR_OPTIONS $$system_quote($$system_path($$QFACE_ABS_PWD/$${QFACE_FILE})) $$system_quote($$system_path($$QFACE_OUTPUT_DIR)) &&
+qface_sources.commands += $$TOUCH $$system_quote($$system_path($$OUT_PWD/.stamp-ivigenerator))
qface_sources.depends = $$IVI_GENERATOR_PATH/generate.py
qface_sources.depends += $$QFACE_ABS_PWD/$${QFACE_FILE}
-qface_sources.depends += $$files($$IVI_GENERATOR_PATH/common/*)
+qface_sources.depends += $$files($$IVI_GENERATOR_PATH/templates/common/*)
+
+QMAKE_CLEAN += $$relative_path(.stamp-ivigenerator, $$OUT_PWD)
# Add all templates of the generator format as dependency
-QFACE_TEMPLATE_PWD = $$IVI_GENERATOR_PATH/templates_$${QFACE_FORMAT}
+QFACE_TEMPLATE_PWD = $$IVI_GENERATOR_PATH/templates/$${QFACE_FORMAT}
exists($$QFACE_TEMPLATE_PWD) {
qface_sources.depends += $$files($${QFACE_TEMPLATE_PWD}/*)
} else: exists($${QFACE_FORMAT}) {
@@ -114,14 +129,14 @@ exists($$QFACE_YAML) {
QFACE_HEADERS_OUTPUT_TARGET = $${QFACE_HEADERS_OUTPUT_DIR}/$$lower($${QFACE_MODULE_NAME})module.h
qface_headers.target = $$relative_path($$QFACE_HEADERS_OUTPUT_TARGET, $$OUT_PWD)
qface_headers.commands = $${QMAKE_COPY_FILE} $${QFACE_OUTPUT_DIR}/*.h $${QFACE_HEADERS_OUTPUT_DIR}
- qface_headers.depends = $$relative_path($$PRI, $$OUT_PWD) $$IVI_GENERATOR_PATH/generate.py
+ qface_headers.depends = $$relative_path(.stamp-ivigenerator, $$OUT_PWD) $$IVI_GENERATOR_PATH/generate.py
}
# Reevaluate the Makefile after the generation has finished
Makefile.target = Makefile
# The relative_path is needed here as qmake will use a relative_path for the output files
# when using a QMAKE_EXTRA_COMPILER
-Makefile.depends = $$relative_path($$PRI, $$OUT_PWD)
+Makefile.depends = $$relative_path(.stamp-ivigenerator, $$OUT_PWD)
# Make the qmake_all target work for usage inside QtCreator
# Because of the Makefile target the generator is called before the actual Makefile
@@ -170,7 +185,7 @@ QMAKE_EXTRA_TARGETS += Makefile qface_sources
# Afterwards the sub makefiles are read (Makefile.debug/release), which have been
# regenerated before starting NMAKE on them.
win32-msvc* {
- qmake.depends = $$relative_path($$PRI, $$OUT_PWD)
+ qmake.depends = $$relative_path(.stamp-ivigenerator, $$OUT_PWD)
debug.depends = qmake
debug-make_first.depends = qmake
diff --git a/src/geniviextras/qdltregistration.cpp b/src/geniviextras/qdltregistration.cpp
index 14b2130..bef94d1 100644
--- a/src/geniviextras/qdltregistration.cpp
+++ b/src/geniviextras/qdltregistration.cpp
@@ -55,6 +55,9 @@ QT_BEGIN_NAMESPACE
void qtGeniviLogLevelChangedHandler(char context_id[], uint8_t log_level, uint8_t trace_status)
{
+ if (!globalDltRegistration())
+ return;
+
auto d = globalDltRegistration()->d_ptr;
d->m_mutex.lock();
const QLoggingCategory *category = d->dltLogLevelChanged(context_id, log_level, trace_status);
diff --git a/src/helper/remoteobjects/qivipagingmodel.rep b/src/helper/remoteobjects/qivipagingmodel.rep
new file mode 100644
index 0000000..938ce34
--- /dev/null
+++ b/src/helper/remoteobjects/qivipagingmodel.rep
@@ -0,0 +1,14 @@
+#include <QtIviCore/QtIviCoreModule>
+#include <QUuid>
+
+class QIviPagingModel
+{
+ SLOT(void registerInstance(const QUuid &identifier))
+ SLOT(void unregisterInstance(const QUuid &identifier))
+ SLOT(void fetchData(const QUuid &identifier, int start, int count))
+
+ SIGNAL(supportedCapabilitiesChanged(const QUuid &identifier, QtIviCoreModule::ModelCapabilities capabilities))
+ SIGNAL(countChanged(const QUuid &identifier, int newLength))
+ SIGNAL(dataFetched(const QUuid &identifier, const QList<QVariant> &data, int start, bool moreAvailable))
+ SIGNAL(dataChanged(const QUuid &identifier, const QList<QVariant> &data, int start, int count))
+};
diff --git a/src/helper/remoteobjects/qivipagingmodelqtroadapter.cpp b/src/helper/remoteobjects/qivipagingmodelqtroadapter.cpp
new file mode 100644
index 0000000..6ddc865
--- /dev/null
+++ b/src/helper/remoteobjects/qivipagingmodelqtroadapter.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** 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 "qivipagingmodelqtroadapter.h"
+
+QIviPagingModelQtRoAdapter::QIviPagingModelQtRoAdapter(const QString &remoteObjectsLookupName, QIviPagingModelInterface *parent)
+ : QIviPagingModelSource(parent)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
+ , m_backend(parent)
+{
+ connect(m_backend, &QIviPagingModelInterface::supportedCapabilitiesChanged, this, &QIviPagingModelQtRoAdapter::supportedCapabilitiesChanged);
+ connect(m_backend, &QIviPagingModelInterface::countChanged, this, &QIviPagingModelQtRoAdapter::countChanged);
+ connect(m_backend, &QIviPagingModelInterface::dataFetched, this, &QIviPagingModelQtRoAdapter::dataFetched);
+ connect(m_backend, &QIviPagingModelInterface::dataChanged, this, &QIviPagingModelQtRoAdapter::dataChanged);
+}
+
+QString QIviPagingModelQtRoAdapter::remoteObjectsLookupName() const
+{
+ return m_remoteObjectsLookupName;
+}
+
+void QIviPagingModelQtRoAdapter::registerInstance(const QUuid &identifier)
+{
+ m_backend->registerInstance(identifier);
+}
+
+void QIviPagingModelQtRoAdapter::unregisterInstance(const QUuid &identifier)
+{
+ m_backend->unregisterInstance(identifier);
+}
+
+void QIviPagingModelQtRoAdapter::fetchData(const QUuid &identifier, int start, int count)
+{
+ m_backend->fetchData(identifier, start, count);
+}
diff --git a/src/helper/remoteobjects/qivipagingmodelqtroadapter.h b/src/helper/remoteobjects/qivipagingmodelqtroadapter.h
new file mode 100644
index 0000000..9bd9a75
--- /dev/null
+++ b/src/helper/remoteobjects/qivipagingmodelqtroadapter.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** 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 QIVIPAGINGMODELQTROADAPTER_H
+#define QIVIPAGINGMODELQTROADAPTER_H
+
+#include <QtIviCore/QIviPagingModelInterface>
+#include <rep_qivipagingmodel_source.h>
+
+QT_BEGIN_NAMESPACE
+
+template <class ObjectType>
+struct QIviPagingModelAddressWrapper: public QIviPagingModelSourceAPI<ObjectType> {
+ QIviPagingModelAddressWrapper(ObjectType *object)
+ : QIviPagingModelSourceAPI<ObjectType>(object, object->remoteObjectsLookupName())
+ {}
+};
+
+class QIviPagingModelQtRoAdapter : public QIviPagingModelSource
+{
+ Q_OBJECT
+
+public:
+ explicit QIviPagingModelQtRoAdapter(const QString &remoteObjectsLookupName, QIviPagingModelInterface *parent = nullptr);
+
+ QString remoteObjectsLookupName() const;
+
+public Q_SLOTS:
+ void registerInstance(const QUuid &identifier) override;
+ void unregisterInstance(const QUuid &identifier) override;
+ void fetchData(const QUuid &identifier, int start, int count) override;
+
+private:
+ QString m_remoteObjectsLookupName;
+ QIviPagingModelInterface *m_backend;
+};
+
+QT_END_NAMESPACE
+
+#endif // QIVIPAGINGMODELQTROADAPTER_H
diff --git a/src/helper/remoteobjects/remoteobjects.pro b/src/helper/remoteobjects/remoteobjects.pro
index 22317f1..b56c388 100644
--- a/src/helper/remoteobjects/remoteobjects.pro
+++ b/src/helper/remoteobjects/remoteobjects.pro
@@ -8,13 +8,28 @@ CMAKE_MODULE_TESTS = '-'
CONFIG -= create_cmake
SOURCES += \
+ qivipagingmodelqtroadapter.cpp \
qiviremoteobjectreplicahelper.cpp \
qiviremoteobjectpendingresult.cpp
HEADERS += \
+ qivipagingmodelqtroadapter.h \
qiviremoteobjectreplicahelper.h \
qiviremoteobjectsourcehelper.h \
qiviremoteobjectpendingresult.h
+REPC_SOURCE += \
+ qivipagingmodel.rep
+
+REPC_REPLICA += \
+ qivipagingmodel.rep
+
load(qt_module)
+
+# This is a ugly hack to make sure the generated rep_* headers are installed as well.
+# Because the headers are marked as injected headers, syncqt correctly adds them to the headers.pri.
+# qmake reads the pri in qt_module.prf and creates the INSTALL targets, but these are only created
+# if the files also exist at this point.
+targ_headers.CONFIG = no_check_exist
+
CONFIG -= hide_symbols
diff --git a/src/imports/core/plugins.qmltypes b/src/imports/core/plugins.qmltypes
index 599e59c..ab20f80 100644
--- a/src/imports/core/plugins.qmltypes
+++ b/src/imports/core/plugins.qmltypes
@@ -9,6 +9,280 @@ import QtQuick.tooling 1.2
Module {
dependencies: ["QtQuick 2.0"]
Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Enum {
+ name: "CheckIndexOption"
+ values: {
+ "NoOption": 0,
+ "IndexIsValid": 1,
+ "DoNotUseParent": 2,
+ "ParentIsInvalid": 4
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
+ Component {
name: "QIviAbstractFeature"
prototype: "QObject"
exports: ["QtIvi/AbstractFeature 1.0"]
diff --git a/src/imports/media/plugins.qmltypes b/src/imports/media/plugins.qmltypes
index 5596872..eb2fc6c 100644
--- a/src/imports/media/plugins.qmltypes
+++ b/src/imports/media/plugins.qmltypes
@@ -9,6 +9,280 @@ import QtQuick.tooling 1.2
Module {
dependencies: ["QtQuick 2.0"]
Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Enum {
+ name: "CheckIndexOption"
+ values: {
+ "NoOption": 0,
+ "IndexIsValid": 1,
+ "DoNotUseParent": 2,
+ "ParentIsInvalid": 4
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
+ Component {
name: "QIviAbstractFeature"
prototype: "QObject"
Enum {
diff --git a/src/ivicore/doc/qtivi-project.qdocconf b/src/ivicore/doc/qtivi-project.qdocconf
index c25fc04..0881745 100644
--- a/src/ivicore/doc/qtivi-project.qdocconf
+++ b/src/ivicore/doc/qtivi-project.qdocconf
@@ -63,10 +63,12 @@ qhp.QtIvi.subprojects.examples.sortPages = true
tagfile = qtivi.tags
-depends += qtcore qtwidgets qtdoc qtquick qtqml qtautomotivesuite qtremoteobjects
+depends += qtcore qtdbus qtwidgets qtdoc qtquick qtqml qtautomotivesuite qtremoteobjects
navigation.homepage = "Qt Automotive Suite"
navigation.landingpage = "Qt IVI"
navigation.cppclassespage = "Qt IVI C++ Classes"
navigation.qmltypespage = "Qt IVI QML Types"
buildversion = "Qt IVI $QT_VERSION"
+
+macro.fileLink = "\\l {https://code.qt.io/cgit/qt/qtivi.git/tree/\1?h=$QT_VER}{\2}"
diff --git a/src/ivicore/doc/src/concepts.qdoc b/src/ivicore/doc/src/concepts.qdoc
index d34905a..cb23917 100644
--- a/src/ivicore/doc/src/concepts.qdoc
+++ b/src/ivicore/doc/src/concepts.qdoc
@@ -33,7 +33,7 @@ All Qt IVI feature APIs depend on the following set of key concepts:
\list
\li \l {Dynamic Backend System}
- \li \l {Qt IVI Autogenerator}
+ \li \l {Qt IVI Generator}
\li \l {Models}
\li \l {Qt IVI Query Language}
\li \l {Qt IVI Simulation System}
diff --git a/src/ivicore/doc/src/configuration.qdoc b/src/ivicore/doc/src/configuration.qdoc
index d61cdf3..4e5bd2d 100644
--- a/src/ivicore/doc/src/configuration.qdoc
+++ b/src/ivicore/doc/src/configuration.qdoc
@@ -38,11 +38,13 @@ The following environment variables are supported for runtime configurations:
\li Environment Variable
\li Description
\row
- \li SIMULATOR_HOSTNAME
- \li Specifies where the QtSimulator server is running, such as, the autogenerated control
- panel binaries.
- \note This is only available when the \l {feature-qtsimulator} {QtSimulator Support} is
- enabled.
+ \li QTIVI_SIMULATION_OVERRIDE
+ \li Overrides the simulation file used by a specific simulation engine.
+ See \l {Runtime Override}{QIviSimulationEngine} for more information.
+ \row
+ \li QTIVI_SIMULATION_DATA_OVERRIDE
+ \li Overrides the simulation data used by a specific simulation engine.
+ See \l {Runtime Override}{QIviSimulationEngine} for more information.
\endtable
For more runtime configuration options, see \l{QtIvi Backends}{backend plugins}.
diff --git a/src/ivicore/doc/src/examples-qface-ivi-climate.qdoc b/src/ivicore/doc/src/examples-qface-ivi-climate.qdoc
index 214e172..b42236c 100644
--- a/src/ivicore/doc/src/examples-qface-ivi-climate.qdoc
+++ b/src/ivicore/doc/src/examples-qface-ivi-climate.qdoc
@@ -118,8 +118,8 @@ of each individual item. The second definition is similar, but using the \c flag
\section2 Comments and Annotations
-Compared to the minimal IDL we saw in the previous section,the full
-\l {ivicore/qface-ivi-climate/example-ivi-climate.qface} {IDL file} contains a lot of comments
+Compared to the minimal IDL we saw in the previous section, the full
+\fileLink {examples/ivicore/qface-ivi-climate/example-ivi-climate.qface}{IDL file} contains a lot of comments
and annotations.
Comments starting with \c /** define documentation statements and can be converted into
diff --git a/src/ivicore/doc/src/examples-qface-tutorial.qdoc b/src/ivicore/doc/src/examples-qface-tutorial.qdoc
index 4fe5726..394fef2 100644
--- a/src/ivicore/doc/src/examples-qface-tutorial.qdoc
+++ b/src/ivicore/doc/src/examples-qface-tutorial.qdoc
@@ -115,7 +115,7 @@
\section2 Autogeneration
Now that our first version of the IDL file is ready, it's time to autogenerate API from it,
- using the \l{Qt IVI Autogenerator}{IVI Generator tool}. Similar to
+ using the \l{Qt IVI Generator}{IVI Generator tool}. Similar to
\l{https://doc.qt.io/qt-5/moc.html}{moc}, this autogeneration process is integrated into the
qmake Build System and is done on compile time.
@@ -393,6 +393,19 @@
function or using the \c QT_PLUGIN_PATH environment variable. For more information, see
\l{https://doc.qt.io/qt-5/plugins-howto.html}{How to create Qt Plugins}.
+ Now everything is in place, but because our plugin links against the frontend library, we need
+ to make sure the library can be found by the dynamic linker. This can be achieved by
+ setting the \c LD_LIBRARY_PATH environment variable to our library folder. But this results
+ in the problem, that every user would need to set this variable to be able to use our
+ application.
+ To make things easier for the user, we rather use a relative RPATH instead and annotate our
+ plugin with the information for the linker, where it might find the needed libraries, relative
+ to the plugin's location:
+
+ \quotefromfile ivicore/qface-tutorial/chapter3-simulation-backend/backend_simulator/backend_simulator.pro
+ \skipto INCLUDEPATH
+ \printuntil QMAKE_RPATHDIR
+
\section2 Export the QML Types in a QML Plugin
In the first chapter, we extended our \c main.cpp to register all types of our autogenerated
@@ -429,7 +442,7 @@
search for it and is still using the old hardcoded registration. So, we can now remove the
linking step in the \c instrument-cluster.pro file and change our main file accordingly:
- \quotefromfile ivicore/qface-tutorial/chapter1-basics/instrument-cluster/main.cpp
+ \quotefromfile ivicore/qface-tutorial/chapter3-simulation-backend/instrument-cluster/main.cpp
\skipto #include
\printuntil }
@@ -612,7 +625,7 @@
part can also be autogenerated using the IVI Generator in a similar fashion:
\quotefromfile ivicore/qface-tutorial/chapter5-ipc/simulation_server/simulation_server.pro
- \printto target.path
+ \printto RESOURCES
Because we'd like to generate a server binary, the \c TEMPLATE needs to be set to "app" instead
of "lib". Similar to the plugin, the server also needs to link against our library to give it
@@ -704,7 +717,7 @@
\quotefromfile ivicore/qface-tutorial/chapter6-own-backend/backend_dbus/instrumentclusterplugin.cpp
\skipto #include
- \printuntil eof
+ \printto
In \c interfaces() we use the IID which is defined in \c{instrumentclusterbackendinterface.h}
from our autogenerated library. In \c insterfaceInstance() we check for the correct string and
diff --git a/src/ivicore/doc/src/external-resources.qdoc b/src/ivicore/doc/src/external-resources.qdoc
index 6541ff5..6e1911f 100644
--- a/src/ivicore/doc/src/external-resources.qdoc
+++ b/src/ivicore/doc/src/external-resources.qdoc
@@ -34,3 +34,8 @@
\externalpage https://doc.qt.io/qt-5/qabstractlistmodel.html#subclassing
\title QAbstractListModel - Subclassing
*/
+
+/*!
+ \externalpage https://qface.readthedocs.io/en/latest/extending.html#rule-base-generation
+ \title QFace - Rule Base Generation
+*/
diff --git a/src/ivicore/doc/src/ivigenerator/generator-usage.qdoc b/src/ivicore/doc/src/ivigenerator/generator-usage.qdoc
index ba45323..7d870d9 100644
--- a/src/ivicore/doc/src/ivigenerator/generator-usage.qdoc
+++ b/src/ivicore/doc/src/ivigenerator/generator-usage.qdoc
@@ -77,6 +77,13 @@
overrides the previously set value. This option can be used multiple times. For
more information, see \l{merge-annotations}{Merge Annotations}.
\row
+ \target import-option
+ \li -I, --import <import-path>
+ \li Adds the given path to the list of import paths. All directories in this list are
+ scanned recursively for QFace files. The QFace files found are then used to resolve
+ the information required when importing a module; this is similar to how C++ include
+ paths work.
+ \row
\li source
\li Path or paths to the IDL source files. If there are multiple entries, each one is
handled. If a directory path is provided, it's scanned for IDL files.
@@ -146,23 +153,25 @@
This YAML file must have the following structure:
\code
- generate_rules:
- module_rules:
- - dest_file: "{{module.module_name|lower}}plugin.h"
- template_file: "plugin.h.tpl"
- interface_rules:
- - dest_file: '{{interface|lower}}backend.h'
- template_file: 'backend.h.tpl'
- struct_rules:
+ frontend:
+ module:
+ documents:
+ - "{{module.module_name|lower}}plugin.h": "plugin.h.tpl"
+ interface:
+ documents:
+ - '{{interface|lower}}backend.h': 'backend.h.tpl'
\endcode
For every entity, there's a list of templates that must be called, when traversing this entity
- in the domain model tree. Here, \e{dest_file} is a name of the file that needs to be created,
- as specified in the \l {Jinja template syntax}{Jinja template language} format. The value of
- the object property used in the template's name is processed and substituted into the template,
- thus forming the final name of the file to create. \e{dest_file} is the name of the template to
- use. For the IVI generator, you must specify rules for three kinds of entities: modules,
- interfaces and structures.
+ in the domain model tree. Here, the YAML file defines a list of documents, which need to be
+ generated for all modules and a list for all interfaces. Every list entry consists of two
+ parts; the first part is the name of the file that needs to be created, as specified in the \l
+ {Jinja template syntax}{Jinja template language} format. The value of the object property used
+ in the template's name is processed and substituted into the template, thus forming the final
+ name of the file to create. The second part is the name of the template to use. For the IVI
+ generator, you must specify rules for three kinds of entities: modules, interfaces and
+ structures. See the \l{QFace - Rule Base Generation}{QFace Rule Base Generation Documentation}
+ for more information.
\section2 Annotations YAML
diff --git a/src/ivicore/doc/src/ivigenerator/ivigenerator.qdoc b/src/ivicore/doc/src/ivigenerator/ivigenerator.qdoc
index 2d62ed5..485ea6f 100644
--- a/src/ivicore/doc/src/ivigenerator/ivigenerator.qdoc
+++ b/src/ivicore/doc/src/ivigenerator/ivigenerator.qdoc
@@ -50,13 +50,11 @@ QFace library, that provides a generic autogeneration framework.
Currently, Qt IVI generator has the following limitations:
\list
- \li It's not possible to import other QFace modules using the \c import command.
\li There's no support for external C++ types, outside of the IDL, such as reusing a
QGeoCoordinate inside a QFace IDL.
+ \li Defined Interfaces can't be used as types in properties or function arguments.
\li The \c map<> type is not supported.
\li Any default values provided directly in the QFace file are currently ignored.
- \li The \c ivigenerator uses it's own YAML template, that's incorporated with QFace's YAML to
- define the generation rules.
\endlist
*/
diff --git a/src/ivicore/doc/src/ivigenerator/qmake-integration.qdoc b/src/ivicore/doc/src/ivigenerator/qmake-integration.qdoc
index 7b79d1e..d56459f 100644
--- a/src/ivicore/doc/src/ivigenerator/qmake-integration.qdoc
+++ b/src/ivicore/doc/src/ivigenerator/qmake-integration.qdoc
@@ -71,6 +71,10 @@ The following qmake variables are available:
\li QFACE_ANNOTATIONS
\li A list of additional annotation files in YAML format. For more information, see the
\l{annotations-option}{Annotations Option}.
+ \row
+ \li QFACE_IMPORT_PATH
+ \li A list of import paths, which are considered when an IDL file uses an import statement.
+ For more information, see the \l{import-option}{Import Option}.
\endtable
For more details on the generator's command line arguments, see \l {Use the Generator}.
diff --git a/src/ivicore/doc/src/qtivi.qdoc b/src/ivicore/doc/src/qtivi.qdoc
index 5d3aca6..697594e 100644
--- a/src/ivicore/doc/src/qtivi.qdoc
+++ b/src/ivicore/doc/src/qtivi.qdoc
@@ -32,7 +32,7 @@
The Qt In-Vehicle Infotainment (IVI) module provides both, the tools and the core APIs, for you
to implement Middleware APIs, Middleware Backends, and Middlware Services. The
- \l{Qt IVI Autogenerator} provides a flexible way to define new APIs via an Interface Definition
+ \l{Qt IVI Generator} provides a flexible way to define new APIs via an Interface Definition
Language (IDL) and generate classes for use, from C++ and QML.
Qt IVI is built around a pattern that separates the API exposed to the application developer,
@@ -64,6 +64,7 @@
\li \l{Configuration}
\li \l{Concepts and Architecture}
\li \l{Get Started with the Qt IVI Generator}
+ \li \l{Qt IVI Generator Tutorial}
\li \l{Extending Qt IVI}
\endlist
diff --git a/src/ivicore/qiviabstractfeature.cpp b/src/ivicore/qiviabstractfeature.cpp
index aaa59d0..ce5cd05 100644
--- a/src/ivicore/qiviabstractfeature.cpp
+++ b/src/ivicore/qiviabstractfeature.cpp
@@ -133,25 +133,21 @@ void QIviAbstractFeaturePrivate::onInitializationDone()
\inmodule QtIviCore
\brief The QIviAbstractFeature is the base class for all QtIvi Features.
- QIviAbstractFeature is the base class for the front-facing API towards the developer.
- The QIviAbstractFeature provides you with a way to automatically connect to a backend
- implementing the interface needed. To discover a backend, we start it using the
- startAutoDiscovery() function.
+ QIviAbstractFeature is the base class for the front-facing API towards the developer. Subclass
+ QIviAbstractFeature to create an API for your feature.
- Once the auto discovery is complete, you can check whether a backend was found using the
- isValid() function.
+ QIviAbstractFeature provides you with auto discovery: a way to automatically connect to a
+ backend that implements the required interface. To discover a backend, use the
+ startAutoDiscovery() function. Once auto discovery is complete, use the isValid() function to
+ check whether a suitable backend was found.
- The auto discovery gives you an easy way to automatically connect to the right backend
- implementation. If you don't want to use the auto discovery, it's also possible to use
- QIviServiceManager to retrieve all backends. Then, manually search for the right backend
- and call setServiceObject() to connect it to the QIviAbstractFeature.
-
- The type of backend to load can be controlled by setting the \c discvoeryMode to
+ The type of backend to load can be controlled by setting the \c discoveryMode to
\c AutoDiscovery. This mode is enabled by default, which indicates that a production backend
is always preferred over a simulation backend.
- QIviAbstractFeature is an abstract base class that you need to subclass to create an API
- for your feature.
+ Alternatively, it's also possible to use QIviServiceManager to retrieve all backends. Then,
+ manually search for the right backend and call setServiceObject() to connect it to the
+ QIviAbstractFeature.
\section1 Write a Subclass
@@ -165,7 +161,7 @@ void QIviAbstractFeaturePrivate::onInitializationDone()
\endlist
Once a QIviServiceObject has been set, either via startAutoDiscovery() or setServiceObject(),
- the acceptServiceObject() function is then called to make sure that the implemented feature
+ call the acceptServiceObject() function to make sure that the feature you've implemented
can work with the QIviServiceObject and, in turn, the QIviServiceObject provides the required
interface.
diff --git a/src/ivicore/qiviabstractfeaturelistmodel.cpp b/src/ivicore/qiviabstractfeaturelistmodel.cpp
index dbd8e3e..d23b77a 100644
--- a/src/ivicore/qiviabstractfeaturelistmodel.cpp
+++ b/src/ivicore/qiviabstractfeaturelistmodel.cpp
@@ -138,7 +138,7 @@ QIviFeatureInterface *QIviAbstractFeatureListModelPrivate::backend() const
\list
\li For more details on how to integrate with the \l{Dynamic Backend System}, see
- \l{QIviAbstractFeature::Write a Subclass}{QIviAbstractFeature}.
+ \l{Write a Subclass}{QIviAbstractFeature}.
\li For more details on what you need to do to provide the model's required
functionality, see \l{QAbstractListModel - Subclassing}.
\li For a class that implements all the necessary QIviAbstractFeatureListModel functions
diff --git a/src/ivicore/qivipagingmodel.cpp b/src/ivicore/qivipagingmodel.cpp
index 5986138..0ddf289 100644
--- a/src/ivicore/qivipagingmodel.cpp
+++ b/src/ivicore/qivipagingmodel.cpp
@@ -151,7 +151,7 @@ void QIviPagingModelPrivate::onDataFetched(const QUuid &identifier, const QList<
void QIviPagingModelPrivate::onCountChanged(const QUuid &identifier, int new_length)
{
- if (!identifier.isNull() && (identifier != m_identifier || m_loadingType != QIviPagingModel::DataChanged || m_itemList.count() == new_length))
+ if (m_loadingType != QIviPagingModel::DataChanged || (!identifier.isNull() && identifier != m_identifier) || m_itemList.count() == new_length)
return;
Q_Q(QIviPagingModel);
diff --git a/src/ivicore/qivipagingmodelinterface.cpp b/src/ivicore/qivipagingmodelinterface.cpp
index 2d528d6..c8fed22 100644
--- a/src/ivicore/qivipagingmodelinterface.cpp
+++ b/src/ivicore/qivipagingmodelinterface.cpp
@@ -123,10 +123,10 @@ QIviPagingModelInterface::QIviPagingModelInterface(QObjectPrivate &dd, QObject *
*/
/*!
- \fn void QIviPagingModelInterface::countChanged(const QUuid &identifier, int newLength)
+ \fn void QIviPagingModelInterface::countChanged(const QUuid &identifier, int count)
This signal is emitted when the current number of items in the QIviPagingModel instance identified by \a identifier changed.
- The new number of items is returned as \a newLength.
+ The new number of items is returned as \a count.
This signal is expected to be emitted after the model instance has requested new data for the first time by calling fetchData() and
should be emitted before the data is returned by emitting the dataFetched() signal.
diff --git a/src/ivicore/qivipagingmodelinterface.h b/src/ivicore/qivipagingmodelinterface.h
index 0f3375a..4a6973e 100644
--- a/src/ivicore/qivipagingmodelinterface.h
+++ b/src/ivicore/qivipagingmodelinterface.h
@@ -69,7 +69,7 @@ protected:
Q_SIGNALS:
void supportedCapabilitiesChanged(const QUuid &identifier, QtIviCoreModule::ModelCapabilities capabilities);
- void countChanged(const QUuid &identifier, int newLength);
+ void countChanged(const QUuid &identifier = QUuid(), int count = -1);
void dataFetched(const QUuid &identifier, const QList<QVariant> &data, int start, bool moreAvailable);
void dataChanged(const QUuid &identifier, const QList<QVariant> &data, int start, int count);
};
diff --git a/src/ivicore/qivipendingreply.cpp b/src/ivicore/qivipendingreply.cpp
index 8fe9391..2caa926 100644
--- a/src/ivicore/qivipendingreply.cpp
+++ b/src/ivicore/qivipendingreply.cpp
@@ -59,18 +59,31 @@ QT_BEGIN_NAMESPACE
#define QTIVI_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, AliasingType) \
QTIVI_ADD_STATIC_METATYPE2(MetaTypeName, MetaTypeId, AliasingType, nullptr)
-struct QIviPendingReplyRegistrator {
- QIviPendingReplyRegistrator() {
- qRegisterMetaType<QIviPendingReplyBase>("QIviPendingReplyBase");
- QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QTIVI_ADD_STATIC_METATYPE)
- QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QTIVI_ADD_STATIC_METATYPE)
- QT_FOR_EACH_STATIC_CORE_POINTER(QTIVI_ADD_STATIC_METATYPE)
- QT_FOR_EACH_STATIC_CORE_TEMPLATE(QTIVI_ADD_STATIC_METATYPE)
- QT_FOR_EACH_STATIC_CORE_CLASS(QTIVI_ADD_STATIC_METATYPE)
- QT_FOR_EACH_STATIC_ALIAS_TYPE(QTIVI_ADD_STATIC_METATYPE2)
- }
-};
-static QIviPendingReplyRegistrator _registrator;
+
+/*!
+ \relates QIviPendingReply
+
+ Registers QIviPendingReplys of all Qt basic types to the meta type system.
+
+ Usually this function called automatically when creating a QCoreApplication or a QIviPendingReply
+ and doesn't need to be called manually.
+*/
+void qiviRegisterPendingReplyBasicTypes() {
+ static bool once = false;
+ if (once)
+ return;
+
+ qRegisterMetaType<QIviPendingReplyBase>("QIviPendingReplyBase");
+ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QTIVI_ADD_STATIC_METATYPE)
+ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QTIVI_ADD_STATIC_METATYPE)
+ QT_FOR_EACH_STATIC_CORE_POINTER(QTIVI_ADD_STATIC_METATYPE)
+ QT_FOR_EACH_STATIC_CORE_TEMPLATE(QTIVI_ADD_STATIC_METATYPE)
+ QT_FOR_EACH_STATIC_CORE_CLASS(QTIVI_ADD_STATIC_METATYPE)
+ QT_FOR_EACH_STATIC_ALIAS_TYPE(QTIVI_ADD_STATIC_METATYPE2)
+ once = true;
+}
+
+Q_COREAPP_STARTUP_FUNCTION(qiviRegisterPendingReplyBasicTypes)
// TODO make it reentrant
@@ -561,6 +574,7 @@ void QIviPendingReplyWatcher::then(const QJSValue &success, const QJSValue &fail
QIviPendingReplyBase::QIviPendingReplyBase(int userType)
: m_watcher(new QIviPendingReplyWatcher(userType))
{
+ qiviRegisterPendingReplyBasicTypes();
}
QIviPendingReplyBase::QIviPendingReplyBase(const QIviPendingReplyBase &other)
@@ -828,9 +842,9 @@ void QIviPendingReplyBase::setSuccessNoCheck(const QVariant &value)
*/
/*!
- \fn template <class T> QIviPendingReply<T>::setSuccess(const T &value)
+ \fn template <class T> QIviPendingReply<T>::setSuccess(const T &val)
- Sets the result of the reply to \a value and marks the reply as succeeded.
+ Sets the result of the reply to \a val and marks the reply as succeeded.
\note a result can only be set once and cannot be changed again later.
diff --git a/src/ivicore/qivipendingreply.h b/src/ivicore/qivipendingreply.h
index e0b5aeb..36368b8 100644
--- a/src/ivicore/qivipendingreply.h
+++ b/src/ivicore/qivipendingreply.h
@@ -55,6 +55,8 @@ QT_BEGIN_NAMESPACE
class QIviPendingReplyWatcherPrivate;
+Q_QTIVICORE_EXPORT void qiviRegisterPendingReplyBasicTypes();
+
class Q_QTIVICORE_EXPORT QIviPendingReplyWatcher : public QObject
{
Q_OBJECT
diff --git a/src/ivicore/qiviqmlconversion_helper.cpp b/src/ivicore/qiviqmlconversion_helper.cpp
index bad773a..2b13b7c 100644
--- a/src/ivicore/qiviqmlconversion_helper.cpp
+++ b/src/ivicore/qiviqmlconversion_helper.cpp
@@ -114,11 +114,15 @@ QVariant qtivi_convertFromJSON(const QVariant &value)
if (type == QStringLiteral("enum")) {
QString enumValue = value.toString();
const int lastIndex = enumValue.lastIndexOf(QStringLiteral("::"));
- const QString className = enumValue.left(lastIndex - 1 );
+ const QString className = enumValue.left(lastIndex) + QStringLiteral("*");
enumValue = enumValue.right(enumValue.count() - lastIndex - 2);
const QMetaObject *mo = QMetaType::metaObjectForType(QMetaType::type(className.toLatin1()));
- if (!mo)
+ if (Q_UNLIKELY(!mo)) {
+ qWarning() << "Couldn't retrieve MetaObject for enum parsing:" << map;
+ qWarning("Please make sure %s is registered in Qt's meta-type system: qRegisterMetaType<%s>()",
+ qPrintable(className), qPrintable(className));
return QVariant();
+ }
for (int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) {
QMetaEnum me = mo->enumerator(i);
@@ -132,14 +136,34 @@ QVariant qtivi_convertFromJSON(const QVariant &value)
} else {
int typeId = QMetaType::type(type.toLatin1());
const QMetaObject *mo = QMetaType::metaObjectForType(typeId);
- if (!mo)
+ if (Q_UNLIKELY(!mo)) {
+ qWarning() << "Couldn't retrieve MetaObject for struct parsing:" << map;
+ qWarning("Please make sure %s is registered in Qt's meta-type system: qRegisterMetaType<%s>()",
+ qPrintable(type), qPrintable(type));
return QVariant();
+ }
- QVariantList values = value.toList();
- for (auto i = values.begin(); i != values.end(); ++i)
- *i = qtivi_convertFromJSON(*i);
+ void *gadget = QMetaType::create(typeId);
+ if (!Q_UNLIKELY(gadget)) {
+ qWarning("Couldn't create a new instance of %s", QMetaType::typeName(typeId));
+ return QVariant();
+ }
+
+ /* Left here for debugging
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i)
+ qDebug() << mo->method(i).methodSignature();
+ */
+
+ int moIdx = mo->indexOfMethod("fromJSON(QVariant)");
+ if (Q_UNLIKELY(moIdx == -1)) {
+ qWarning("Couldn't find method: %s::fromJSON(QVariant)\n"
+ "If your are using code created by the ivigenerator, please regenerate"
+ "your frontend code. See AUTOSUITE-1374 for why this is needed",
+ QMetaType::typeName(typeId));
+ return QVariant();
+ }
- void *gadget = mo->newInstance(Q_ARG(QVariant, QVariant(values)));
+ mo->method(moIdx).invokeOnGadget(gadget, Q_ARG(QVariant, QVariant(value)));
return QVariant(typeId, gadget);
}
}
diff --git a/src/ivicore/qiviserviceinterface.cpp b/src/ivicore/qiviserviceinterface.cpp
index 06d1885..8fe00a7 100644
--- a/src/ivicore/qiviserviceinterface.cpp
+++ b/src/ivicore/qiviserviceinterface.cpp
@@ -85,7 +85,7 @@ QIviServiceInterface::~QIviServiceInterface()
/*!
\fn QObject* QIviServiceInterface::interfaceInstance(const QString& interfaceName) const
- Returns an object implementing the service interface requested through \a interface.
+ Returns an object implementing the service interface requested through \a interfaceName.
*/
QT_END_NAMESPACE
diff --git a/src/ivicore/qiviservicemanager.cpp b/src/ivicore/qiviservicemanager.cpp
index 606c236..df37c4b 100644
--- a/src/ivicore/qiviservicemanager.cpp
+++ b/src/ivicore/qiviservicemanager.cpp
@@ -97,7 +97,10 @@ namespace qtivi_helper {
using namespace qtivi_helper;
-QIviServiceManagerPrivate::QIviServiceManagerPrivate(QIviServiceManager *parent) : QObject(parent), q_ptr(parent)
+QIviServiceManagerPrivate::QIviServiceManagerPrivate(QIviServiceManager *parent)
+ : QObject(parent)
+ , m_staticLoaded(false)
+ , q_ptr(parent)
{
}
@@ -161,16 +164,29 @@ QList<QIviServiceObject *> QIviServiceManagerPrivate::findServiceByInterface(con
void QIviServiceManagerPrivate::searchPlugins()
{
bool found = false;
+
const auto pluginDirs = QCoreApplication::libraryPaths();
for (const QString &pluginDir : pluginDirs) {
+ // Already loaded, skip it...
+ if (m_loadedPaths.contains(pluginDir))
+ continue;
+ m_loadedPaths << pluginDir;
+#ifdef Q_OS_ANDROID
+ QString path = pluginDir;
+#else
QString path = pluginDir + QDir::separator() + QLatin1String(QIVI_PLUGIN_DIRECTORY);
+#endif
QDir dir(path);
//Check whether the directory exists
if (!dir.exists())
continue;
- const QStringList plugins = QDir(path).entryList(QDir::Files);
+ const QStringList plugins = QDir(path).entryList(
+#ifdef Q_OS_ANDROID
+ QStringList(QLatin1String("libplugins_%1_*.so").arg(QLatin1String(QIVI_PLUGIN_DIRECTORY))),
+#endif
+ QDir::Files);
for (const QString &pluginFileName : plugins) {
if (!QLibrary::isLibrary(pluginFileName))
continue;
@@ -183,11 +199,16 @@ void QIviServiceManagerPrivate::searchPlugins()
found = true;
}
}
- const auto staticPlugins = QPluginLoader::staticPlugins();
- for (const QStaticPlugin &plugin : staticPlugins)
- registerStaticBackend(plugin);
- if (Q_UNLIKELY(!found))
+ // Only load the static plugins once
+ if (!m_staticLoaded) {
+ m_staticLoaded = true;
+ const auto staticPlugins = QPluginLoader::staticPlugins();
+ for (const QStaticPlugin &plugin : staticPlugins)
+ registerStaticBackend(plugin);
+ }
+
+ if (Q_UNLIKELY(!found && m_backends.count() == 0))
qWarning() << "No plugins found in search path: " << QCoreApplication::libraryPaths().join(QLatin1String(":"));
}
@@ -294,6 +315,8 @@ void QIviServiceManagerPrivate::unloadAllBackends()
q->endResetModel();
m_interfaceNames.clear();
+ m_loadedPaths.clear();
+ m_staticLoaded = false;
}
void QIviServiceManagerPrivate::addBackend(Backend *backend)
@@ -305,14 +328,22 @@ void QIviServiceManagerPrivate::addBackend(Backend *backend)
const QString newBackendFile = backend->metaData.value(fileNameLiteral).toString();
const QString newBackendFileBase = qtivi_helper::backendBaseName(newBackendFile);
const QStringList ifaceList = backend->metaData.value(interfacesLiteral).toStringList();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
const QSet<QString> newInterfaces = QSet<QString>(ifaceList.begin(), ifaceList.end());
+#else
+ const QSet<QString> newInterfaces = ifaceList.toSet();
+#endif
bool addBackend = true;
if (!newBackendFile.isEmpty()) {
for (int i = 0; i < m_backends.count(); i++) {
Backend *b = m_backends[i];
const QStringList curIfaceList = backend->metaData.value(interfacesLiteral).toStringList();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
const QSet<QString> interfaces = QSet<QString>(curIfaceList.begin(), curIfaceList.end());
+#else
+ const QSet<QString> interfaces = curIfaceList.toSet();
+#endif
if (interfaces == newInterfaces && b->name == backend->name) {
const QString fileName = b->metaData.value(fileNameLiteral).toString();
if (fileName == newBackendFile) {
@@ -535,6 +566,7 @@ QIviServiceManager *QIviServiceManager::instance()
QList<QIviServiceObject *> QIviServiceManager::findServiceByInterface(const QString &interface, SearchFlags searchFlags)
{
Q_D(QIviServiceManager);
+ d->searchPlugins();
return d->findServiceByInterface(interface, searchFlags);
}
diff --git a/src/ivicore/qiviservicemanager_p.h b/src/ivicore/qiviservicemanager_p.h
index 71c56ed..02533d0 100644
--- a/src/ivicore/qiviservicemanager_p.h
+++ b/src/ivicore/qiviservicemanager_p.h
@@ -108,6 +108,8 @@ public:
QList<Backend*> m_backends;
QSet<QString> m_interfaceNames;
+ QStringList m_loadedPaths;
+ bool m_staticLoaded;
QIviServiceManager * const q_ptr;
Q_DECLARE_PUBLIC(QIviServiceManager)
diff --git a/src/ivicore/qivisimulationglobalobject.cpp b/src/ivicore/qivisimulationglobalobject.cpp
index db312b6..48c47ea 100644
--- a/src/ivicore/qivisimulationglobalobject.cpp
+++ b/src/ivicore/qivisimulationglobalobject.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2019 Luxoft Sweden AB
** Copyright (C) 2018 Pelagicore AG
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtIvi module of the Qt Toolkit.
@@ -42,6 +43,7 @@
#include "qivisimulationglobalobject_p.h"
#include <QtDebug>
+#include <QJsonDocument>
QT_BEGIN_NAMESPACE
@@ -301,7 +303,7 @@ QVariantMap QIviSimulationGlobalObject::findData(const QVariantMap &data, const
int index = key.indexOf('.');
if (index == -1)
break;
- key = key.right(key.count() - index);
+ key = key.right(key.count() - index - 1);
}
return QVariantMap();
@@ -395,18 +397,18 @@ QString QIviSimulationGlobalObject::constraint(const QVariantMap &data, const QS
if (maxDomain.isValid())
return QStringLiteral("<= ") + maxDomain.toString();
if (domainDomain.isValid())
- return domainDomain.toString();
+ return QString::fromUtf8(QJsonDocument::fromVariant(domainDomain).toJson(QJsonDocument::Compact));
return QString();
}
/*!
- \qmlmethod IviSimulator::checkSettings(object data, var data, string zone)
+ \qmlmethod IviSimulator::checkSettings(object data, var value, string zone)
Searches for all boundary settings in \a data for the given \a zone and returns whether the
- provided \a value meets this contraint.
+ provided \a value meets this constraint.
- To show meaningful error messages when the value is not within the boundaries, the contraint()
+ To show meaningful error messages when the value is not within the boundaries, the constraint()
function can be used.
\sa constraint()
@@ -429,7 +431,7 @@ bool QIviSimulationGlobalObject::checkSettings(const QVariantMap &data, const QV
const QVariant domainDomain = parseDomainValue(data, domainLiteral, zone);
if (unsupportedDomain.isValid())
- return unsupportedDomain.toBool();
+ return !unsupportedDomain.toBool();
if (minDomain.isValid() && maxDomain.isValid())
return !(value < minDomain || value > maxDomain);
if (minDomain.isValid())
@@ -461,8 +463,8 @@ QVariant QIviSimulationGlobalObject::parseDomainValue(const QVariantMap &data, c
if (zone.isEmpty())
z = QStringLiteral("=");
- if (domainMap.contains(zone))
- return qtivi_convertFromJSON(domainMap.value(zone));
+ if (domainMap.contains(z))
+ return qtivi_convertFromJSON(domainMap.value(z));
}
return qtivi_convertFromJSON(domainData);
diff --git a/src/ivicore/qivisimulationglobalobject_p.h b/src/ivicore/qivisimulationglobalobject_p.h
index aaae92a..1ab5e21 100644
--- a/src/ivicore/qivisimulationglobalobject_p.h
+++ b/src/ivicore/qivisimulationglobalobject_p.h
@@ -69,7 +69,7 @@
QT_BEGIN_NAMESPACE
-class QIviSimulationGlobalObject : public QObject
+class Q_QTIVICORE_EXPORT QIviSimulationGlobalObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant simulationData READ simulationData CONSTANT)
diff --git a/src/ivicore/qtivicoremodule.cpp b/src/ivicore/qtivicoremodule.cpp
index 18836de..576fd01 100644
--- a/src/ivicore/qtivicoremodule.cpp
+++ b/src/ivicore/qtivicoremodule.cpp
@@ -69,7 +69,7 @@ QObject* serviceManagerSingelton(QQmlEngine *, QJSEngine *)
\inmodule QtIviCore
\brief The QtIviCoreModule class holds enums which are used by multiple classes of QtIviCore
- and provides convenience functions to register types to QML
+ and provides convenience functions to register types to QML.
*/
/*!
diff --git a/src/ivivehiclefunctions/doc/src/examples-climate_widget.qdoc b/src/ivivehiclefunctions/doc/src/examples-climate_widget.qdoc
index 9b1e1c1..82b92a8 100644
--- a/src/ivivehiclefunctions/doc/src/examples-climate_widget.qdoc
+++ b/src/ivivehiclefunctions/doc/src/examples-climate_widget.qdoc
@@ -63,7 +63,7 @@
The first thing to do is to create a QIviClimateControl instance in our
MainWindow constructor. As we only have one Climate backend and don't want
- to choose which one to use, we call \l {QIviAbstractFeature::}{startAutoDiscovery()}
+ to choose which one to use, we call \l {QIviAbstractFeature::}{startAutoDiscovery}
to start searching for a suitable backend right away and pick the first one
that matches.
diff --git a/src/plugins/ivimedia/media_qtro/media_qtro.pro b/src/plugins/ivimedia/media_qtro/media_qtro.pro
index 20b2881..f6f96c5 100644
--- a/src/plugins/ivimedia/media_qtro/media_qtro.pro
+++ b/src/plugins/ivimedia/media_qtro/media_qtro.pro
@@ -2,7 +2,7 @@ TARGET = media_qtro
PLUGIN_TYPE = qtivi
PLUGIN_EXTENDS = ivimedia
-PLUGIN_CLASS_NAME = MediaPlugin
+PLUGIN_CLASS_NAME = MediaQtROPlugin
load(qt_plugin)
diff --git a/src/plugins/ivimedia/media_qtro/mediaplugin.cpp b/src/plugins/ivimedia/media_qtro/mediaplugin.cpp
index eca202d..c8f73df 100644
--- a/src/plugins/ivimedia/media_qtro/mediaplugin.cpp
+++ b/src/plugins/ivimedia/media_qtro/mediaplugin.cpp
@@ -54,7 +54,7 @@
#include <QSettings>
#include <QRemoteObjectNode>
-MediaPlugin::MediaPlugin(QObject *parent)
+MediaQtROPlugin::MediaQtROPlugin(QObject *parent)
: QObject(parent)
, m_player(new MediaPlayerBackend(this))
, m_indexer(new MediaIndexerBackend(this))
@@ -63,7 +63,7 @@ MediaPlugin::MediaPlugin(QObject *parent)
{
}
-QStringList MediaPlugin::interfaces() const
+QStringList MediaQtROPlugin::interfaces() const
{
QStringList list;
@@ -74,7 +74,7 @@ QStringList MediaPlugin::interfaces() const
return list;
}
-QIviFeatureInterface *MediaPlugin::interfaceInstance(const QString &interface) const
+QIviFeatureInterface *MediaQtROPlugin::interfaceInstance(const QString &interface) const
{
if (interface == QStringLiteral(QIviMediaPlayer_iid))
return m_player;
diff --git a/src/plugins/ivimedia/media_qtro/mediaplugin.h b/src/plugins/ivimedia/media_qtro/mediaplugin.h
index 79bad77..b77be79 100644
--- a/src/plugins/ivimedia/media_qtro/mediaplugin.h
+++ b/src/plugins/ivimedia/media_qtro/mediaplugin.h
@@ -49,14 +49,14 @@ class MediaIndexerBackend;
class SearchAndBrowseModel;
class MediaDiscoveryBackend;
-class MediaPlugin : public QObject, QIviServiceInterface
+class MediaQtROPlugin : public QObject, QIviServiceInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QIviServiceInterface_iid FILE "media_qtro.json")
Q_INTERFACES(QIviServiceInterface)
public:
- explicit MediaPlugin(QObject *parent = nullptr);
+ explicit MediaQtROPlugin(QObject *parent = nullptr);
QStringList interfaces() const override;
QIviFeatureInterface *interfaceInstance(const QString &interface) const override;
diff --git a/src/plugins/ivimedia/media_simulator/mediaplayerbackend.cpp b/src/plugins/ivimedia/media_simulator/mediaplayerbackend.cpp
index 6863ed3..30ac847 100644
--- a/src/plugins/ivimedia/media_simulator/mediaplayerbackend.cpp
+++ b/src/plugins/ivimedia/media_simulator/mediaplayerbackend.cpp
@@ -98,7 +98,11 @@ void MediaPlayerBackend::initialize()
void MediaPlayerBackend::play()
{
qCDebug(media) << Q_FUNC_INFO;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
qCDebug(media) << m_player->media().request().url();
+#else
+ qCDebug(media) << m_player->media().canonicalUrl();
+#endif
m_requestedState = QIviMediaPlayer::Playing;
m_player->play();
}
diff --git a/src/plugins/ivimedia/media_simulator/mediaplugin.cpp b/src/plugins/ivimedia/media_simulator/mediaplugin.cpp
index 68e9c8f..b158dc2 100644
--- a/src/plugins/ivimedia/media_simulator/mediaplugin.cpp
+++ b/src/plugins/ivimedia/media_simulator/mediaplugin.cpp
@@ -56,7 +56,7 @@
#include <QStringList>
#include <QtDebug>
-MediaPlugin::MediaPlugin(QObject *parent)
+MediaSimulatorPlugin::MediaSimulatorPlugin(QObject *parent)
: QObject(parent)
, m_discovery(new MediaDiscoveryBackend(this))
{
@@ -85,7 +85,7 @@ MediaPlugin::MediaPlugin(QObject *parent)
}
-QStringList MediaPlugin::interfaces() const
+QStringList MediaSimulatorPlugin::interfaces() const
{
QStringList list;
list << QStringLiteral(QIviMediaPlayer_iid);
@@ -95,7 +95,7 @@ QStringList MediaPlugin::interfaces() const
return list;
}
-QIviFeatureInterface *MediaPlugin::interfaceInstance(const QString &interface) const
+QIviFeatureInterface *MediaSimulatorPlugin::interfaceInstance(const QString &interface) const
{
if (interface == QStringLiteral(QIviMediaPlayer_iid))
return m_player;
diff --git a/src/plugins/ivimedia/media_simulator/mediaplugin.h b/src/plugins/ivimedia/media_simulator/mediaplugin.h
index 23f42d6..1e27d3e 100644
--- a/src/plugins/ivimedia/media_simulator/mediaplugin.h
+++ b/src/plugins/ivimedia/media_simulator/mediaplugin.h
@@ -54,14 +54,14 @@ class MediaDiscoveryBackend;
class MediaIndexerBackend;
class AmFmTunerBackend;
-class MediaPlugin : public QObject, QIviServiceInterface
+class MediaSimulatorPlugin : public QObject, QIviServiceInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QIviServiceInterface_iid FILE "media_simulator.json")
Q_INTERFACES(QIviServiceInterface)
public:
- explicit MediaPlugin(QObject *parent = nullptr);
+ explicit MediaSimulatorPlugin(QObject *parent = nullptr);
QStringList interfaces() const override;
QIviFeatureInterface *interfaceInstance(const QString &interface) const override;
diff --git a/src/plugins/ivimedia/tuner_simulator/tunerplugin.cpp b/src/plugins/ivimedia/tuner_simulator/tunerplugin.cpp
index 5be4e5d..74c54ce 100644
--- a/src/plugins/ivimedia/tuner_simulator/tunerplugin.cpp
+++ b/src/plugins/ivimedia/tuner_simulator/tunerplugin.cpp
@@ -49,14 +49,14 @@
#include <QtIviCore/QIviSearchAndBrowseModel>
#include <QtIviMedia/QIviMediaPlayer>
-TunerPlugin::TunerPlugin(QObject *parent)
+TunerSimulatorPlugin::TunerSimulatorPlugin(QObject *parent)
: QObject(parent)
, m_amfmtuner(new AmFmTunerBackend(this))
, m_searchbackend(new SearchAndBrowseBackend(m_amfmtuner, this))
{
}
-QStringList TunerPlugin::interfaces() const
+QStringList TunerSimulatorPlugin::interfaces() const
{
QStringList list;
list << QStringLiteral(QIviSearchAndBrowseModel_iid);
@@ -64,7 +64,7 @@ QStringList TunerPlugin::interfaces() const
return list;
}
-QIviFeatureInterface *TunerPlugin::interfaceInstance(const QString &interface) const
+QIviFeatureInterface *TunerSimulatorPlugin::interfaceInstance(const QString &interface) const
{
if (interface == QLatin1String(QIviAmFmTuner_iid))
return m_amfmtuner;
diff --git a/src/plugins/ivimedia/tuner_simulator/tunerplugin.h b/src/plugins/ivimedia/tuner_simulator/tunerplugin.h
index 73999bc..bbbebc3 100644
--- a/src/plugins/ivimedia/tuner_simulator/tunerplugin.h
+++ b/src/plugins/ivimedia/tuner_simulator/tunerplugin.h
@@ -48,14 +48,14 @@
class AmFmTunerBackend;
class SearchAndBrowseBackend;
-class TunerPlugin : public QObject, QIviServiceInterface
+class TunerSimulatorPlugin : public QObject, QIviServiceInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QIviServiceInterface_iid FILE "tuner_simulator.json")
Q_INTERFACES(QIviServiceInterface)
public:
- explicit TunerPlugin(QObject *parent = nullptr);
+ explicit TunerSimulatorPlugin(QObject *parent = nullptr);
QStringList interfaces() const override;
QIviFeatureInterface *interfaceInstance(const QString &interface) const override;
diff --git a/src/plugins/ivivehiclefunctions/vehiclefunctions_qtro/vehiclefunctions_qtro.pro b/src/plugins/ivivehiclefunctions/vehiclefunctions_qtro/vehiclefunctions_qtro.pro
index 009d19d..016900c 100644
--- a/src/plugins/ivivehiclefunctions/vehiclefunctions_qtro/vehiclefunctions_qtro.pro
+++ b/src/plugins/ivivehiclefunctions/vehiclefunctions_qtro/vehiclefunctions_qtro.pro
@@ -11,6 +11,6 @@ QFACE_SOURCES += ../../../ivivehiclefunctions/ivivehiclefunctions.qface
PLUGIN_TYPE = qtivi
PLUGIN_EXTENDS = ivivehiclefunctions
-PLUGIN_CLASS_NAME = QtIviVehicleFunctionsPlugin
+PLUGIN_CLASS_NAME = QtIviVehicleFunctionsQtROPlugin
load(qt_plugin)
diff --git a/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/QIviConcreteWindowControlSimulation.qml b/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/QIviConcreteWindowControlSimulation.qml
index 0aa9ed7..770f847 100644
--- a/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/QIviConcreteWindowControlSimulation.qml
+++ b/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/QIviConcreteWindowControlSimulation.qml
@@ -140,45 +140,47 @@ QtObject {
function setHeaterMode(heaterMode, zone) {
- if (IviSimulator.checkSettings(settings["heaterMode"], heaterMode, zone)) {
- if (zone) {
- console.log("SIMULATION heaterMode for zone: " + zone + " changed to: " + heaterMode);
- backend.zones[zone].heaterMode = heaterMode
- } else {
- console.log("SIMULATION heaterMode changed to: " + heaterMode);
- backend.heaterMode = heaterMode
- }
+ if ("heaterMode" in settings && !IviSimulator.checkSettings(settings["heaterMode"], heaterMode, zone)) {
+ console.error("SIMULATION changing heaterMode is not possible: provided: " + heaterMode + "constraint: " + IviSimulator.constraint(settings["heaterMode"]));
+ return;
+ }
+
+ if (zone) {
+ console.log("SIMULATION heaterMode for zone: " + zone + " changed to: " + heaterMode);
+ backend.zones[zone].heaterMode = heaterMode
} else {
- console.error("SIMULATION changing heaterMode is not possible: provided: " + heaterMode + "constraint: " + IviSimulator.constraint_string(settings["heaterMode"]));
+ console.log("SIMULATION heaterMode changed to: " + heaterMode);
+ backend.heaterMode = heaterMode
}
}
function setHeater(heater, zone) {
- if (IviSimulator.checkSettings(settings["heater"], heater, zone)) {
- console.log("SIMULATION heater changed to: " + heater);
- if (zone) {
- console.log("SIMULATION heater for zone: " + zone + " changed to: " + heater);
- backend.zones[zone].heater = heater
- } else {
- console.log("SIMULATION heater changed to: " + heater);
- backend.heater = heater
- }
+ if ("heater" in settings && !IviSimulator.checkSettings(settings["heater"], heater, zone)) {
+ console.error("SIMULATION changing heater is not possible: provided: " + heater + "constraint: " + IviSimulator.constraint(settings["heater"]));
+ return;
+ }
+
+ if (zone) {
+ console.log("SIMULATION heater for zone: " + zone + " changed to: " + heater);
+ backend.zones[zone].heater = heater
} else {
- console.error("SIMULATION changing heater is not possible: provided: " + heater + "constraint: " + IviSimulator.constraint_string(settings["heater"]));
+ console.log("SIMULATION heater changed to: " + heater);
+ backend.heater = heater
}
}
function setState(state, zone) {
- if (IviSimulator.checkSettings(settings["state"], state, zone)) {
- if (zone) {
- console.log("SIMULATION state for zone: " + zone + " changed to: " + state);
- backend.zones[zone].state = state
- } else {
- console.log("SIMULATION state changed to: " + state);
- backend.state = state
- }
+ if ("state" in settings && !IviSimulator.checkSettings(settings["state"], state, zone)) {
+ console.error("SIMULATION changing state is not possible: provided: " + state + "constraint: " + IviSimulator.constraint(settings["state"]));
+ return;
+ }
+
+ if (zone) {
+ console.log("SIMULATION state for zone: " + zone + " changed to: " + state);
+ backend.zones[zone].state = state
} else {
- console.error("SIMULATION changing state is not possible: provided: " + state + "constraint: " + IviSimulator.constraint_string(settings["state"]));
+ console.log("SIMULATION state changed to: " + state);
+ backend.state = state
}
}
@@ -190,16 +192,17 @@ QtObject {
}
function setBlindState(blindState, zone) {
- if (IviSimulator.checkSettings(settings["blindState"], blindState, zone)) {
- if (zone) {
- console.log("SIMULATION blindState for zone: " + zone + " changed to: " + blindState);
- backend.zones[zone].blindState = blindState
- } else {
- console.log("SIMULATION blindState changed to: " + blindState);
- backend.blindState = blindState
- }
+ if ("blindState" in settings && !IviSimulator.checkSettings(settings["blindState"], blindState, zone)) {
+ console.error("SIMULATION changing blindState is not possible: provided: " + blindState + "constraint: " + IviSimulator.constraint(settings["blindState"]));
+ return;
+ }
+
+ if (zone) {
+ console.log("SIMULATION blindState for zone: " + zone + " changed to: " + blindState);
+ backend.zones[zone].blindState = blindState
} else {
- console.error("SIMULATION changing blindState is not possible: provided: " + blindState + "constraint: " + IviSimulator.constraint_string(settings["blindState"]));
+ console.log("SIMULATION blindState changed to: " + blindState);
+ backend.blindState = blindState
}
}
}
diff --git a/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/vehiclefunctions_simulator.pro b/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/vehiclefunctions_simulator.pro
index ea81268..8751c91 100644
--- a/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/vehiclefunctions_simulator.pro
+++ b/src/plugins/ivivehiclefunctions/vehiclefunctions_simulator/vehiclefunctions_simulator.pro
@@ -11,7 +11,7 @@ QFACE_SOURCES += ../../../ivivehiclefunctions/ivivehiclefunctions.qface
PLUGIN_TYPE = qtivi
PLUGIN_EXTENDS = ivivehiclefunctions
-PLUGIN_CLASS_NAME = QtIviVehicleFunctionsPlugin
+PLUGIN_CLASS_NAME = QtIviVehicleFunctionsSimulatorPlugin
load(qt_plugin)
diff --git a/src/tools/ivigenerator/common/pagingmodel.rep.tpl b/src/tools/ivigenerator/common/pagingmodel.rep.tpl
deleted file mode 100644
index 0ccda70..0000000
--- a/src/tools/ivigenerator/common/pagingmodel.rep.tpl
+++ /dev/null
@@ -1,61 +0,0 @@
-{#
-# Copyright (C) 2019 Luxoft Sweden AB
-# 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
-#}
-/////////////////////////////////////////////////////////////////////////////
-// Generated from '{{module}}.qface'
-//
-// Created by: The QFace generator (QtAS {{qtASVersion}})
-//
-// WARNING! All changes made in this file will be lost!
-/////////////////////////////////////////////////////////////////////////////
-
-#include <QtIviCore/QtIviCoreModule>
-#include <QUuid>
-
-class PagingModel
-{
- SLOT(void registerInstance(const QUuid &identifier))
- SLOT(void unregisterInstance(const QUuid &identifier))
- SLOT(void fetchData(const QUuid &identifier, int start, int count))
-
- SIGNAL(supportedCapabilitiesChanged(const QUuid &identifier, QtIviCoreModule::ModelCapabilities capabilities))
- SIGNAL(countChanged(const QUuid &identifier, int newLength))
- SIGNAL(dataFetched(const QUuid &identifier, const QList<QVariant> &data, int start, bool moreAvailable))
- SIGNAL(dataChanged(const QUuid &identifier, const QList<QVariant> &data, int start, int count))
-};
diff --git a/src/tools/ivigenerator/generate.py b/src/tools/ivigenerator/generate.py
index b792797..ba35506 100755
--- a/src/tools/ivigenerator/generate.py
+++ b/src/tools/ivigenerator/generate.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
+# Copyright (C) 2019 The Qt Company Ltd.
# Copyright (C) 2019 Luxoft Sweden AB
# Copyright (C) 2018 Pelagicore AG
# Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB)
@@ -38,699 +39,72 @@
#
# SPDX-License-Identifier: LGPL-3.0
-import re
import os
+import sys
+import fnmatch
import click
import logging.config
-import yaml
-import json
from path import Path
from qface.generator import FileSystem, Generator
-from qface.helper.qtcpp import Filters
from qface.watch import monitor
-from qface.idl.domain import Module, Interface, Property, Parameter, Field, Struct
-from qface.helper.generic import upper_first
-from jinja2 import TemplateAssertionError
-import inspect
+import generator.builtin_config as builtin_config
+from generator.global_functions import register_global_functions
+from generator.filters import register_filters
+from generator.rule_generator import CustomRuleGenerator
here = Path(__file__).dirname()
log = logging.getLogger(__file__)
-Filters.classPrefix = ''
-currentQFaceSrcFile = ''
+builtinTemplatesPath = Path(here / 'templates')
+builtinTemplates = [os.path.splitext(f)[0] for f in os.listdir(builtinTemplatesPath) if fnmatch.fnmatch(f, '*.yaml')]
-builtin_config = {}
-IVI_DEFAULT_TEMPLATES = ['frontend', 'qmlplugin', 'backend_simulator', 'backend_qtro', 'server_qtro', 'server_qtro_simulator', 'test']
-def jinjaTrace():
- """
- Collects all jinja template files and the line numbers from the current calltrace
- """
- frame = inspect.currentframe()
- infos = []
- while frame:
- template = frame.f_globals.get('__jinja_template__')
- if template is not None:
- infos.append((inspect.getsourcefile(frame), template.get_corresponding_lineno(frame.f_lineno)))
- frame = frame.f_back
-
- return infos
-
-def jinja_error(msg):
- """
- Throws an error for the current jinja template and the templates this is included from
- This can be used inside a filter to indicate problems with the passed arguments or direclty inside
- an template
- """
- infos = jinjaTrace()
- if len(infos):
- message = msg
- if len(infos) > 1:
- for info in infos[1:]:
- message = message + "\n{0}:{1}: instantiated from here".format(info[0], info[1])
- message = message + "\n{0}: instantiated from here".format(currentQFaceSrcFile)
- raise TemplateAssertionError(message, infos[0][1], "", infos[0][0])
- raise TemplateAssertionError(msg, -1, "", "unknown")
-
-def jinja_warning(msg):
- """
- Reports an warning in the current jinja template.
- This can be used inside a filter to indicate problems with the passed arguments or direclty inside
- an template
- """
- file, lineno = jinjaTrace()[0]
- if file:
- message = '{0}:{1}: warning: {2}'.format(file, lineno, msg)
- else:
- message = '<unknown-file>: warning: {0}'.format(msg)
- click.secho(message, fg='yellow', err=True)
-
-def tag_by_path(symbol, path, default_value=False):
- """
- Find the tag given by its full path in the object hierarchy,
- like "property.config_sim.zones.right". If some part of the
- path is missing, return None
- """
- path_parts = path.split(".")
- cur_level_obj = symbol.tags
- for path_part in path_parts:
- if path_part in cur_level_obj:
- cur_level_obj = cur_level_obj[path_part]
- else:
- cur_level_obj = None
- break
- if cur_level_obj is None:
- cur_level_obj = default_value
- return cur_level_obj
-
-
-def conf_sim_tag(symbol, path, default_value=False):
- """
- Find tag, given by its path, located under "config_simulator" sub-object.
- Returns None, of any of the path parts is missing
- """
- return tag_by_path(symbol, "config_simulator." + path, default_value)
-
-
-def enum_value_to_cppliteral(value, module_name):
- value = value.strip().rsplit('.', 1)[-1]
- return '{0}{1}Module::{2}'.format(Filters.classPrefix, upper_first(module_name), value)
-
-
-def enum_value(value, module_name):
- sub_values = value.split('|')
- sub_values = [enum_value_to_cppliteral(v, module_name) for v in sub_values]
- return "|".join(sub_values)
-
-def default_type_value(symbol):
- """
- Find the default value for the type. Models are initialized as nullptr
- """
- prefix = Filters.classPrefix
- t = symbol.type # type: qface.domain.TypeSymbol
- if t.is_primitive:
- if t.is_int:
- return 'int(0)'
- if t.is_bool:
- return 'bool(false)'
- if t.is_string:
- return 'QString()'
- if t.is_real:
- return 'qreal(0.0)'
- if t.is_var:
- return 'QVariant()'
- elif t.is_void:
- return ''
- elif t.is_enum:
- module_name = t.reference.module.module_name
- value = next(iter(t.reference.members))
- return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
- elif t.is_flag:
- module_name = t.reference.module.module_name
- return '{0}{1}Module::{2}()'.format(prefix, upper_first(module_name), flag_type(symbol))
- elif symbol.type.is_list:
- nested = Filters.returnType(symbol.type.nested)
- return 'QVariantList()'.format(nested)
- elif symbol.type.is_struct:
- return '{0}{1}()'.format(prefix, symbol.type)
- elif symbol.type.is_model:
- return 'nullptr'
- jinja_error('default_type_value: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
-
-def test_type_value(symbol):
- """
- Find a value different than the default value for the type. Models are initialized as nullptr
- """
- prefix = Filters.classPrefix
- t = symbol.type # type: qface.domain.TypeSymbol
- if t.is_primitive:
- if t.is_int:
- return '111'
- if t.is_bool:
- return 'true'
- if t.is_string:
- return '"TEST STRING"'
- if t.is_real:
- return '1234.5678'
- if t.is_var:
- return 'QVariant("TEST VARIANT")'
- elif t.is_void:
- return ''
- elif t.is_enum:
- module_name = t.reference.module.module_name
- value = list(iter(t.reference.members))[-1]
- return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
- elif t.is_flag:
- module_name = t.reference.module.module_name
- value = next(iter(t.reference.members))
- return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
- elif symbol.type.is_list:
- value = test_type_value(t.nested.type)
- if not (t.nested.type.is_primitive ):
- value = 'QVariant::fromValue({0})'.format(value)
- return 'QVariantList({{{0}}})'.format(value)
- elif symbol.type.is_struct:
- values_string = ', '.join(test_type_value(e) for e in symbol.type.reference.fields)
- return '{0}{1}({2})'.format(prefix, symbol.type, values_string)
- elif symbol.type.is_model:
- return 'new QIviPagingModel()'
- jinja_error('test_type_value: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
-
-def default_value_helper(symbol, res):
- t = symbol.type
- if t.is_struct:
- if not (isinstance(res, dict) or isinstance(res, list)):
- jinja_error('default_value: value in annotation is supposed to be a dict or list')
- if len(res) != len(t.reference.fields):
- jinja_error('default_value: argument count in annotation and number of struct fields does not match')
- values_string = ', '.join(default_value_helper(list(t.reference.fields)[idx], property) for idx, property in enumerate(res))
- return '{0}({{{1}}})'.format(t.type, values_string)
- if t.is_model or t.is_list:
- if not isinstance(res, list):
- jinja_error('default_value: value in annotation is supposed to be a list')
- row_string = ''
- if t.nested.is_struct and t.is_list:
- row_string = ', '.join(('QVariant::fromValue({0})'.format(default_value_helper(t.nested, row))) for row in res)
- else:
- row_string = ', '.join(default_value_helper(t.nested, row) for row in res)
- return '{{{0}}}'.format(row_string)
- if t.is_enum or t.is_flag:
- module_name = t.reference.module.module_name
- return enum_value(res, module_name)
- # in case it's bool, Python True is sent to the C++ as "True", let's take care of that
- if t.is_bool:
- if res:
- return 'true'
- else:
- return 'false'
- if t.is_string:
- return 'QLatin1String("{0}")'.format(res.replace("\\", "\\\\"))
- if t.is_var:
- if isinstance(res, str):
- res = 'QLatin1String("{0}")'.format(res)
- return 'QVariant({0})'.format(res)
-
- return '{0}'.format(res)
-
-def default_value(symbol, zone='='):
- """
- Find the default value used by the simulator backend
- """
- res = default_type_value(symbol)
- if symbol.type.is_model:
- res = '{}';
- if 'config_simulator' in symbol.tags and 'default' in symbol.tags['config_simulator']:
- res = symbol.tags['config_simulator']['default']
- if isinstance(res, dict):
- if zone in res:
- res = res[zone]
- elif '=' in res:
- res = res['=']
- return default_value_helper(symbol, res)
-
- return res
-
-def parameter_type_default(symbol):
- """
- Return the parameter declaration for properties, handle camel case module name
- """
- prefix = Filters.classPrefix
- if symbol.type.is_enum or symbol.type.is_flag:
- return '{0}{1}Module::{2} {3}={4}'.format(prefix, upper_first(symbol.module.module_name), flag_type(symbol), symbol, default_type_value(symbol))
- if symbol.type.is_void or symbol.type.is_primitive:
- if symbol.type.name == 'string':
- return 'const QString &{0}=QString()'.format(symbol)
- if symbol.type.name == 'var':
- return 'const QVariant &{0}=QVariant()'.format(symbol)
- if symbol.type.name == 'real':
- return 'qreal {0}=qreal()'.format(symbol)
- return '{0} {1}={2}'.format(symbol.type, symbol, default_type_value(symbol))
- elif symbol.type.is_list:
- nested = return_type(symbol.type.nested)
- return 'const QVariantList &{1}=QVariantList()'.format(nested, symbol)
- elif symbol.type.is_model:
- nested = symbol.type.nested
- if nested.is_primitive:
- return '{0}VariantModel *{1}=QVariantModel'.format(prefix, symbol)
- elif nested.is_complex:
- return 'QIviPagingModel *{0}=nullptr'.format(symbol)
- else:
- return 'const {0}{1} &{2}={0}{1}()'.format(prefix, symbol.type, symbol)
- jinja_error('parameter_type_default: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
-
-def parameter_type(symbol):
- """
- Return the parameter declaration for properties, handle camel case module name
- """
- prefix = Filters.classPrefix
- if symbol.type.is_enum or symbol.type.is_flag:
- return '{0}{1}Module::{2} {3}'.format(prefix, upper_first(symbol.module.module_name), flag_type(symbol), symbol)
- if symbol.type.is_void or symbol.type.is_primitive:
- if symbol.type.name == 'string':
- return 'const QString &{0}'.format(symbol)
- if symbol.type.name == 'var':
- return 'const QVariant &{0}'.format(symbol)
- if symbol.type.name == 'real':
- return 'qreal {0}'.format(symbol)
- return '{0} {1}'.format(symbol.type, symbol)
- elif symbol.type.is_list:
- nested = return_type(symbol.type.nested)
- return 'const QVariantList &{1}'.format(nested, symbol)
- elif symbol.type.is_model:
- nested = symbol.type.nested
- if nested.is_primitive:
- return '{0}VariantModel *{1}'.format(prefix, symbol)
- elif nested.is_complex:
- return 'QIviPagingModel *{0}'.format(symbol)
- else:
- return 'const {0}{1} &{2}'.format(prefix, symbol.type, symbol)
- jinja_error('parameter_type: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
-
-
-def return_type(symbol):
- """
- Return the type declaration for properties, handle camel case module name
- """
- prefix = Filters.classPrefix
- if symbol.type.is_enum or symbol.type.is_flag:
- return('{0}{1}Module::{2}'.format(prefix, upper_first(symbol.module.module_name), flag_type(symbol)))
- if symbol.type.is_void or symbol.type.is_primitive:
- if symbol.type.name == 'string':
- return 'QString'
- if symbol.type.name == 'var':
- return 'QVariant'
- if symbol.type.name == 'real':
- return 'qreal'
- return symbol.type.name
- elif symbol.type.is_list:
- nested = return_type(symbol.type.nested)
- return 'QVariantList'.format(nested)
- elif symbol.type.is_model:
- nested = symbol.type.nested
- if nested.is_primitive:
- return '{0}VariantModel *'.format(prefix)
- elif nested.is_complex:
- return 'QIviPagingModel *'
- else:
- return '{0}{1}'.format(prefix, symbol.type)
- jinja_error('return_type: Unknown symbol {0} of type {1}'.format(symbol, symbol.type))
-
-
-def flag_type(symbol):
- """
- Return the annotation for the flag type if available, the plural otherwise
- """
- actualType = symbol
- if symbol.type.reference:
- actualType = symbol.type.reference
- if actualType.is_flag:
- if 'config' in actualType.tags and 'type' in actualType.tags['config']:
- return actualType.tags['config']['type']
- return '{0}s'.format(actualType)
- return actualType
-
-
-def domain_values(symbol):
- """
- Returns domain values for property (if defined by @domain)
- """
- if type(symbol) is Property:
- if 'config_simulator' in symbol.tags:
- if 'domain' in symbol.tags['config_simulator']:
- return symbol.tags['config_simulator']['domain']
- return None
-
-def getter_name(symbol):
- """
- Returns the getter name of the property
- """
- if type(symbol) is Property:
- if 'config' in symbol.tags and 'getter_name' in symbol.tags['config']:
- return symbol.tags['config']['getter_name']
- return symbol
-
-def setter_name(symbol):
- """
- Returns the setter name of the property
- """
- if type(symbol) is Property:
- if 'config' in symbol.tags and 'setter_name' in symbol.tags['config']:
- return symbol.tags['config']['setter_name']
- return 'set' + symbol.name[0].upper() + symbol.name[1:]
-
-def range_value(symbol, index, key):
- """
- Returns value for property (if defined by @range index or key)
- """
- if type(symbol) is Property and symbol.type.is_int or symbol.type.is_real:
- if 'config_simulator' in symbol.tags:
- if 'range' in symbol.tags['config_simulator']:
- return symbol.tags['config_simulator']['range'][index]
- if key in symbol.tags['config_simulator']:
- return symbol.tags['config_simulator'][key]
- return None
-
-
-def range_high(symbol):
- """
- Returns maximum value for property (if defined by @range or @maximum)
- """
- return range_value(symbol, 1, 'maximum')
-
-
-def range_low(symbol):
- """
- Returns minimum value for property (if defined by @range or @minimum)
- """
- return range_value(symbol, 0, 'minimum')
+def validateType(srcFile, type, errorString):
+ if type.is_interface:
+ sys.exit("{0}: {1} of type 'interface' are not supported".format(srcFile, errorString))
+ if type.is_map:
+ sys.exit("{0}: {1} of type 'map' are not supported".format(srcFile, errorString))
-def has_domains(properties):
+def validateSystem(srcFile, system):
"""
- Returns true if any property has range or domain tags
+ Searches for types we don't support and reports an error
"""
- for property in properties:
- if 'config_simulator' in property.tags:
- for p in ['range', 'domain', 'minimum', 'maximum']:
- if p in property.tags['config_simulator']:
- return True
- return False
-
-def strip_QT(s):
- """
- If the given string starts with QT, stip it away.
- """
- s = str(s)
- if s.startswith('QT'):
- return s[2:]
- return s
-
-def json_domain(properties):
- """
- Returns property domains formated in json
- """
- data = {}
- if len(properties):
- data["iviVersion"] = builtin_config["VERSION"]
- for property in properties:
- if 'config_simulator' in property.tags:
- for p in ['range', 'domain', 'minimum', 'maximum']:
- if property.tags['config_simulator'] is not None and p in property.tags['config_simulator']:
- if not property.name in data:
- data[property.name] = {}
- data[property.name][p] = property.tags['config_simulator'][p]
- return json.dumps(data, separators=(',', ':'))
-
-def simulationData(module):
-# if type(module) is not Module:
-# return
-
- found = False
- data = {}
- for interface in module.interfaces:
- iData = {}
- if 'config_simulator' in interface.tags:
- iData = interface.tags['config_simulator']
- for property in interface.properties:
- if 'config_simulator' in property.tags:
- for p in ['range', 'domain', 'minimum', 'maximum', 'default']:
- if property.tags['config_simulator'] is not None and p in property.tags['config_simulator']:
- if not property.name in iData:
- iData[property.name] = {}
- iData[property.name][p] = symbolToJson(property.tags['config_simulator'][p], property.type)
- data[interface.name] = iData
- return json.dumps(data, indent=' ')
-
-def symbolToJson(data, symbol):
- if symbol.type.is_struct:
- t = symbol.type
- if not (isinstance(data, dict) or isinstance(data, list)):
- jinja_error('simulationData: value in annotation is supposed to be a dict or list')
- if len(data) != len(t.reference.fields):
- jinja_error('simulationData: argument count in annotation and number of struct fields does not match')
- newList = list(symbolToJson(property, list(t.reference.fields)[idx]) for idx, property in enumerate(data))
- return { "type": symbol.type.name, "value": newList }
- elif symbol.type.is_enum or symbol.type.is_flag:
- module_name = symbol.type.reference.module.module_name
- return { "type": "enum", "value": enum_value(data, module_name) }
- elif symbol.type.is_list or symbol.type.is_model:
- nested = symbol.type.nested
- if nested.is_complex:
- newList = []
- for value in data:
- newList.append(symbolToJson(value, nested))
- return newList
- return data
-
-def qml_control_properties(symbol, backend_object):
- """
- Returns properties of the QML control matching to this
- IDL type (e.g. min/max properties)
- """
- prop_str = lower_first_filter(symbol) + "Control"
- if isinstance(symbol, Property):
- top = range_high(symbol)
- bottom = range_low(symbol)
- binding = "value: {0}.{1};".format(backend_object, symbol.name)
- if top is not None and bottom is not None:
- return 'id: {0}; from: {1}; to: {2}; {3}'.format(prop_str, bottom, top, binding)
-
- if top is not None or bottom is not None:
- if top is None:
- return 'id: {0}; from: {1}; to:100000; {2}'.format(prop_str, bottom, binding)
- elif bottom is None:
- return 'id: {0}; from:-100000; to: {1}; {2}'.format(prop_str, top, binding)
-
- values = domain_values(symbol)
- if values is None and (symbol.type.is_enum or symbol.type.is_flag):
- values_string = ' '.join('ListElement {{ key: "{0}"; value: {1}.{0} }}'.format(e, qml_type(symbol.interface)) for e in symbol.type.reference.members)
- return 'id: {0}; textRole: "key"; {2} model: ListModel {{ {1} }}'.format(prop_str, values_string, binding)
- if values is not None:
- values_string = ','.join('"'+str(e)+'"' for e in values)
- return 'id: {0}; model: [ {1} ]; '.format(prop_str, values_string)
- if symbol.type.is_bool:
- binding = "checked: {0}.{1};".format(backend_object, symbol.name)
- return 'id: {0}; {1}'.format(prop_str, binding)
- if symbol.type.is_real or symbol.type.is_int or symbol.type.is_string:
- binding = "text: {0}.{1};".format(backend_object, symbol.name)
- return 'id: {0}; {1}'.format(prop_str, binding)
-
- if isinstance(symbol, Parameter):
- return 'id: {1}Param{0}'.format(prop_str, symbol.operation)
- if isinstance(symbol, Field):
- return 'id: {1}_{0}'.format(prop_str, lower_first_filter(symbol.struct))
-
-def qml_control_signal_parameters(symbol):
- """
- Returns the parameters for calling the signal using the values from the ui controls
- """
- return ', '.join('{0}Param{1}Control.{2}'.format(e.operation, lower_first_filter(e), qml_binding_property(e)) for e in symbol.parameters)
-
-def qml_meta_control_name(symbol):
- """
- Returns name of the QML control needed to display this type based on the meta
- data of the symbol -- if symbol has some meta data (e.g. value limits or domain)
- then control name is taken based on these constraints. Otherwise returns None.
- """
- top = range_high(symbol)
- bottom = range_low(symbol)
- if top is not None and bottom is not None:
- return 'Slider'
-
- if top is not None or bottom is not None:
- return 'SpinBox'
-
- values = domain_values(symbol)
- if values is not None:
- return "ComboBox"
-
-def qml_type_control_name(symbol):
- """
- Returns name of the QML control inferred based on the type of the symbol.
- """
- t = symbol.type
- if t.is_string or t.is_int or t.is_real:
- return "TextField"
- elif t.is_bool:
- return "CheckBox"
- elif t.is_enum:
- if t.reference.is_enum:
- return "EnumControl"
- elif t.reference.is_flag:
- return "FlagControl"
- elif t.is_flag:
- return "FlagControl"
- return "TextField"
-
-
-def qml_control_name(symbol):
- """
- Returns name of the QML control for the symbol. First it checks meta data (as it may
- influence the control type) and if nothing is defined there, it falls back to the
- symbol actual type.
- """
- # First try to calculate control name based on the tags
- control_name = qml_meta_control_name(symbol)
- # If nothing is defined, calculate it based on its type
- if control_name is None:
- control_name = qml_type_control_name(symbol)
- return control_name
-
-
-def qml_control(symbol, backend_object):
- """
- Returns QML code for the control (or group of controls) to represent the editing UI for the symbol.
- """
-
- if symbol.type.is_struct:
- return qml_struct_control(symbol)
-
- return "{0} {{ {1} }}".format(qml_control_name(symbol), qml_control_properties(symbol, backend_object))
-
+ for module in system.modules:
+ for interface in module.interfaces:
+ for property in interface.properties:
+ validateType(srcFile, property.type, "Properties")
+ for operation in interface.operations:
+ for param in operation.parameters:
+ validateType(srcFile, param.type, "Arguments")
+ validateType(srcFile, operation.type, "Return values")
-def qml_binding_property(symbol):
- """
- :param symbol: property which is being bound by the control
- :return: name of the property of the QML control to be bound with
- """
- control_name = qml_control_name(symbol)
- if control_name == "CheckBox":
- return "checked"
- elif control_name == "Slider" or control_name == "SpinBox" or control_name == "FlagControl" or control_name == "EnumControl":
- return "value"
- elif control_name == "TextField":
- return "text"
- elif control_name == "ComboBox":
- return "currentIndex"
-
-def qml_struct_control(symbol):
- if symbol.type.is_struct and symbol.type.reference.fields:
- result = "Rectangle { ColumnLayout { "
- for field in symbol.type.reference.fields:
- result += qml_control(field)
- result += "}}"
- return result
-
-
-def qml_info_type(symbol):
- """
- Returns the correct type for the symbol, to be used inside the qmltype templates
- """
- prefix = Filters.classPrefix
- if symbol.type.is_enum or symbol.type.is_flag:
- return('{0}{1}Module::{2}'.format(prefix, upper_first(symbol.module.module_name), flag_type(symbol)))
- elif symbol.type.is_void or symbol.type.is_primitive:
- if symbol.type.is_real:
- return 'double'
- return symbol.type.name
- elif symbol.type.is_struct:
- return 'QVariant'
- elif symbol.type.is_list:
- return 'QVariantList'
- elif symbol.type.is_model:
- return 'QIviPagingModel'
- else:
- jinja_error('qml_info_type: Unknown symbol {0} of type {1}'.format(symbol, symbol.type))
+ for signal in interface.signals:
+ for param in signal.parameters:
+ validateType(srcFile, param.type, "Arguments")
-def qml_type(symbol):
- """
- :param interface:
- :return: Returns the name of the interface for using in QML. This name is defined in the IDL under
- the "config" tag as "qml_type". This annotation is optional, if not provided, the interface name is
- used.
- """
- result = symbol.name
- if 'qml_type' in symbol.tags['config']:
- result = symbol.tags['config']['qml_type']
- elif 'qml_name' in symbol.tags['config']:
- result = symbol.tags['config']['qml_name']
- return result
-
-def model_type(symbol):
- if symbol.type.is_model:
- nested = symbol.type.nested
- return '{0}Model'.format(nested)
- return None
-
-
-def struct_includes(symbol):
- includesSet = set()
- tpl = '#include \"{0}.h\"'
- if isinstance(symbol, Struct):
- for val in symbol.fields:
- if val.type.is_struct:
- includesSet.add(tpl.format(val.type).lower())
- elif isinstance(symbol, Interface):
- for val in symbol.properties:
- if val.type.is_struct:
- includesSet.add(tpl.format(val.type).lower())
- for op in symbol.operations:
- for param in op.parameters:
- if param.type.is_struct:
- includesSet.add(tpl.format(param.type).lower())
- if op.type.is_struct:
- includesSet.add(tpl.format(op.type).lower())
- for op in symbol.signals:
- for param in op.parameters:
- if param.type.is_struct:
- includesSet.add(tpl.format(param.type).lower())
-
- return includesSet
-
-def comment_text(comment):
- """
- Returns the text of the passed comment without the leading/trailing comment tokens e.g. /**, *
- """
- comment_start = [ '/**', '/*!', '/*']
- processed = []
- isComment = False
-
- # No comment is NOT a error
- if len(comment) == 0:
- return processed
-
- for token in comment_start:
- if (comment.startswith(token)):
- isComment = True
- break;
- if isComment:
- comment = comment[3:-2]
- else:
- jinja_error("comment_text: The provided comment needs to be start with one of these strings: {}".format(comment_start))
+ for struct in module.structs:
+ for field in struct.fields:
+ validateType(srcFile, field.type, "Fields")
- for line in comment.splitlines():
- line = line.lstrip(" *")
- processed.append(line)
- return processed
-def generate(tplconfig, moduleConfig, annotations, src, dst):
+def generate(tplconfig, moduleConfig, annotations, imports, src, dst):
log.debug('run {0} {1}'.format(src, dst))
FileSystem.strict = True
Generator.strict = True
+
+ # First run without imports to know the name of the modules we want to generate
+ module_names = []
system = FileSystem.parse(src)
+ for module in system.modules:
+ module_names.append(module.name)
+
+ # Second run with imports to resolve all needed type information
+ all_files = imports + src
+ system = FileSystem.parse(all_files)
for annotations_file in annotations:
log.debug('{0}'.format(annotations_file))
if not os.path.isabs(annotations_file):
@@ -739,51 +113,24 @@ def generate(tplconfig, moduleConfig, annotations, src, dst):
print('no such annotation file: {0}'.format(annotations_file))
exit(1)
FileSystem.merge_annotations(system, Path(annotations_file))
- generator = Generator(search_path=[tplconfig, here])
-
- generator.env.keep_trailing_newline = True
- generator.register_filter('return_type', return_type)
- generator.register_filter('parameter_type_default', parameter_type_default)
- generator.register_filter('parameter_type', parameter_type)
- generator.register_filter('getter_name', getter_name)
- generator.register_filter('setter_name', setter_name)
- generator.register_filter('test_type_value', test_type_value)
- generator.register_filter('default_type_value', default_type_value)
- generator.register_filter('default_value', default_value)
- generator.register_filter('model_type', model_type)
- generator.register_filter('flag_type', flag_type)
- generator.register_filter('range_low', range_low)
- generator.register_filter('range_high', range_high)
- generator.register_filter('strip_QT', strip_QT)
- generator.register_filter('domain_values', domain_values)
- generator.register_filter("enum_value", enum_value)
- generator.register_filter("tag_by_path", tag_by_path)
- generator.register_filter("conf_sim_tag", conf_sim_tag)
- generator.register_filter('has_domains', has_domains)
- generator.register_filter('simulationData', simulationData)
- generator.register_filter('json_domain', json_domain)
- generator.register_filter('qml_info_type', qml_info_type)
- generator.register_filter('qml_type', qml_type)
- generator.register_filter('qml_control', qml_control)
- generator.register_filter('qml_binding_property', qml_binding_property)
- generator.register_filter('qml_control_signal_parameters', qml_control_signal_parameters)
- generator.register_filter('struct_includes', struct_includes)
- generator.register_filter('comment_text', comment_text)
-
- #Register global functions
- generator.env.globals["error"] = jinja_error
- generator.env.globals["warning"] = jinja_warning
srcFile = os.path.basename(src[0])
srcBase = os.path.splitext(srcFile)[0]
- global currentQFaceSrcFile
- currentQFaceSrcFile = src[0]
- ctx = {'dst': dst, 'qtASVersion': builtin_config["VERSION"], 'srcFile':srcFile, 'srcBase':srcBase, 'features': builtin_config["FEATURES"]}
- gen_config = yaml.load(open(os.path.dirname(tplconfig) + '/{0}.yaml'.format(os.path.basename(tplconfig))), Loader=yaml.SafeLoader)
+ ctx = {'qtASVersion': builtin_config.config["VERSION"], 'srcFile': srcFile, 'srcBase': srcBase}
+ generator = CustomRuleGenerator(search_path=[tplconfig, builtinTemplatesPath], destination=dst,
+ context=ctx, modules=module_names)
+ generator.env.keep_trailing_newline = True
+
+ register_global_functions(generator)
+ register_filters(generator)
- #Make sure the config tag is available for all our symbols
+ validateSystem(srcFile, system)
+
+ # Make sure the config tag is available for all our symbols
for module in system.modules:
module.add_tag('config')
+ for val, key in moduleConfig.items():
+ module.add_attribute('config', val, key)
for interface in module.interfaces:
interface.add_tag('config')
for property in interface.properties:
@@ -801,63 +148,48 @@ def generate(tplconfig, moduleConfig, annotations, src, dst):
for member in enum.members:
member.add_tag('config')
- for module in system.modules:
- log.debug('generate code for module %s', module)
- for val, key in moduleConfig.items():
- module.add_attribute('config', val, key)
- ctx.update({'module': module})
- # TODO: refine that, probably just use plain output folder
- dst = generator.apply('{{dst}}', ctx)
- generator.destination = dst
- module_rules = gen_config['generate_rules']['module_rules']
- force = moduleConfig['force']
- if module_rules is None: module_rules = []
- for rule in module_rules:
- preserve = rule['preserve'] if 'preserve' in rule else False
- generator.write(rule['dest_file'], rule['template_file'], ctx, preserve, force)
- for interface in module.interfaces:
- log.debug('generate backend code for interface %s', interface)
- ctx.update({'interface': interface})
- interface_rules = gen_config['generate_rules']['interface_rules']
- if interface_rules is None: interface_rules = []
- for rule in interface_rules:
- preserve = rule['preserve'] if 'preserve' in rule else False
- generator.write(rule['dest_file'], rule['template_file'], ctx, preserve, force)
- if 'struct_rules' in gen_config['generate_rules'] and isinstance(gen_config['generate_rules']['struct_rules'], list):
- for struct in module.structs:
- log.debug('generate code for struct %s', struct)
- ctx.update({'struct': struct})
- for rule in gen_config['generate_rules']['struct_rules']:
- preserve = rule['preserve'] if 'preserve' in rule else False
- generator.write(rule['dest_file'], rule['template_file'], ctx, preserve, force)
-
-
-def run(format, moduleConfig, annotations, src, dst):
- if format in IVI_DEFAULT_TEMPLATES:
- tplConfig = 'templates_{0}'.format(format)
- generate(here / tplConfig, moduleConfig, annotations, src, dst)
+ generator.process_rules(os.path.dirname(tplconfig) + '/{0}.yaml'.format(os.path.basename(tplconfig)), system)
+
+
+def run(format, moduleConfig, annotations, imports, src, dst):
+ templatePath = format
+ if format in builtinTemplates:
+ templatePath = builtinTemplatesPath / format
+
+ if os.path.exists(templatePath):
+ generate(templatePath, moduleConfig, annotations, imports, src, dst)
else:
- if os.path.exists(format):
- generate(format, moduleConfig, annotations, src, dst)
- else:
- print('Format "{0}" is invalid. Should be one of {1} or an existing template folder'.format(format, IVI_DEFAULT_TEMPLATES))
- exit(1)
+ print('Invalid Format: {0}. It either needs to be one of the builtin formats or an '
+ 'existing template folder. The following builtin formats are available: {1}'
+ .format(format, builtinTemplates))
+ exit(1)
@click.command()
-@click.option('--reload/--no-reload', default=False, help='Specifies whether the generator should keep track of the changes in the IDL file and update output on the fly (--no-reload by default).')
-@click.option('--format', '-f', multiple=False, help='The format the autogenerator should use for the generation. This can either be one of the builtin formats or a path to a template folder. Builtin formats are: \n' + '\n'.join(IVI_DEFAULT_TEMPLATES))
-@click.option('--module', default=False, help='The name of the Qt module the autogenerator is generating. This is automatically used by the qmake integration and passed directly to the qface templates.')
+@click.option('--reload/--no-reload', default=False, help=
+ 'Specifies whether the generator should keep track of the changes in the IDL file and update '
+ 'output on the fly (--no-reload by default).')
+@click.option('--format', '-f', multiple=False, help='The format the autogenerator should use for '
+ 'the generation. This can either be one of the builtin formats or a path to a template folder. '
+ 'Builtin formats are: \n' + '\n'.join(builtinTemplates))
+@click.option('--module', default=False, help='The name of the Qt module the autogenerator is '
+ 'generating. This is automatically used by the qmake integration and passed directly to the '
+ 'qface templates.')
@click.option('--force', is_flag=True, default=False, help='Always write all output files')
@click.option('--annotations', '-A', multiple=True, default=False, help=
'Merges the given annotation file with annotions already in the qface file and the '
'implicit annotation file. The annotation files will be merged in the order they are passed '
'to the generator. Providing a duplicate key in the YAML file will override the previously '
'set value. This option can be used multiple times.')
+@click.option('--import', '-I', 'imports' , multiple=True, default=False, help=
+ 'Adds the given path to the list of import paths. All directories in this list are '
+ 'scanned recursively for QFace files. The QFace files found are then used to resolve '
+ 'the information required when importing a module; this is similar to how C++ include '
+ 'paths work.')
@click.argument('src', nargs=-1, type=click.Path(exists=True))
@click.argument('dst', nargs=1, type=click.Path(exists=True))
-def app(src, dst, format, reload, module, force, annotations):
+def app(src, dst, format, reload, module, force, annotations, imports):
"""
The QtIvi Autogenerator (ivigenerator)
@@ -865,13 +197,8 @@ def app(src, dst, format, reload, module, force, annotations):
in the given dst directory.
"""
- global builtin_config
- builtin_config_path = here / '.config'
- if 'IVIGENERATOR_CONFIG' in os.environ:
- builtin_config_path = os.environ['IVIGENERATOR_CONFIG']
- builtin_config = yaml.load(open(builtin_config_path), Loader=yaml.SafeLoader)
- if not 'VERSION' in builtin_config or not 'FEATURES' in builtin_config:
- sys.exit("Invalid builtin config")
+ # Parse the .config file and throw an error in case it doesn't exist or it is invalid
+ builtin_config.parse(here)
if reload:
script = '{0} {1} {2}'.format(Path(__file__).abspath(), ' '.join(src), dst)
@@ -881,7 +208,7 @@ def app(src, dst, format, reload, module, force, annotations):
"module": module,
"force": force
}
- run(format, moduleConfig, annotations, src, dst)
+ run(format, moduleConfig, annotations, imports, src, dst)
if __name__ == '__main__':
diff --git a/src/tools/ivigenerator/generator/builtin_config.py b/src/tools/ivigenerator/generator/builtin_config.py
new file mode 100644
index 0000000..7e46094
--- /dev/null
+++ b/src/tools/ivigenerator/generator/builtin_config.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+# Copyright (C) 2019 The Qt Company Ltd.
+# Copyright (C) 2019 Luxoft Sweden AB
+# Copyright (C) 2018 Pelagicore AG
+# Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB)
+# 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
+
+import yaml
+import os
+import sys
+
+config = {}
+
+
+def parse(here):
+ global config
+ builtin_config_path = here / '.config'
+ if 'IVIGENERATOR_CONFIG' in os.environ:
+ builtin_config_path = os.environ['IVIGENERATOR_CONFIG']
+ config = yaml.load(open(builtin_config_path), Loader=yaml.SafeLoader)
+ if 'VERSION' not in config or 'FEATURES' not in config:
+ sys.exit("Invalid builtin config")
diff --git a/src/tools/ivigenerator/generator/filters.py b/src/tools/ivigenerator/generator/filters.py
new file mode 100644
index 0000000..737143c
--- /dev/null
+++ b/src/tools/ivigenerator/generator/filters.py
@@ -0,0 +1,734 @@
+#!/usr/bin/env python3
+# Copyright (C) 2019 The Qt Company Ltd.
+# Copyright (C) 2019 Luxoft Sweden AB
+# Copyright (C) 2018 Pelagicore AG
+# Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB)
+# 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
+
+import json
+
+from qface.idl.domain import Module, Interface, Property, Parameter, Field, Struct
+from qface.helper.generic import lower_first, upper_first
+from qface.helper.qtcpp import Filters
+
+from .global_functions import jinja_error, jinja_warning
+from . import builtin_config
+
+
+def tag_by_path(symbol, path, default_value=False):
+ """
+ Find the tag given by its full path in the object hierarchy,
+ like "property.config_sim.zones.right". If some part of the
+ path is missing, return None
+ """
+ path_parts = path.split(".")
+ cur_level_obj = symbol.tags
+ for path_part in path_parts:
+ if path_part in cur_level_obj:
+ cur_level_obj = cur_level_obj[path_part]
+ else:
+ cur_level_obj = None
+ break
+ if cur_level_obj is None:
+ cur_level_obj = default_value
+ return cur_level_obj
+
+
+def conf_sim_tag(symbol, path, default_value=False):
+ """
+ Find tag, given by its path, located under "config_simulator" sub-object.
+ Returns None, of any of the path parts is missing
+ """
+ return tag_by_path(symbol, "config_simulator." + path, default_value)
+
+
+def enum_value_to_cppliteral(value, module_name):
+ value = value.strip().rsplit('.', 1)[-1]
+ return '{0}{1}Module::{2}'.format(Filters.classPrefix, upper_first(module_name), value)
+
+
+def enum_value(value, module_name):
+ sub_values = value.split('|')
+ sub_values = [enum_value_to_cppliteral(v, module_name) for v in sub_values]
+ return "|".join(sub_values)
+
+
+def default_type_value(symbol):
+ """
+ Find the default value for the type. Models are initialized as nullptr
+ """
+ prefix = Filters.classPrefix
+ t = symbol.type
+ if t.is_primitive:
+ if t.is_int:
+ return 'int(0)'
+ if t.is_bool:
+ return 'bool(false)'
+ if t.is_string:
+ return 'QString()'
+ if t.is_real:
+ return 'qreal(0.0)'
+ if t.is_var:
+ return 'QVariant()'
+ elif t.is_void:
+ return ''
+ elif t.is_enum:
+ module_name = t.reference.module.module_name
+ value = next(iter(t.reference.members))
+ return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
+ elif t.is_flag:
+ module_name = t.reference.module.module_name
+ return '{0}{1}Module::{2}()'.format(prefix, upper_first(module_name), flag_type(symbol))
+ elif symbol.type.is_list:
+ nested = Filters.returnType(symbol.type.nested)
+ return 'QVariantList()'.format(nested)
+ elif symbol.type.is_struct:
+ return '{0}{1}()'.format(prefix, symbol.type.reference.name)
+ elif symbol.type.is_model:
+ return 'nullptr'
+ jinja_error('default_type_value: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
+
+
+def test_type_value(symbol):
+ """
+ Find a value different than the default value for the type. Models are initialized as nullptr
+ """
+ prefix = Filters.classPrefix
+ t = symbol.type
+ if t.is_primitive:
+ if t.is_int:
+ return '111'
+ if t.is_bool:
+ return 'true'
+ if t.is_string:
+ return 'QStringLiteral("TEST STRING")'
+ if t.is_real:
+ return '1234.5678'
+ if t.is_var:
+ return 'QVariant("TEST VARIANT")'
+ elif t.is_void:
+ return ''
+ elif t.is_enum:
+ module_name = t.reference.module.module_name
+ value = list(iter(t.reference.members))[-1]
+ return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
+ elif t.is_flag:
+ module_name = t.reference.module.module_name
+ value = next(iter(t.reference.members))
+ return '{0}{1}Module::{2}'.format(prefix, upper_first(module_name), value)
+ elif symbol.type.is_list:
+ value = test_type_value(t.nested.type)
+ if not (t.nested.type.is_primitive):
+ value = 'QVariant::fromValue({0})'.format(value)
+ return 'QVariantList({{{0}}})'.format(value)
+ elif symbol.type.is_struct:
+ values_string = ', '.join(test_type_value(e) for e in symbol.type.reference.fields)
+ return '{0}{1}({2})'.format(prefix, symbol.type.reference.name, values_string)
+ elif symbol.type.is_model:
+ return 'new QIviPagingModel()'
+ jinja_error('test_type_value: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
+
+
+def default_value_helper(symbol, res):
+ t = symbol.type
+ if t.is_struct:
+ if not (isinstance(res, dict) or isinstance(res, list)):
+ jinja_error('default_value: value in annotation is supposed to be a dict or list')
+ if len(res) != len(t.reference.fields):
+ jinja_error('default_value: argument count in annotation and number of struct fields '
+ 'does not match')
+ values = []
+ for idx, property in enumerate(res):
+ values.append(default_value_helper(list(t.reference.fields)[idx], property))
+ return '{0}({{{1}}})'.format(t.type, ', '.join(values))
+ if t.is_model or t.is_list:
+ if not isinstance(res, list):
+ jinja_error('default_value: value in annotation is supposed to be a list')
+ row_string = ''
+ if t.nested.is_struct and t.is_list:
+ row_string = ', '.join(('QVariant::fromValue({0})'.format(default_value_helper(t.nested, row))) for row in res)
+ else:
+ row_string = ', '.join(default_value_helper(t.nested, row) for row in res)
+ return '{{{0}}}'.format(row_string)
+ if t.is_enum or t.is_flag:
+ module_name = t.reference.module.module_name
+ return enum_value(res, module_name)
+ # in case it's bool, Python True is sent to the C++ as "True", let's take care of that
+ if t.is_bool:
+ if res:
+ return 'true'
+ else:
+ return 'false'
+ if t.is_string:
+ return 'QStringLiteral("{0}")'.format(res.replace("\\", "\\\\"))
+ if t.is_var:
+ if isinstance(res, str):
+ res = 'QStringLiteral("{0}")'.format(res)
+ return 'QVariant({0})'.format(res)
+
+ return '{0}'.format(res)
+
+
+def default_value(symbol, zone='='):
+ """
+ Find the default value used by the simulator backend
+ """
+ res = default_type_value(symbol)
+ if symbol.type.is_model:
+ res = '{}'
+ if 'config_simulator' in symbol.tags and 'default' in symbol.tags['config_simulator']:
+ res = symbol.tags['config_simulator']['default']
+ if isinstance(res, dict):
+ if zone in res:
+ res = res[zone]
+ elif '=' in res:
+ res = res['=']
+ return default_value_helper(symbol, res)
+
+ return res
+
+
+def parameter_type_default(symbol):
+ """
+ Return the parameter declaration for properties, handle camel case module name
+ """
+ prefix = Filters.classPrefix
+ if symbol.type.is_enum or symbol.type.is_flag:
+ return '{0}{1}Module::{2} {3}={4}'.format(prefix, upper_first(symbol.type.reference.module.module_name), flag_type(symbol), symbol, default_type_value(symbol))
+ if symbol.type.is_void or symbol.type.is_primitive:
+ if symbol.type.name == 'string':
+ return 'const QString &{0}=QString()'.format(symbol)
+ if symbol.type.name == 'var':
+ return 'const QVariant &{0}=QVariant()'.format(symbol)
+ if symbol.type.name == 'real':
+ return 'qreal {0}=qreal()'.format(symbol)
+ return '{0} {1}={2}'.format(symbol.type, symbol, default_type_value(symbol))
+ elif symbol.type.is_list:
+ nested = return_type(symbol.type.nested)
+ return 'const QVariantList &{1}=QVariantList()'.format(nested, symbol)
+ elif symbol.type.is_model:
+ nested = symbol.type.nested
+ if nested.is_primitive:
+ return '{0}VariantModel *{1}=QVariantModel'.format(prefix, symbol)
+ elif nested.is_complex:
+ return 'QIviPagingModel *{0}=nullptr'.format(symbol)
+ else:
+ return 'const {0}{1} &{2}={0}{1}()'.format(prefix, symbol.type.reference.name, symbol)
+ jinja_error('parameter_type_default: Unknown parameter {0} of type {1}'.format(symbol,
+ symbol.type))
+
+
+def parameter_type(symbol):
+ """
+ Return the parameter declaration for properties, handle camel case module name
+ """
+ prefix = Filters.classPrefix
+ if symbol.type.is_enum or symbol.type.is_flag:
+ return '{0}{1}Module::{2} {3}'.format(prefix, upper_first(symbol.type.reference.module.module_name), flag_type(symbol), symbol)
+ if symbol.type.is_void or symbol.type.is_primitive:
+ if symbol.type.name == 'string':
+ return 'const QString &{0}'.format(symbol)
+ if symbol.type.name == 'var':
+ return 'const QVariant &{0}'.format(symbol)
+ if symbol.type.name == 'real':
+ return 'qreal {0}'.format(symbol)
+ return '{0} {1}'.format(symbol.type, symbol)
+ elif symbol.type.is_list:
+ nested = return_type(symbol.type.nested)
+ return 'const QVariantList &{1}'.format(nested, symbol)
+ elif symbol.type.is_model:
+ nested = symbol.type.nested
+ if nested.is_primitive:
+ return '{0}VariantModel *{1}'.format(prefix, symbol)
+ elif nested.is_complex:
+ return 'QIviPagingModel *{0}'.format(symbol)
+ else:
+ return 'const {0}{1} &{2}'.format(prefix, symbol.type.reference.name, symbol)
+ jinja_error('parameter_type: Unknown parameter {0} of type {1}'.format(symbol, symbol.type))
+
+
+def return_type(symbol):
+ """
+ Return the type declaration for properties, handle camel case module name
+ """
+ prefix = Filters.classPrefix
+ if symbol.type.is_enum or symbol.type.is_flag:
+ return('{0}{1}Module::{2}'.format(prefix,
+ upper_first(symbol.type.reference.module.module_name),
+ flag_type(symbol)))
+ if symbol.type.is_void or symbol.type.is_primitive:
+ if symbol.type.name == 'string':
+ return 'QString'
+ if symbol.type.name == 'var':
+ return 'QVariant'
+ if symbol.type.name == 'real':
+ return 'qreal'
+ return symbol.type.name
+ elif symbol.type.is_list:
+ nested = return_type(symbol.type.nested)
+ return 'QVariantList'.format(nested)
+ elif symbol.type.is_model:
+ nested = symbol.type.nested
+ if nested.is_primitive:
+ return '{0}VariantModel *'.format(prefix)
+ elif nested.is_complex:
+ return 'QIviPagingModel *'
+ else:
+ return '{0}{1}'.format(prefix, symbol.type.reference.name)
+ jinja_error('return_type: Unknown symbol {0} of type {1}'.format(symbol, symbol.type))
+
+
+def flag_type(symbol):
+ """
+ Return the annotation for the flag type if available, the plural otherwise
+ """
+ actualType = symbol
+ if symbol.type.reference:
+ actualType = symbol.type.reference
+ if actualType.is_flag:
+ if 'config' in actualType.tags and 'type' in actualType.tags['config']:
+ return actualType.tags['config']['type']
+ return '{0}s'.format(actualType)
+ return actualType
+
+
+def domain_values(symbol):
+ """
+ Returns domain values for property (if defined by @domain)
+ """
+ if type(symbol) is Property:
+ if 'config_simulator' in symbol.tags:
+ if 'domain' in symbol.tags['config_simulator']:
+ return symbol.tags['config_simulator']['domain']
+ return None
+
+
+def getter_name(symbol):
+ """
+ Returns the getter name of the property
+ """
+ if type(symbol) is Property:
+ if 'config' in symbol.tags and 'getter_name' in symbol.tags['config']:
+ return symbol.tags['config']['getter_name']
+ return symbol
+
+
+def setter_name(symbol):
+ """
+ Returns the setter name of the property
+ """
+ if type(symbol) is Property:
+ if 'config' in symbol.tags and 'setter_name' in symbol.tags['config']:
+ return symbol.tags['config']['setter_name']
+ return 'set' + symbol.name[0].upper() + symbol.name[1:]
+
+
+def range_value(symbol, index, key):
+ """
+ Returns value for property (if defined by @range index or key)
+ """
+ if type(symbol) is Property and symbol.type.is_int or symbol.type.is_real:
+ if 'config_simulator' in symbol.tags:
+ if 'range' in symbol.tags['config_simulator']:
+ return symbol.tags['config_simulator']['range'][index]
+ if key in symbol.tags['config_simulator']:
+ return symbol.tags['config_simulator'][key]
+ return None
+
+
+def range_high(symbol):
+ """
+ Returns maximum value for property (if defined by @range or @maximum)
+ """
+ return range_value(symbol, 1, 'maximum')
+
+
+def range_low(symbol):
+ """
+ Returns minimum value for property (if defined by @range or @minimum)
+ """
+ return range_value(symbol, 0, 'minimum')
+
+
+def has_domains(properties):
+ """
+ Returns true if any property has range or domain tags
+ """
+ for property in properties:
+ if 'config_simulator' in property.tags:
+ for p in ['range', 'domain', 'minimum', 'maximum']:
+ if p in property.tags['config_simulator']:
+ return True
+ return False
+
+
+def strip_QT(s):
+ """
+ If the given string starts with QT, stip it away.
+ """
+ s = str(s)
+ if s.startswith('QT'):
+ return s[2:]
+ return s
+
+
+def json_domain(properties):
+ """
+ Returns property domains formated in json
+ """
+ data = {}
+ if len(properties):
+ data["iviVersion"] = builtin_config.config["VERSION"]
+ for property in properties:
+ if 'config_simulator' in property.tags:
+ for p in ['range', 'domain', 'minimum', 'maximum']:
+ if (property.tags['config_simulator'] is not None
+ and p in property.tags['config_simulator']):
+ if property.name not in data:
+ data[property.name] = {}
+ data[property.name][p] = property.tags['config_simulator'][p]
+ return json.dumps(data, separators=(',', ':'))
+
+
+def simulationData(module):
+ data = {}
+ for interface in module.interfaces:
+ iData = {}
+ if 'config_simulator' in interface.tags:
+ iData = interface.tags['config_simulator']
+ for property in interface.properties:
+ if 'config_simulator' in property.tags:
+ for p in ['range', 'domain', 'minimum', 'maximum', 'default']:
+ if (property.tags['config_simulator'] is not None
+ and p in property.tags['config_simulator']):
+ if property.name not in iData:
+ iData[property.name] = {}
+ iData[property.name][p] = symbolToJson(property.tags['config_simulator'][p],
+ property.type)
+ data[interface.name] = iData
+ return json.dumps(data, indent=' ')
+
+
+def symbolToJson(data, symbol):
+ if symbol.type.is_struct:
+ t = symbol.type
+ if not (isinstance(data, dict) or isinstance(data, list)):
+ jinja_error('simulationData: value in annotation is supposed to be a dict or list')
+ if len(data) != len(t.reference.fields):
+ jinja_error('simulationData: argument count in annotation and number of struct fields '
+ 'does not match')
+ newList = list(symbolToJson(property, list(t.reference.fields)[idx]) for idx, property in enumerate(data))
+ return {"type": symbol.type.name, "value": newList}
+ elif symbol.type.is_enum or symbol.type.is_flag:
+ module_name = symbol.type.reference.module.module_name
+ return {"type": "enum", "value": enum_value(data, module_name)}
+ elif symbol.type.is_list or symbol.type.is_model:
+ nested = symbol.type.nested
+ if nested.is_complex:
+ newList = []
+ for value in data:
+ newList.append(symbolToJson(value, nested))
+ return newList
+ return data
+
+
+def qml_control_properties(symbol, backend_object):
+ """
+ Returns properties of the QML control matching to this
+ IDL type (e.g. min/max properties)
+ """
+ prop_str = lower_first(symbol) + "Control"
+ if isinstance(symbol, Property):
+ top = range_high(symbol)
+ bottom = range_low(symbol)
+ binding = "value: {0}.{1};".format(backend_object, symbol.name)
+ if top is not None and bottom is not None:
+ return 'id: {0}; from: {1}; to: {2}; {3}'.format(prop_str, bottom, top, binding)
+
+ if top is not None or bottom is not None:
+ if top is None:
+ return 'id: {0}; from: {1}; to:100000; {2}'.format(prop_str, bottom, binding)
+ elif bottom is None:
+ return 'id: {0}; from:-100000; to: {1}; {2}'.format(prop_str, top, binding)
+
+ values = domain_values(symbol)
+ if values is None and (symbol.type.is_enum or symbol.type.is_flag):
+ values_string = ' '.join('ListElement {{ key: "{0}"; value: {1}.{0} }}'.format(e, qml_type(symbol.interface)) for e in symbol.type.reference.members)
+ return 'id: {0}; textRole: "key"; {2} model: ListModel {{ {1} }}'.format(prop_str,
+ values_string,
+ binding)
+ if values is not None:
+ values_string = ','.join('"'+str(e)+'"' for e in values)
+ return 'id: {0}; model: [ {1} ]; '.format(prop_str, values_string)
+ if symbol.type.is_bool:
+ binding = "checked: {0}.{1};".format(backend_object, symbol.name)
+ return 'id: {0}; {1}'.format(prop_str, binding)
+ if symbol.type.is_real or symbol.type.is_int or symbol.type.is_string:
+ binding = "text: {0}.{1};".format(backend_object, symbol.name)
+ return 'id: {0}; {1}'.format(prop_str, binding)
+
+ if isinstance(symbol, Parameter):
+ return 'id: {1}Param{0}'.format(prop_str, symbol.operation)
+ if isinstance(symbol, Field):
+ return 'id: {1}_{0}'.format(prop_str, lower_first(symbol.struct))
+
+
+def qml_control_signal_parameters(symbol):
+ """
+ Returns the parameters for calling the signal using the values from the ui controls
+ """
+ return ', '.join('{0}Param{1}Control.{2}'.format(e.operation, lower_first(e),qml_binding_property(e)) for e in symbol.parameters)
+
+
+def qml_meta_control_name(symbol):
+ """
+ Returns name of the QML control needed to display this type based on the meta
+ data of the symbol -- if symbol has some meta data (e.g. value limits or domain)
+ then control name is taken based on these constraints. Otherwise returns None.
+ """
+ top = range_high(symbol)
+ bottom = range_low(symbol)
+ if top is not None and bottom is not None:
+ return 'Slider'
+
+ if top is not None or bottom is not None:
+ return 'SpinBox'
+
+ values = domain_values(symbol)
+ if values is not None:
+ return "ComboBox"
+
+
+def qml_type_control_name(symbol):
+ """
+ Returns name of the QML control inferred based on the type of the symbol.
+ """
+ t = symbol.type
+ if t.is_string or t.is_int or t.is_real:
+ return "TextField"
+ elif t.is_bool:
+ return "CheckBox"
+ elif t.is_enum:
+ if t.reference.is_enum:
+ return "EnumControl"
+ elif t.reference.is_flag:
+ return "FlagControl"
+ elif t.is_flag:
+ return "FlagControl"
+ return "TextField"
+
+
+def qml_control_name(symbol):
+ """
+ Returns name of the QML control for the symbol. First it checks meta data (as it may
+ influence the control type) and if nothing is defined there, it falls back to the
+ symbol actual type.
+ """
+ # First try to calculate control name based on the tags
+ control_name = qml_meta_control_name(symbol)
+ # If nothing is defined, calculate it based on its type
+ if control_name is None:
+ control_name = qml_type_control_name(symbol)
+ return control_name
+
+
+def qml_control(symbol, backend_object):
+ """
+ Returns QML code for the control (or group of controls) to represent the editing UI for the
+ symbol.
+ """
+
+ if symbol.type.is_struct:
+ return qml_struct_control(symbol)
+
+ return "{0} {{ {1} }}".format(qml_control_name(symbol),
+ qml_control_properties(symbol, backend_object))
+
+
+def qml_binding_property(symbol):
+ """
+ :param symbol: property which is being bound by the control
+ :return: name of the property of the QML control to be bound with
+ """
+ control_name = qml_control_name(symbol)
+ if control_name == "CheckBox":
+ return "checked"
+ elif (control_name == "Slider" or control_name == "SpinBox" or control_name == "FlagControl"
+ or control_name == "EnumControl"):
+ return "value"
+ elif control_name == "TextField":
+ return "text"
+ elif control_name == "ComboBox":
+ return "currentIndex"
+
+
+def qml_struct_control(symbol):
+ if symbol.type.is_struct and symbol.type.reference.fields:
+ result = "Rectangle { ColumnLayout { "
+ for field in symbol.type.reference.fields:
+ result += qml_control(field)
+ result += "}}"
+ return result
+
+
+def qml_info_type(symbol):
+ """
+ Returns the correct type for the symbol, to be used inside the qmltype templates
+ """
+ prefix = Filters.classPrefix
+ if symbol.type.is_enum or symbol.type.is_flag:
+ return('{0}{1}Module::{2}'.format(prefix, upper_first(symbol.module.module_name),
+ flag_type(symbol)))
+ elif symbol.type.is_void or symbol.type.is_primitive:
+ if symbol.type.is_real:
+ return 'double'
+ return symbol.type.name
+ elif symbol.type.is_struct:
+ return 'QVariant'
+ elif symbol.type.is_list:
+ return 'QVariantList'
+ elif symbol.type.is_model:
+ return 'QIviPagingModel'
+ else:
+ jinja_error('qml_info_type: Unknown symbol {0} of type {1}'.format(symbol, symbol.type))
+
+
+def qml_type(symbol):
+ """
+ :param interface:
+ :return: Returns the name of the interface for using in QML. This name is defined in the IDL
+ under the "config" tag as "qml_type". This annotation is optional, if not provided, the
+ interface name is used.
+ """
+ result = symbol.name
+ if 'qml_type' in symbol.tags['config']:
+ result = symbol.tags['config']['qml_type']
+ elif 'qml_name' in symbol.tags['config']:
+ result = symbol.tags['config']['qml_name']
+ return result
+
+
+def model_type(symbol):
+ if symbol.type.is_model:
+ nested = symbol.type.nested
+ return '{0}Model'.format(nested)
+ return None
+
+
+def struct_includes(symbol):
+ includesSet = set()
+ tpl = '#include \"{0}.h\"'
+
+ if isinstance(symbol, Struct):
+ for val in symbol.fields:
+ if val.type.is_struct:
+ includesSet.add(tpl.format(val.type.reference.name).lower())
+ elif isinstance(symbol, Interface):
+ for val in symbol.properties:
+ if val.type.is_struct:
+ includesSet.add(tpl.format(val.type.reference.name).lower())
+ for op in symbol.operations:
+ for param in op.parameters:
+ if param.type.is_struct:
+ includesSet.add(tpl.format(param.type.reference.name).lower())
+ if op.type.is_struct:
+ includesSet.add(tpl.format(op.type.reference.name).lower())
+ for op in symbol.signals:
+ for param in op.parameters:
+ if param.type.is_struct:
+ includesSet.add(tpl.format(param.type.reference.name).lower())
+
+ return includesSet
+
+
+def comment_text(comment):
+ """
+ Returns the text of the passed comment without the leading/trailing comment tokens e.g. /**, *
+ """
+ comment_start = ['/**', '/*!', '/*']
+ processed = []
+ isComment = False
+
+ # No comment is NOT a error
+ if len(comment) == 0:
+ return processed
+
+ for token in comment_start:
+ if (comment.startswith(token)):
+ isComment = True
+ break
+ if isComment:
+ comment = comment[3:-2]
+ else:
+ jinja_error("comment_text: The provided comment needs to be start with one of these "
+ "strings: {}".format(comment_start))
+
+ for line in comment.splitlines():
+ line = line.lstrip(" *")
+ processed.append(line)
+ return processed
+
+
+def register_filters(generator):
+ generator.env.keep_trailing_newline = True
+ generator.register_filter('return_type', return_type)
+ generator.register_filter('parameter_type_default', parameter_type_default)
+ generator.register_filter('parameter_type', parameter_type)
+ generator.register_filter('getter_name', getter_name)
+ generator.register_filter('setter_name', setter_name)
+ generator.register_filter('test_type_value', test_type_value)
+ generator.register_filter('default_type_value', default_type_value)
+ generator.register_filter('default_value', default_value)
+ generator.register_filter('model_type', model_type)
+ generator.register_filter('flag_type', flag_type)
+ generator.register_filter('range_low', range_low)
+ generator.register_filter('range_high', range_high)
+ generator.register_filter('strip_QT', strip_QT)
+ generator.register_filter('domain_values', domain_values)
+ generator.register_filter("enum_value", enum_value)
+ generator.register_filter("tag_by_path", tag_by_path)
+ generator.register_filter("conf_sim_tag", conf_sim_tag)
+ generator.register_filter('has_domains', has_domains)
+ generator.register_filter('simulationData', simulationData)
+ generator.register_filter('json_domain', json_domain)
+ generator.register_filter('qml_info_type', qml_info_type)
+ generator.register_filter('qml_type', qml_type)
+ generator.register_filter('qml_control', qml_control)
+ generator.register_filter('qml_binding_property', qml_binding_property)
+ generator.register_filter('qml_control_signal_parameters', qml_control_signal_parameters)
+ generator.register_filter('struct_includes', struct_includes)
+ generator.register_filter('comment_text', comment_text)
diff --git a/src/tools/ivigenerator/generator/global_functions.py b/src/tools/ivigenerator/generator/global_functions.py
new file mode 100644
index 0000000..69c60e5
--- /dev/null
+++ b/src/tools/ivigenerator/generator/global_functions.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+# Copyright (C) 2019 The Qt Company Ltd.
+# Copyright (C) 2019 Luxoft Sweden AB
+# Copyright (C) 2018 Pelagicore AG
+# Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB)
+# 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
+
+import inspect
+import click
+
+from jinja2 import TemplateAssertionError
+from jinja2 import contextfunction
+
+
+def jinjaTrace():
+ """
+ Collects all jinja template files and the line numbers from the current calltrace
+ """
+ frame = inspect.currentframe()
+ infos = []
+ while frame:
+ template = frame.f_globals.get('__jinja_template__')
+ if template is not None:
+ infos.append((inspect.getsourcefile(frame),
+ template.get_corresponding_lineno(frame.f_lineno)))
+ frame = frame.f_back
+ return infos
+
+
+@contextfunction
+def jinja_error(context, msg):
+ """
+ Throws an error for the current jinja template and the templates this is included from
+ This can be used inside a filter to indicate problems with the passed arguments or direclty
+ inside an template
+ """
+ infos = jinjaTrace()
+ if len(infos):
+ message = msg
+ if len(infos) > 1:
+ for info in infos[1:]:
+ message = message + "\n{0}:{1}: instantiated from here".format(info[0], info[1])
+ message = message + "\n{0}: instantiated from here".format(context["srcFile"])
+ raise TemplateAssertionError(message, infos[0][1], "", infos[0][0])
+ raise TemplateAssertionError(msg, -1, "", "unknown")
+
+
+def jinja_warning(msg):
+ """
+ Reports an warning in the current jinja template.
+ This can be used inside a filter to indicate problems with the passed arguments or direclty
+ inside an template
+ """
+ file, lineno = jinjaTrace()[0]
+ if file:
+ message = '{0}:{1}: warning: {2}'.format(file, lineno, msg)
+ else:
+ message = '<unknown-file>: warning: {0}'.format(msg)
+ click.secho(message, fg='yellow', err=True)
+
+
+def register_global_functions(generator):
+ generator.env.globals["error"] = jinja_error
+ generator.env.globals["warning"] = jinja_warning
diff --git a/src/tools/ivigenerator/generator/rule_generator.py b/src/tools/ivigenerator/generator/rule_generator.py
new file mode 100644
index 0000000..ab14531
--- /dev/null
+++ b/src/tools/ivigenerator/generator/rule_generator.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+# Copyright (C) 2019 The Qt Company Ltd.
+# 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
+
+import click
+import logging.config
+import sys
+import yaml
+from path import Path
+
+from qface.generator import RuleGenerator
+from qface.idl.domain import Module, Interface, Property, Parameter, Field, Struct
+
+log = logging.getLogger(__file__)
+
+
+class CustomRuleGenerator(RuleGenerator):
+ """Extended RuleGenerator to only generate the wanted modules instead of all"""
+
+ def __init__(self, search_path: str, destination: Path, modules: [], context: dict = {},
+ features: set = set(), force=False):
+ super().__init__(search_path, destination, context, features, force)
+ self.module_names = modules
+
+ def process_rules(self, path: Path, system):
+ gen_config = yaml.load(open(path), Loader=yaml.SafeLoader)
+ if 'generate_rules' in gen_config:
+ self._process_legacy(gen_config, system)
+ else:
+ super().process_rules(path, system)
+
+ def _process_rules(self, rules: dict, system):
+ self._source = None # reset the template source
+ if not self._shall_proceed(rules):
+ return
+ self.context.update(rules.get('context', {}))
+ self.path = rules.get('path', '')
+ self.source = rules.get('source', None)
+ self._process_rule(rules.get('system', None), {'system': system})
+ for module in system.modules:
+ # Only generate files for the modules detected from the first parse run
+ if module.name not in self.module_names:
+ continue
+
+ log.debug('generate code for module %s', module)
+
+ # Report early if we cannot find the imported modules
+ for imp in module._importMap:
+ if imp not in system._moduleMap:
+ sys.exit("Couldn't resolve import '{0}'".format(imp))
+
+ self._process_rule(rules.get('module', None), {'module': module})
+ for interface in module.interfaces:
+ self._process_rule(rules.get('interface', None), {'interface': interface})
+ for struct in module.structs:
+ self._process_rule(rules.get('struct', None), {'struct': struct})
+ for enum in module.enums:
+ self._process_rule(rules.get('enum', None), {'enum': enum})
+
+ def _process_legacy(self, gen_config, system):
+
+ click.secho('Using the legacy Generation YAML Parser. Please consider porting to the new '
+ 'Rule based Generation provided by QFace 2.0', fg='yellow')
+
+ for module in system.modules:
+ # Only generate files for the modules detected from the first parse run
+ if module.name not in self.module_names:
+ continue
+
+ log.debug('generate code for module %s', module)
+
+ # Report early if we cannot find the imported modules
+ for imp in module._importMap:
+ if imp not in system._moduleMap:
+ sys.exit("Couldn't resolve import '{0}'".format(imp))
+
+ self.context.update({'module': module})
+ dst = self.apply('{{dst}}', self.context)
+ self.destination = dst
+ module_rules = gen_config['generate_rules']['module_rules']
+ force = True # moduleConfig['force']
+ if module_rules is None:
+ module_rules = []
+
+ for rule in module_rules:
+ preserve = rule['preserve'] if 'preserve' in rule else False
+ self.write(rule['dest_file'], rule['template_file'], self.context, preserve, force)
+ for interface in module.interfaces:
+ log.debug('generate backend code for interface %s', interface)
+ self.context.update({'interface': interface})
+ interface_rules = gen_config['generate_rules']['interface_rules']
+ if interface_rules is None:
+ interface_rules = []
+ for rule in interface_rules:
+ preserve = rule['preserve'] if 'preserve' in rule else False
+ self.write(rule['dest_file'], rule['template_file'], self.context, preserve,
+ force)
+ if ('struct_rules' in gen_config['generate_rules']
+ and isinstance(gen_config['generate_rules']['struct_rules'], list)):
+ for struct in module.structs:
+ log.debug('generate code for struct %s', struct)
+ self.context.update({'struct': struct})
+ for rule in gen_config['generate_rules']['struct_rules']:
+ preserve = rule['preserve'] if 'preserve' in rule else False
+ self.write(rule['dest_file'], rule['template_file'], ctx, preserve, force)
diff --git a/src/tools/ivigenerator/ivigenerator.pro b/src/tools/ivigenerator/ivigenerator.pro
index 59784d4..ae1a748 100644
--- a/src/tools/ivigenerator/ivigenerator.pro
+++ b/src/tools/ivigenerator/ivigenerator.pro
@@ -12,102 +12,110 @@ QT_FOR_CONFIG += ivicore
CONFIG -= debug_and_release
common.files += \
- common/generated_comment.cpp.tpl \
- common/qtivi_macros.j2 \
- common/simulation.qmltypes.tpl \
- common/plugins.qmltypes.tpl \
- common/qmldir.tpl \
- common/interface.rep.tpl \
- common/pagingmodel.rep.tpl \
- common/simulation_data.json.tpl \
- common/simulation.qrc.tpl \
- common/module_simulation.qml.tpl \
- common/backend_simulation.cpp.tpl \
- common/backend_simulation.h.tpl \
- common/backend_simulation.qml.tpl \
- common/pagingmodel_simulation.h.tpl \
- common/pagingmodel_simulation.cpp.tpl
-common.path = $$[QT_HOST_BINS]/ivigenerator/common
+ templates/common/generated_comment.cpp.tpl \
+ templates/common/qtivi_macros.j2 \
+ templates/common/simulation.qmltypes.tpl \
+ templates/common/plugins.qmltypes.tpl \
+ templates/common/qmldir.tpl \
+ templates/common/interface.rep.tpl \
+ templates/common/simulation_data.json.tpl \
+ templates/common/simulation.qrc.tpl \
+ templates/common/module_simulation.qml.tpl \
+ templates/common/backend_simulation.cpp.tpl \
+ templates/common/backend_simulation.h.tpl \
+ templates/common/backend_simulation.qml.tpl \
+ templates/common/pagingmodel_simulation.h.tpl \
+ templates/common/pagingmodel_simulation.cpp.tpl
+common.path = $$[QT_HOST_BINS]/ivigenerator/templates/common
templates_frontend.files += \
- templates_frontend/backendinterface.cpp.tpl \
- templates_frontend/backendinterface.h.tpl \
- templates_frontend/global.h.tpl \
- templates_frontend/interface.cpp.tpl \
- templates_frontend/interface.h.tpl \
- templates_frontend/interface_p.h.tpl \
- templates_frontend/module.cpp.tpl \
- templates_frontend/module.h.tpl \
- templates_frontend/module_qml_enum.qdocinc.tpl \
- templates_frontend/module.pri.tpl \
- templates_frontend/modulefactory.cpp.tpl \
- templates_frontend/modulefactory.h.tpl \
- templates_frontend/struct.cpp.tpl \
- templates_frontend/struct.h.tpl
-templates_frontend.path = $$[QT_HOST_BINS]/ivigenerator/templates_frontend
+ templates/frontend/backendinterface.cpp.tpl \
+ templates/frontend/backendinterface.h.tpl \
+ templates/frontend/global.h.tpl \
+ templates/frontend/interface.cpp.tpl \
+ templates/frontend/interface.h.tpl \
+ templates/frontend/interface_p.h.tpl \
+ templates/frontend/module.cpp.tpl \
+ templates/frontend/module.h.tpl \
+ templates/frontend/module_qml_enum.qdocinc.tpl \
+ templates/frontend/module.pri.tpl \
+ templates/frontend/modulefactory.cpp.tpl \
+ templates/frontend/modulefactory.h.tpl \
+ templates/frontend/struct.cpp.tpl \
+ templates/frontend/struct.h.tpl
+templates_frontend.path = $$[QT_HOST_BINS]/ivigenerator/templates/frontend
templates_qmlplugin.files += \
- templates_qmlplugin/module.pri.tpl \
- templates_qmlplugin/plugin.cpp.tpl \
- templates_qmlplugin/qmldir_plugin.tpl
-templates_qmlplugin.path = $$[QT_HOST_BINS]/ivigenerator/templates_qmlplugin
+ templates/qmlplugin/module.pri.tpl \
+ templates/qmlplugin/plugin.cpp.tpl \
+ templates/qmlplugin/qmldir_plugin.tpl
+templates_qmlplugin.path = $$[QT_HOST_BINS]/ivigenerator/templates/qmlplugin
templates_backend_simulator.files += \
- templates_backend_simulator/plugin.cpp.tpl \
- templates_backend_simulator/plugin.h.tpl \
- templates_backend_simulator/plugin.json \
- templates_backend_simulator/plugin.pri.tpl \
- templates_backend_simulator/plugin.pro
-templates_backend_simulator.path = $$[QT_HOST_BINS]/ivigenerator/templates_backend_simulator
+ templates/backend_simulator/plugin.cpp.tpl \
+ templates/backend_simulator/plugin.h.tpl \
+ templates/backend_simulator/plugin.json \
+ templates/backend_simulator/plugin.pri.tpl \
+ templates/backend_simulator/plugin.pro
+templates_backend_simulator.path = $$[QT_HOST_BINS]/ivigenerator/templates/backend_simulator
templates_backend_qtro.files += \
- templates_backend_qtro/backend.cpp.tpl \
- templates_backend_qtro/backend.h.tpl \
- templates_backend_qtro/pagingmodel.h.tpl \
- templates_backend_qtro/pagingmodel.cpp.tpl \
- templates_backend_qtro/plugin.cpp.tpl \
- templates_backend_qtro/plugin.h.tpl \
- templates_backend_qtro/plugin.json \
- templates_backend_qtro/plugin.pri.tpl
-templates_backend_qtro.path = $$[QT_HOST_BINS]/ivigenerator/templates_backend_qtro
+ templates/backend_qtro/backend.cpp.tpl \
+ templates/backend_qtro/backend.h.tpl \
+ templates/backend_qtro/pagingmodel.h.tpl \
+ templates/backend_qtro/pagingmodel.cpp.tpl \
+ templates/backend_qtro/plugin.cpp.tpl \
+ templates/backend_qtro/plugin.h.tpl \
+ templates/backend_qtro/plugin.json \
+ templates/backend_qtro/plugin.pri.tpl
+templates_backend_qtro.path = $$[QT_HOST_BINS]/ivigenerator/templates/backend_qtro
templates_server_qtro.files += \
- templates_server_qtro/core.cpp.tpl \
- templates_server_qtro/core.h.tpl \
- templates_server_qtro/server.pri.tpl
-templates_server_qtro.path = $$[QT_HOST_BINS]/ivigenerator/templates_server_qtro
+ templates/server_qtro/core.cpp.tpl \
+ templates/server_qtro/core.h.tpl \
+ templates/server_qtro/server.pri.tpl
+templates_server_qtro.path = $$[QT_HOST_BINS]/ivigenerator/templates/server_qtro
templates_server_qtro_simulator.files += \
- templates_server_qtro_simulator/core.cpp.tpl \
- templates_server_qtro_simulator/core.h.tpl \
- templates_server_qtro_simulator/adapter.cpp.tpl \
- templates_server_qtro_simulator/adapter.h.tpl \
- templates_server_qtro_simulator/main.cpp.tpl \
- templates_server_qtro_simulator/server.pri.tpl
-templates_server_qtro_simulator.path = $$[QT_HOST_BINS]/ivigenerator/templates_server_qtro_simulator
+ templates/server_qtro_simulator/core.cpp.tpl \
+ templates/server_qtro_simulator/core.h.tpl \
+ templates/server_qtro_simulator/adapter.cpp.tpl \
+ templates/server_qtro_simulator/adapter.h.tpl \
+ templates/server_qtro_simulator/main.cpp.tpl \
+ templates/server_qtro_simulator/server.pri.tpl
+templates_server_qtro_simulator.path = $$[QT_HOST_BINS]/ivigenerator/templates/server_qtro_simulator
templates_test.files += \
- templates_test/tst_test.h.tpl \
- templates_test/tst_test.cpp.tpl \
- templates_test/module.pri.tpl \
- templates_test/main.cpp.tpl \
- templates_test/pagingmodel.h.tpl
-templates_test.path = $$[QT_HOST_BINS]/ivigenerator/templates_test
+ templates/test/tst_test.h.tpl \
+ templates/test/tst_test.cpp.tpl \
+ templates/test/module.pri.tpl \
+ templates/test/main.cpp.tpl \
+ templates/test/pagingmodel.h.tpl
+templates_test.path = $$[QT_HOST_BINS]/ivigenerator/templates/test
+
+templates_yaml.files += \
+ templates/frontend.yaml \
+ templates/qmlplugin.yaml \
+ templates/backend_simulator.yaml \
+ templates/test.yaml
+templates_yaml.path = $$[QT_HOST_BINS]/ivigenerator/templates
+
+generator_module.files += \
+ generator/global_functions.py \
+ generator/builtin_config.py \
+ generator/filters.py \
+ generator/rule_generator.py
+generator_module.path = $$[QT_HOST_BINS]/ivigenerator/generator
generator.files += \
generate.py \
- $$OUT_PWD/.config \
- templates_frontend.yaml \
- templates_qmlplugin.yaml \
- templates_backend_simulator.yaml \
- templates_test.yaml \
-
+ $$OUT_PWD/.config
generator.path = $$[QT_HOST_BINS]/ivigenerator
qtConfig(remoteobjects) {
- generator.files += templates_backend_qtro.yaml \
- templates_server_qtro.yaml \
- templates_server_qtro_simulator.yaml \
+ templates_yaml.files += templates/backend_qtro.yaml \
+ templates/server_qtro.yaml \
+ templates/server_qtro_simulator.yaml \
INSTALLS += templates_backend_qtro \
templates_server_qtro \
@@ -116,6 +124,8 @@ qtConfig(remoteobjects) {
}
INSTALLS += generator \
+ generator_module \
+ templates_yaml \
common \
templates_frontend \
templates_qmlplugin \
diff --git a/src/tools/ivigenerator/templates/backend_qtro.yaml b/src/tools/ivigenerator/templates/backend_qtro.yaml
new file mode 100644
index 0000000..795d781
--- /dev/null
+++ b/src/tools/ivigenerator/templates/backend_qtro.yaml
@@ -0,0 +1,12 @@
+backend_qtro:
+ module:
+ documents:
+ - "{{module.module_name|lower}}qtroplugin.h": "plugin.h.tpl"
+ - "{{module.module_name|lower}}qtroplugin.cpp": "plugin.cpp.tpl"
+ - "{{module.module_name|lower}}.json": "plugin.json"
+ - "{{srcBase|lower}}.pri": "plugin.pri.tpl"
+ interface:
+ documents:
+ - '{{interface|lower}}backend.h': 'backend.h.tpl'
+ - '{{interface|lower}}backend.cpp': 'backend.cpp.tpl'
+ - "{{interface|lower}}.rep": "common/interface.rep.tpl"
diff --git a/src/tools/ivigenerator/templates_backend_qtro/backend.cpp.tpl b/src/tools/ivigenerator/templates/backend_qtro/backend.cpp.tpl
index 39c2bea..5a46282 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/backend.cpp.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/backend.cpp.tpl
@@ -65,7 +65,9 @@ QT_BEGIN_NAMESPACE
, m_parent(parent)
, m_zone(zone)
{% for property in interface.properties %}
-{% if not property.type.is_model %}
+{% if property.type.is_model %}
+ , m_{{property}}(new Zoned{{property|upperfirst}}ModelBackend(QStringLiteral("{{interface.qualified_name}}.{{property}}.") + m_zone, this))
+{% else %}
, m_{{ property }}({{property|default_value}})
{% endif %}
{% endfor %}
@@ -83,10 +85,13 @@ void {{zone_class}}::sync()
return;
{% for property in interface.properties %}
+{% if not property.type.is_model %}
m_propertiesToSync.append(QStringLiteral("{{property}}"));
+{% endif %}
{% endfor %}
{% for property in interface.properties %}
+{% if not property.type.is_model %}
QRemoteObjectPendingReply<{{property|return_type}}> {{property}}Reply = m_parent->m_replica->{{property|getter_name}}(m_zone);
auto {{property}}Watcher = new QRemoteObjectPendingCallWatcher({{property}}Reply);
connect({{property}}Watcher, &QRemoteObjectPendingCallWatcher::finished, this, [this](QRemoteObjectPendingCallWatcher *self) mutable {
@@ -97,6 +102,7 @@ void {{zone_class}}::sync()
}
self->deleteLater();
});
+{% endif %}
{% endfor %}
}
@@ -122,13 +128,18 @@ void {{zone_class}}::emitCurrentState()
{% endfor %}
{% endif %}
-{{class}}::{{class}}(QObject *parent)
+{{class}}::{{class}}(const QString &remoteObjectsLookupName, QObject *parent)
: {{class}}Interface(parent)
, m_node(nullptr)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_helper(new QIviRemoteObjectReplicaHelper(qLcRO{{interface}}(), this))
{% for property in interface.properties %}
{% if property.type.is_model %}
- , m_{{property}}(new {{property|upperfirst}}ModelBackend(this))
+{% if interface_zoned %}
+ , m_{{property}}(new Zoned{{property|upperfirst}}ModelBackend(QStringLiteral("{{interface.qualified_name}}.{{property}}"), this))
+{% else %}
+ , m_{{property}}(new {{property|upperfirst}}ModelBackend(QStringLiteral("{{interface.qualified_name}}.{{property}}"), this))
+{% endif %}
{% endif %}
{% endfor %}
{% if interface_zoned %}
@@ -295,7 +306,7 @@ bool {{class}}::connectToNode()
return false;
}
qCInfo(qLcRO{{interface}}) << "Connecting to" << m_url;
- m_replica.reset(m_node->acquire<{{interface}}Replica>(QStringLiteral("{{interface.qualified_name}}")));
+ m_replica.reset(m_node->acquire<{{interface}}Replica>(m_remoteObjectsLookupName));
setupConnections();
}
return true;
diff --git a/src/tools/ivigenerator/templates_backend_qtro/backend.h.tpl b/src/tools/ivigenerator/templates/backend_qtro/backend.h.tpl
index 7020177..74ee93e 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/backend.h.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/backend.h.tpl
@@ -106,7 +106,8 @@ class {{class}} : public {{class}}Interface
Q_OBJECT
public:
- explicit {{class}}(QObject *parent = nullptr);
+ explicit {{class}}(const QString &remoteObjectsLookupName = QStringLiteral("{{interface.qualified_name}}"),
+ QObject *parent = nullptr);
~{{class}}();
void initialize() override;
@@ -141,6 +142,7 @@ protected:
QSharedPointer<{{interface}}Replica> m_replica;
QRemoteObjectNode* m_node= nullptr;
QUrl m_url;
+ QString m_remoteObjectsLookupName;
QHash<quint64, QIviPendingReplyBase> m_pendingReplies;
QIviRemoteObjectReplicaHelper *m_helper;
{% for property in interface.properties %}
diff --git a/src/tools/ivigenerator/templates_backend_qtro/pagingmodel.cpp.tpl b/src/tools/ivigenerator/templates/backend_qtro/pagingmodel.cpp.tpl
index 6a20585..b9e7558 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/pagingmodel.cpp.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/pagingmodel.cpp.tpl
@@ -36,14 +36,20 @@
#
# SPDX-License-Identifier: LGPL-3.0
#}
+{% set interface_zoned = interface.tags.config and interface.tags.config.zoned %}
+{% if interface_zoned %}
+{% set class = 'Zoned{0}ModelBackend'.format(property|upperfirst) %}
+{% else %}
{% set class = '{0}ModelBackend'.format(property|upperfirst) %}
+{% endif %}
Q_LOGGING_CATEGORY(qLcRO{{interface}}{{property|upper_first}}, "{{module|qml_type|lower}}.{{interface|lower}}backend.{{property|lower}}.remoteobjects", QtInfoMsg)
-{{class}}::{{class}}(QObject* parent)
+{{class}}::{{class}}(const QString &remoteObjectsLookupName, QObject* parent)
: QIviPagingModelInterface(parent)
, m_node(nullptr)
, m_helper(new QIviRemoteObjectReplicaHelper(qLcRO{{interface}}{{property|upper_first}}(), this))
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
{
qRegisterMetaType<QIviPagingModelInterface*>();
}
@@ -110,7 +116,7 @@ bool {{class}}::connectToNode()
return false;
}
qCInfo(qLcRO{{interface}}{{property|upper_first}}) << "Connecting to" << m_url;
- m_replica.reset(m_node->acquire<PagingModelReplica>(QStringLiteral("{{interface.qualified_name}}.{{property}}")));
+ m_replica.reset(m_node->acquire<QIviPagingModelReplica>(m_remoteObjectsLookupName));
setupConnections();
}
return true;
@@ -123,8 +129,8 @@ void {{class}}::setupConnections()
connect(m_helper, &QIviRemoteObjectReplicaHelper::errorChanged, this, &QIviFeatureInterface::errorChanged);
connect(m_replica.data(), &QRemoteObjectReplica::stateChanged, m_helper, &QIviRemoteObjectReplicaHelper::onReplicaStateChanged);
- connect(m_replica.data(), &PagingModelReplica::supportedCapabilitiesChanged, this, &{{class}}::supportedCapabilitiesChanged);
- connect(m_replica.data(), &PagingModelReplica::countChanged, this, &{{class}}::countChanged);
- connect(m_replica.data(), &PagingModelReplica::dataFetched, this, &{{class}}::dataFetched);
- connect(m_replica.data(), &PagingModelReplica::dataChanged, this, &{{class}}::dataChanged);
+ connect(m_replica.data(), &QIviPagingModelReplica::supportedCapabilitiesChanged, this, &{{class}}::supportedCapabilitiesChanged);
+ connect(m_replica.data(), &QIviPagingModelReplica::countChanged, this, &{{class}}::countChanged);
+ connect(m_replica.data(), &QIviPagingModelReplica::dataFetched, this, &{{class}}::dataFetched);
+ connect(m_replica.data(), &QIviPagingModelReplica::dataChanged, this, &{{class}}::dataChanged);
}
diff --git a/src/tools/ivigenerator/templates_backend_qtro/pagingmodel.h.tpl b/src/tools/ivigenerator/templates/backend_qtro/pagingmodel.h.tpl
index ceeaff9..740298f 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/pagingmodel.h.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/pagingmodel.h.tpl
@@ -36,18 +36,23 @@
#
# SPDX-License-Identifier: LGPL-3.0
#}
+{% set interface_zoned = interface.tags.config and interface.tags.config.zoned %}
+{% if interface_zoned %}
+{% set class = 'Zoned{0}ModelBackend'.format(property|upperfirst) %}
+{% else %}
{% set class = '{0}ModelBackend'.format(property|upperfirst) %}
+{% endif %}
#include <QIviPagingModelInterface>
#include "{{property.type.nested|lower}}.h"
-#include "rep_pagingmodel_replica.h"
+#include "rep_qivipagingmodel_replica.h"
class {{class}} : public QIviPagingModelInterface
{
Q_OBJECT
public:
- explicit {{class}}(QObject *parent = nullptr);
+ explicit {{class}}(const QString &remoteObjectsLookupName = QStringLiteral("{{interface.qualified_name}}.{{property}}"), QObject *parent = nullptr);
~{{class}}();
void initialize() override;
@@ -60,9 +65,10 @@ private:
bool connectToNode();
void setupConnections();
- QSharedPointer<PagingModelReplica> m_replica;
+ QSharedPointer<QIviPagingModelReplica> m_replica;
QIviRemoteObjectReplicaHelper *m_helper;
QRemoteObjectNode *m_node= nullptr;
+ QString m_remoteObjectsLookupName;
QUrl m_url;
QVariantList m_list;
};
diff --git a/src/tools/ivigenerator/templates_backend_qtro/plugin.cpp.tpl b/src/tools/ivigenerator/templates/backend_qtro/plugin.cpp.tpl
index febdbb1..290b5e9 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/plugin.cpp.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/plugin.cpp.tpl
@@ -38,7 +38,7 @@
# SPDX-License-Identifier: LGPL-3.0
#}
{% include "common/generated_comment.cpp.tpl" %}
-{% set class = '{0}Plugin'.format(module.module_name) %}
+{% set class = '{0}QtROPlugin'.format(module.module_name) %}
#include "{{class|lower}}.h"
@@ -53,9 +53,9 @@ QT_BEGIN_NAMESPACE
{{class}}::{{class}}(QObject *parent)
: QObject(parent)
{
-{% for interface in module.interfaces %}
- m_interfaces << new {{interface}}Backend(this);
-{% endfor %}
+{% for interface in module.interfaces %}
+ m_interfaces << new {{interface}}Backend(QStringLiteral("{{interface.qualified_name}}"), this);
+{% endfor %}
}
QStringList {{class}}::interfaces() const
diff --git a/src/tools/ivigenerator/templates_backend_qtro/plugin.h.tpl b/src/tools/ivigenerator/templates/backend_qtro/plugin.h.tpl
index bc8ddc5..ea9cd6b 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/plugin.h.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/plugin.h.tpl
@@ -38,7 +38,7 @@
# SPDX-License-Identifier: LGPL-3.0
#}
{% include "common/generated_comment.cpp.tpl" %}
-{% set class = '{0}Plugin'.format(module.module_name) %}
+{% set class = '{0}QtROPlugin'.format(module.module_name) %}
{% set oncedefine = '{0}_{1}_H_'.format(module.module_name|upper, class|upper) %}
#ifndef {{oncedefine}}
diff --git a/src/tools/ivigenerator/templates_backend_qtro/plugin.json b/src/tools/ivigenerator/templates/backend_qtro/plugin.json
index b205459..b205459 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/plugin.json
+++ b/src/tools/ivigenerator/templates/backend_qtro/plugin.json
diff --git a/src/tools/ivigenerator/templates_backend_qtro/plugin.pri.tpl b/src/tools/ivigenerator/templates/backend_qtro/plugin.pri.tpl
index 8d1f3c5..cb2e822 100644
--- a/src/tools/ivigenerator/templates_backend_qtro/plugin.pri.tpl
+++ b/src/tools/ivigenerator/templates/backend_qtro/plugin.pri.tpl
@@ -48,16 +48,15 @@ HEADERS += \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}backend.h \
{% endfor %}
- $$PWD/{{module.module_name|lower}}plugin.h
+ $$PWD/{{module.module_name|lower}}qtroplugin.h
SOURCES += \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}backend.cpp \
{% endfor %}
- $$PWD/{{module.module_name|lower}}plugin.cpp
+ $$PWD/{{module.module_name|lower}}qtroplugin.cpp
REPC_REPLICA += \
- $$PWD/pagingmodel.rep \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}.rep \
{% endfor %}
diff --git a/src/tools/ivigenerator/templates/backend_simulator.yaml b/src/tools/ivigenerator/templates/backend_simulator.yaml
new file mode 100644
index 0000000..9228664
--- /dev/null
+++ b/src/tools/ivigenerator/templates/backend_simulator.yaml
@@ -0,0 +1,19 @@
+backend_simulator:
+ module:
+ documents:
+ - "{{module.module_name|lower}}simulatorplugin.h": "plugin.h.tpl"
+ - "{{module.module_name|lower}}simulatorplugin.cpp": "plugin.cpp.tpl"
+ - "{{module.module_name|lower}}_simulation.qml": "common/module_simulation.qml.tpl"
+ - "{{module.module_name|lower}}.json": "plugin.json"
+ - "{{module.module_name|lower}}_simulation_data.json": "common/simulation_data.json.tpl"
+ - "{{module.module_name|lower}}_simulation.qrc": "common/simulation.qrc.tpl"
+ - "{{srcBase|lower}}.pri": "plugin.pri.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/simulation/plugins.qmltypes": "common/simulation.qmltypes.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/simulation/qmldir": "common/qmldir.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes": "common/plugins.qmltypes.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/qmldir": "common/qmldir.tpl"
+ interface:
+ documents:
+ - '{{interface|lower}}backend.h': 'common/backend_simulation.h.tpl'
+ - '{{interface|lower}}backend.cpp': 'common/backend_simulation.cpp.tpl'
+ - '{{interface|upperfirst}}Simulation.qml': 'common/backend_simulation.qml.tpl'
diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl b/src/tools/ivigenerator/templates/backend_simulator/plugin.cpp.tpl
index 710c504..22d1a58 100644
--- a/src/tools/ivigenerator/templates_backend_simulator/plugin.cpp.tpl
+++ b/src/tools/ivigenerator/templates/backend_simulator/plugin.cpp.tpl
@@ -39,7 +39,7 @@
# SPDX-License-Identifier: LGPL-3.0
#}
{% include "common/generated_comment.cpp.tpl" %}
-{% set class = '{0}Plugin'.format(module.module_name|upperfirst) %}
+{% set class = '{0}SimulatorPlugin'.format(module.module_name|upperfirst) %}
#include "{{class|lower}}.h"
diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.h.tpl b/src/tools/ivigenerator/templates/backend_simulator/plugin.h.tpl
index dfb86b1..cd235d6 100644
--- a/src/tools/ivigenerator/templates_backend_simulator/plugin.h.tpl
+++ b/src/tools/ivigenerator/templates/backend_simulator/plugin.h.tpl
@@ -39,7 +39,7 @@
# SPDX-License-Identifier: LGPL-3.0
#}
{% include "common/generated_comment.cpp.tpl" %}
-{% set class = '{0}Plugin'.format(module.module_name|upperfirst) %}
+{% set class = '{0}SimulatorPlugin'.format(module.module_name|upperfirst) %}
{% set oncedefine = '{0}_{1}_H_'.format(module.module_name|upper, class|upper) %}
#ifndef {{oncedefine}}
diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.json b/src/tools/ivigenerator/templates/backend_simulator/plugin.json
index 146b83a..146b83a 100644
--- a/src/tools/ivigenerator/templates_backend_simulator/plugin.json
+++ b/src/tools/ivigenerator/templates/backend_simulator/plugin.json
diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.pri.tpl b/src/tools/ivigenerator/templates/backend_simulator/plugin.pri.tpl
index 2ad5932..84dbe37 100644
--- a/src/tools/ivigenerator/templates_backend_simulator/plugin.pri.tpl
+++ b/src/tools/ivigenerator/templates/backend_simulator/plugin.pri.tpl
@@ -50,13 +50,13 @@ HEADERS += \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}backend.h \
{% endfor %}
- $$PWD/{{module.module_name|lower}}plugin.h
+ $$PWD/{{module.module_name|lower}}simulatorplugin.h
SOURCES += \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}backend.cpp \
{% endfor %}
- $$PWD/{{module.module_name|lower}}plugin.cpp
+ $$PWD/{{module.module_name|lower}}simulatorplugin.cpp
RESOURCES += $$PWD/{{module.module_name|lower}}_simulation.qrc
diff --git a/src/tools/ivigenerator/templates_backend_simulator/plugin.pro b/src/tools/ivigenerator/templates/backend_simulator/plugin.pro
index dd96eb2..dd96eb2 100644
--- a/src/tools/ivigenerator/templates_backend_simulator/plugin.pro
+++ b/src/tools/ivigenerator/templates/backend_simulator/plugin.pro
diff --git a/src/tools/ivigenerator/common/backend_simulation.cpp.tpl b/src/tools/ivigenerator/templates/common/backend_simulation.cpp.tpl
index 7684b68..9ee929e 100644
--- a/src/tools/ivigenerator/common/backend_simulation.cpp.tpl
+++ b/src/tools/ivigenerator/templates/common/backend_simulation.cpp.tpl
@@ -62,7 +62,13 @@ QT_BEGIN_NAMESPACE
, m_parent(parent)
, m_zone(zone)
{% for property in interface.properties %}
-{% if not property.type.is_model %}
+{% if property.type.is_model %}
+{% if interface_zoned %}
+ , m_{{ property }}(new Zoned{{property|upperfirst}}ModelBackend(this))
+{% else %}
+ , m_{{ property }}(new {{property|upperfirst}}ModelBackend(this));
+{% endif %}
+{% else %}
, m_{{ property }}({{property|default_value}})
{% endif %}
{% endfor %}
diff --git a/src/tools/ivigenerator/common/backend_simulation.h.tpl b/src/tools/ivigenerator/templates/common/backend_simulation.h.tpl
index 73dbd5c..73dbd5c 100644
--- a/src/tools/ivigenerator/common/backend_simulation.h.tpl
+++ b/src/tools/ivigenerator/templates/common/backend_simulation.h.tpl
diff --git a/src/tools/ivigenerator/common/backend_simulation.qml.tpl b/src/tools/ivigenerator/templates/common/backend_simulation.qml.tpl
index 2cbbd11..1ee5e6b 100644
--- a/src/tools/ivigenerator/common/backend_simulation.qml.tpl
+++ b/src/tools/ivigenerator/templates/common/backend_simulation.qml.tpl
@@ -70,26 +70,28 @@ QtObject {
{% if interface_zoned %}
function {{property|setter_name}}({{property}}, zone) {
- if (IviSimulator.checkSettings(settings["{{property}}"], {{property}}, zone)) {
- if (zone) {
- console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} for zone: " + zone + " changed to: " + {{property}});
- backend.zones[zone].{{property}} = {{property}}
- } else {
- console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} changed to: " + {{property}});
- backend.{{property}} = {{property}}
- }
- } else {
+ if ("{{property}}" in settings && !IviSimulator.checkSettings(settings["{{property}}"], {{property}}, zone)) {
console.error(qLc{{interface|upperfirst}}, "SIMULATION changing {{property}} is not possible: provided: " + {{property}} + " constraint: " + IviSimulator.constraint(settings["{{property}}"]));
+ return;
+ }
+
+ if (zone) {
+ console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} for zone: " + zone + " changed to: " + {{property}});
+ backend.zones[zone].{{property}} = {{property}}
+ } else {
+ console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} changed to: " + {{property}});
+ backend.{{property}} = {{property}}
}
}
{% else %}
function {{property|setter_name}}({{property}}) {
- if (IviSimulator.checkSettings(settings["{{property}}"], {{property}})) {
- console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} changed to: " + {{property}});
- backend.{{property}} = {{property}}
- } else {
+ if ("{{property}}" in settings && !IviSimulator.checkSettings(settings["{{property}}"], {{property}})) {
console.error(qLc{{interface|upperfirst}}, "SIMULATION changing {{property}} is not possible: provided: " + {{property}} + " constraint: " + IviSimulator.constraint(settings["{{property}}"]));
+ return;
}
+
+ console.log(qLc{{interface|upperfirst}}, "SIMULATION {{ property }} changed to: " + {{property}});
+ backend.{{property}} = {{property}}
}
{% endif %}
{% endfor %}
diff --git a/src/tools/ivigenerator/common/generated_comment.cpp.tpl b/src/tools/ivigenerator/templates/common/generated_comment.cpp.tpl
index 95878f2..95878f2 100644
--- a/src/tools/ivigenerator/common/generated_comment.cpp.tpl
+++ b/src/tools/ivigenerator/templates/common/generated_comment.cpp.tpl
diff --git a/src/tools/ivigenerator/common/interface.rep.tpl b/src/tools/ivigenerator/templates/common/interface.rep.tpl
index dd75f03..dd75f03 100644
--- a/src/tools/ivigenerator/common/interface.rep.tpl
+++ b/src/tools/ivigenerator/templates/common/interface.rep.tpl
diff --git a/src/tools/ivigenerator/common/module_simulation.qml.tpl b/src/tools/ivigenerator/templates/common/module_simulation.qml.tpl
index ff558d8..ff558d8 100644
--- a/src/tools/ivigenerator/common/module_simulation.qml.tpl
+++ b/src/tools/ivigenerator/templates/common/module_simulation.qml.tpl
diff --git a/src/tools/ivigenerator/common/pagingmodel_simulation.cpp.tpl b/src/tools/ivigenerator/templates/common/pagingmodel_simulation.cpp.tpl
index a6b222e..184cecf 100644
--- a/src/tools/ivigenerator/common/pagingmodel_simulation.cpp.tpl
+++ b/src/tools/ivigenerator/templates/common/pagingmodel_simulation.cpp.tpl
@@ -56,6 +56,11 @@
{
}
+int {{class}}::count() const
+{
+ return m_list.count();
+}
+
void {{class}}::initialize()
{
QIVI_SIMULATION_TRY_CALL({{class}}, "initialize", void);
@@ -92,6 +97,7 @@ void {{class}}::insert(int index, const {{property.type.nested}} &item)
m_list.insert(index, item);
Q_EMIT dataChanged(QUuid(), { QVariant::fromValue(item) }, index, 0);
+ Q_EMIT countChanged(QUuid(), m_list.count());
}
void {{class}}::remove(int index)
@@ -99,6 +105,7 @@ void {{class}}::remove(int index)
m_list.removeAt(index);
Q_EMIT dataChanged(QUuid(), QVariantList(), index, 1);
+ Q_EMIT countChanged(QUuid(), m_list.count());
}
void {{class}}::move(int currentIndex, int newIndex)
@@ -117,6 +124,7 @@ void {{class}}::move(int currentIndex, int newIndex)
void {{class}}::reset()
{
Q_EMIT dataChanged(QUuid(), QVariantList(), 0, m_list.count());
+ Q_EMIT countChanged(QUuid(), 0);
m_list.clear();
}
@@ -126,7 +134,7 @@ void {{class}}::update(int index, const {{property.type.nested}} &item)
Q_EMIT dataChanged(QUuid(), { QVariant::fromValue(item) }, index, 1);
}
-const {{property.type.nested}} &{{class}}::at(int index) const
+{{property.type.nested}} {{class}}::at(int index) const
{
return m_list.at(index);
}
diff --git a/src/tools/ivigenerator/common/pagingmodel_simulation.h.tpl b/src/tools/ivigenerator/templates/common/pagingmodel_simulation.h.tpl
index ace6a72..be911f8 100644
--- a/src/tools/ivigenerator/common/pagingmodel_simulation.h.tpl
+++ b/src/tools/ivigenerator/templates/common/pagingmodel_simulation.h.tpl
@@ -51,10 +51,13 @@
class {{class}} : public QIviPagingModelInterface
{
Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
explicit {{class}}(QObject *parent = nullptr);
~{{class}}();
+ int count() const;
+
Q_INVOKABLE void initialize() override;
Q_INVOKABLE void registerInstance(const QUuid &identifier) override;
Q_INVOKABLE void unregisterInstance(const QUuid &identifier) override;
@@ -67,7 +70,7 @@ public Q_SLOTS:
void move(int currentIndex, int newIndex);
void reset();
void update(int index, const {{property.type.nested}} &item);
- const {{property.type.nested}} &at(int index) const;
+ {{property.type.nested}} at(int index) const;
private:
QList<{{property.type.nested}}> m_list;
diff --git a/src/tools/ivigenerator/common/plugins.qmltypes.tpl b/src/tools/ivigenerator/templates/common/plugins.qmltypes.tpl
index 5480e2e..5480e2e 100644
--- a/src/tools/ivigenerator/common/plugins.qmltypes.tpl
+++ b/src/tools/ivigenerator/templates/common/plugins.qmltypes.tpl
diff --git a/src/tools/ivigenerator/common/qmldir.tpl b/src/tools/ivigenerator/templates/common/qmldir.tpl
index 4ed2cd6..4ed2cd6 100644
--- a/src/tools/ivigenerator/common/qmldir.tpl
+++ b/src/tools/ivigenerator/templates/common/qmldir.tpl
diff --git a/src/tools/ivigenerator/common/qtivi_macros.j2 b/src/tools/ivigenerator/templates/common/qtivi_macros.j2
index be326b5..be326b5 100644
--- a/src/tools/ivigenerator/common/qtivi_macros.j2
+++ b/src/tools/ivigenerator/templates/common/qtivi_macros.j2
diff --git a/src/tools/ivigenerator/common/simulation.qmltypes.tpl b/src/tools/ivigenerator/templates/common/simulation.qmltypes.tpl
index 80173c8..b8e79dc 100644
--- a/src/tools/ivigenerator/common/simulation.qmltypes.tpl
+++ b/src/tools/ivigenerator/templates/common/simulation.qmltypes.tpl
@@ -103,6 +103,7 @@ Module {
exports: ["{{module|qml_type}}.simulation/{{property|upperfirst}}ModelBackend {{module.majorVersion}}.{{module.minorVersion}}"]
Property { name: "Base"; type: "{{property|upperfirst}}ModelBackend"; isPointer: true }
+ Property { name: "count"; type: "int" }
Method { name: "initialize" }
Method {
diff --git a/src/tools/ivigenerator/common/simulation.qrc.tpl b/src/tools/ivigenerator/templates/common/simulation.qrc.tpl
index 151a7ec..151a7ec 100644
--- a/src/tools/ivigenerator/common/simulation.qrc.tpl
+++ b/src/tools/ivigenerator/templates/common/simulation.qrc.tpl
diff --git a/src/tools/ivigenerator/common/simulation_data.json.tpl b/src/tools/ivigenerator/templates/common/simulation_data.json.tpl
index 57cee12..57cee12 100644
--- a/src/tools/ivigenerator/common/simulation_data.json.tpl
+++ b/src/tools/ivigenerator/templates/common/simulation_data.json.tpl
diff --git a/src/tools/ivigenerator/templates/frontend.yaml b/src/tools/ivigenerator/templates/frontend.yaml
new file mode 100644
index 0000000..fdab347
--- /dev/null
+++ b/src/tools/ivigenerator/templates/frontend.yaml
@@ -0,0 +1,23 @@
+frontend:
+ module:
+ documents:
+ - '{{module.module_name|lower}}global.h': 'global.h.tpl'
+ - '{{module.module_name|lower}}module.h': 'module.h.tpl'
+ - '{{module.module_name|lower}}module.cpp': 'module.cpp.tpl'
+ - '{{module.module_name|lower}}module_enum.qdocinc': 'module_qml_enum.qdocinc.tpl'
+ - '{{module.module_name|lower}}modulefactory.h': 'modulefactory.h.tpl'
+ - '{{module.module_name|lower}}modulefactory.cpp': 'modulefactory.cpp.tpl'
+ - '{{srcBase|lower}}.pri': 'module.pri.tpl'
+ - 'qml/{{module|qml_type|replace(".", "/")}}/plugins.qmltypes': 'common/plugins.qmltypes.tpl'
+ - 'qml/{{module|qml_type|replace(".", "/")}}/qmldir': 'common/qmldir.tpl'
+ interface:
+ documents:
+ - '{{interface|lower}}backendinterface.h': 'backendinterface.h.tpl'
+ - '{{interface|lower}}backendinterface.cpp': 'backendinterface.cpp.tpl'
+ - '{{interface|lower}}.h': 'interface.h.tpl'
+ - '{{interface|lower}}_p.h': 'interface_p.h.tpl'
+ - '{{interface|lower}}.cpp': 'interface.cpp.tpl'
+ struct:
+ documents:
+ - '{{struct|lower}}.h': 'struct.h.tpl'
+ - '{{struct|lower}}.cpp': 'struct.cpp.tpl'
diff --git a/src/tools/ivigenerator/templates_frontend/backendinterface.cpp.tpl b/src/tools/ivigenerator/templates/frontend/backendinterface.cpp.tpl
index b13be0a..b13be0a 100644
--- a/src/tools/ivigenerator/templates_frontend/backendinterface.cpp.tpl
+++ b/src/tools/ivigenerator/templates/frontend/backendinterface.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/backendinterface.h.tpl b/src/tools/ivigenerator/templates/frontend/backendinterface.h.tpl
index 2eb9b97..2eb9b97 100644
--- a/src/tools/ivigenerator/templates_frontend/backendinterface.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/backendinterface.h.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/global.h.tpl b/src/tools/ivigenerator/templates/frontend/global.h.tpl
index 7ebbf64..7ebbf64 100644
--- a/src/tools/ivigenerator/templates_frontend/global.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/global.h.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl b/src/tools/ivigenerator/templates/frontend/interface.cpp.tpl
index 40a9b3c..40a9b3c 100644
--- a/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl
+++ b/src/tools/ivigenerator/templates/frontend/interface.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/interface.h.tpl b/src/tools/ivigenerator/templates/frontend/interface.h.tpl
index e1dc448..e1dc448 100644
--- a/src/tools/ivigenerator/templates_frontend/interface.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/interface.h.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/interface_p.h.tpl b/src/tools/ivigenerator/templates/frontend/interface_p.h.tpl
index 0a68644..0a68644 100644
--- a/src/tools/ivigenerator/templates_frontend/interface_p.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/interface_p.h.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/module.cpp.tpl b/src/tools/ivigenerator/templates/frontend/module.cpp.tpl
index ac3f6d8..ec0f87b 100644
--- a/src/tools/ivigenerator/templates_frontend/module.cpp.tpl
+++ b/src/tools/ivigenerator/templates/frontend/module.cpp.tpl
@@ -113,6 +113,24 @@ QObject* {{class|lower}}_singletontype_provider(QQmlEngine*, QJSEngine*)
/*! \internal */
void {{class}}::registerTypes()
{
+ static bool once = false;
+ if (once)
+ return;
+ once = true;
+
+{% for import in module.imports %}
+{# All imports are provided including their imported version e.g. "Common 1.0". Because we need
+ to access the Module type, we first need to split the version and then search for the name.
+ See https://github.com/Pelagicore/qface/issues/87
+#}
+{% set name = import.split(' ')[0] %}
+{% for mod in system.modules %}
+{% if mod.name == name %}
+ {{mod.module_name|upperfirst}}Module::registerTypes();
+{% endif %}
+{% endfor %}
+{% endfor %}
+
{% for enum in module.enums %}
qRegisterMetaType<{{class}}::{{enum|flag_type}}>();
qRegisterMetaTypeStreamOperators<{{class}}::{{enum|flag_type}}>();
@@ -126,6 +144,7 @@ void {{class}}::registerTypes()
{% for struct in module.structs %}
qRegisterMetaType<{{struct}}>();
qRegisterMetaTypeStreamOperators<{{struct}}>();
+ QMetaType::registerEqualsComparator<{{struct}}>();
qIviRegisterPendingReplyType<{{struct}}>();
{% endfor %}
}
diff --git a/src/tools/ivigenerator/templates_frontend/module.h.tpl b/src/tools/ivigenerator/templates/frontend/module.h.tpl
index b9efded..859cf51 100644
--- a/src/tools/ivigenerator/templates_frontend/module.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/module.h.tpl
@@ -50,6 +50,20 @@
{% else %}
#include "{{module.module_name|lower}}global.h"
{% endif %}
+
+{% for import in module.imports %}
+{# All imports are provided including their imported version e.g. "Common 1.0". Because we need
+ to access the Module type, we first need to split the version and then search for the name.
+ See https://github.com/Pelagicore/qface/issues/87
+#}
+{% set name = import.split(' ')[0] %}
+{% for mod in system.modules %}
+{% if mod.name == name %}
+#include <{{mod.module_name|lower}}module.h>
+{% endif %}
+{% endfor %}
+{% endfor %}
+
#include <QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/tools/ivigenerator/templates_frontend/module.pri.tpl b/src/tools/ivigenerator/templates/frontend/module.pri.tpl
index acd167f..acd167f 100644
--- a/src/tools/ivigenerator/templates_frontend/module.pri.tpl
+++ b/src/tools/ivigenerator/templates/frontend/module.pri.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/module_qml_enum.qdocinc.tpl b/src/tools/ivigenerator/templates/frontend/module_qml_enum.qdocinc.tpl
index 65e4f88..65e4f88 100644
--- a/src/tools/ivigenerator/templates_frontend/module_qml_enum.qdocinc.tpl
+++ b/src/tools/ivigenerator/templates/frontend/module_qml_enum.qdocinc.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/modulefactory.cpp.tpl b/src/tools/ivigenerator/templates/frontend/modulefactory.cpp.tpl
index dcffada..dcffada 100644
--- a/src/tools/ivigenerator/templates_frontend/modulefactory.cpp.tpl
+++ b/src/tools/ivigenerator/templates/frontend/modulefactory.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/modulefactory.h.tpl b/src/tools/ivigenerator/templates/frontend/modulefactory.h.tpl
index 306b728..306b728 100644
--- a/src/tools/ivigenerator/templates_frontend/modulefactory.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/modulefactory.h.tpl
diff --git a/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl b/src/tools/ivigenerator/templates/frontend/struct.cpp.tpl
index 7b4a57d..00ea37b 100644
--- a/src/tools/ivigenerator/templates_frontend/struct.cpp.tpl
+++ b/src/tools/ivigenerator/templates/frontend/struct.cpp.tpl
@@ -109,31 +109,6 @@ public:
{
}
-{{class}}::{{class}}(const QVariant &variant)
- : {{class}}()
-{
- QVariant value = qtivi_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}}()
{
@@ -167,6 +142,30 @@ QString {{class}}::type() const
{% endfor %}
+void {{class}}::fromJSON(const QVariant &variant)
+{
+ QVariant value = qtivi_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 %}
+ }
+}
+
bool operator==(const {{class}} &left, const {{class}} &right) Q_DECL_NOTHROW
{
if (left.d == right.d)
diff --git a/src/tools/ivigenerator/templates_frontend/struct.h.tpl b/src/tools/ivigenerator/templates/frontend/struct.h.tpl
index 76639c2..3eaa480 100644
--- a/src/tools/ivigenerator/templates_frontend/struct.h.tpl
+++ b/src/tools/ivigenerator/templates/frontend/struct.h.tpl
@@ -47,8 +47,8 @@
#ifndef {{oncedefine}}
#define {{oncedefine}}
-{% if interface.module.tags.config.module %}
-#include <{{interface.module.tags.config.module}}/{{module.module_name|lower}}module.h>
+{% if module.tags.config.module %}
+#include <{{module.tags.config.module}}/{{module.module_name|lower}}module.h>
{% else %}
#include "{{module.module_name|lower}}module.h"
{% endif %}
@@ -73,11 +73,10 @@ class {{exportsymbol}} {{class}} : public QIviStandardItem
Q_CLASSINFO("IviPropertyDomains", "{{ struct.fields|json_domain|replace("\"", "\\\"") }}")
public:
- Q_INVOKABLE {{class}}();
- Q_INVOKABLE {{class}}(const {{class}} &rhs);
+ {{class}}();
+ {{class}}(const {{class}} &rhs);
{{class}} &operator=(const {{class}} &);
- Q_INVOKABLE {{class}}({{struct.fields|map('parameter_type')|join(', ')}});
- Q_INVOKABLE {{class}}(const QVariant &variant);
+ {{class}}({{struct.fields|map('parameter_type')|join(', ')}});
~{{class}}();
QString type() const override;
@@ -97,6 +96,9 @@ public:
{% endif %}
{% endfor %}
+protected:
+ Q_INVOKABLE void fromJSON(const QVariant &variant);
+
private:
QSharedDataPointer<{{class}}Private> d;
friend {{exportsymbol}} bool operator==(const {{class}} &left, const {{class}} &right) Q_DECL_NOTHROW;
diff --git a/src/tools/ivigenerator/templates/qmlplugin.yaml b/src/tools/ivigenerator/templates/qmlplugin.yaml
new file mode 100644
index 0000000..ba6d505
--- /dev/null
+++ b/src/tools/ivigenerator/templates/qmlplugin.yaml
@@ -0,0 +1,9 @@
+qmlplugin:
+ module:
+ documents:
+ - "plugin.cpp": "plugin.cpp.tpl"
+ - "{{srcBase|lower}}.pri": "module.pri.tpl"
+ - "plugins.qmltypes": "common/plugins.qmltypes.tpl"
+ - "qmldir": "qmldir_plugin.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes": "common/plugins.qmltypes.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/qmldir": "qmldir_plugin.tpl"
diff --git a/src/tools/ivigenerator/templates_qmlplugin/module.pri.tpl b/src/tools/ivigenerator/templates/qmlplugin/module.pri.tpl
index 4bd7d05..4bd7d05 100644
--- a/src/tools/ivigenerator/templates_qmlplugin/module.pri.tpl
+++ b/src/tools/ivigenerator/templates/qmlplugin/module.pri.tpl
diff --git a/src/tools/ivigenerator/templates_qmlplugin/plugin.cpp.tpl b/src/tools/ivigenerator/templates/qmlplugin/plugin.cpp.tpl
index 0d5a492..0d5a492 100644
--- a/src/tools/ivigenerator/templates_qmlplugin/plugin.cpp.tpl
+++ b/src/tools/ivigenerator/templates/qmlplugin/plugin.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_qmlplugin/qmldir_plugin.tpl b/src/tools/ivigenerator/templates/qmlplugin/qmldir_plugin.tpl
index 3936fd6..3936fd6 100644
--- a/src/tools/ivigenerator/templates_qmlplugin/qmldir_plugin.tpl
+++ b/src/tools/ivigenerator/templates/qmlplugin/qmldir_plugin.tpl
diff --git a/src/tools/ivigenerator/templates/server_qtro.yaml b/src/tools/ivigenerator/templates/server_qtro.yaml
new file mode 100644
index 0000000..0c8024e
--- /dev/null
+++ b/src/tools/ivigenerator/templates/server_qtro.yaml
@@ -0,0 +1,9 @@
+server_qtro:
+ module:
+ documents:
+ - "core.cpp": "core.cpp.tpl"
+ - "core.h": "core.h.tpl"
+ - "{{srcBase|lower}}.pri": "server.pri.tpl"
+ interface:
+ documents:
+ - "{{interface|lower}}.rep": "common/interface.rep.tpl"
diff --git a/src/tools/ivigenerator/templates_server_qtro/core.cpp.tpl b/src/tools/ivigenerator/templates/server_qtro/core.cpp.tpl
index 1c3450a..1c3450a 100644
--- a/src/tools/ivigenerator/templates_server_qtro/core.cpp.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro/core.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_server_qtro/core.h.tpl b/src/tools/ivigenerator/templates/server_qtro/core.h.tpl
index cb81491..cb81491 100644
--- a/src/tools/ivigenerator/templates_server_qtro/core.h.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro/core.h.tpl
diff --git a/src/tools/ivigenerator/templates_server_qtro/server.pri.tpl b/src/tools/ivigenerator/templates/server_qtro/server.pri.tpl
index aca2f24..230f897 100644
--- a/src/tools/ivigenerator/templates_server_qtro/server.pri.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro/server.pri.tpl
@@ -49,7 +49,6 @@ HEADERS += $$PWD/core.h
SOURCES += $$PWD/core.cpp
REPC_SOURCE += \
- $$PWD/pagingmodel.rep \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}.rep \
{% endfor %}
diff --git a/src/tools/ivigenerator/templates/server_qtro_simulator.yaml b/src/tools/ivigenerator/templates/server_qtro_simulator.yaml
new file mode 100644
index 0000000..b85de86
--- /dev/null
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator.yaml
@@ -0,0 +1,22 @@
+server_qtro_simulator:
+ module:
+ documents:
+ - "core.cpp": "core.cpp.tpl"
+ - "core.h": "core.h.tpl"
+ - "{{srcBase|lower}}.pri": "server.pri.tpl"
+ - "main.cpp": "main.cpp.tpl"
+ - "{{module.module_name|lower}}_simulation.qml": "common/module_simulation.qml.tpl"
+ - "{{module.module_name|lower}}_simulation_data.json": "common/simulation_data.json.tpl"
+ - "{{module.module_name|lower}}_simulation.qrc": "common/simulation.qrc.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/simulation/plugins.qmltypes": "common/simulation.qmltypes.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/simulation/qmldir": "common/qmldir.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes": "common/plugins.qmltypes.tpl"
+ - "qml/{{module|qml_type|replace('.', '/')}}/qmldir": "common/qmldir.tpl"
+ interface:
+ documents:
+ - "{{interface|lower}}.rep": "common/interface.rep.tpl"
+ - '{{interface|lower}}adapter.h': 'adapter.h.tpl'
+ - '{{interface|lower}}adapter.cpp': 'adapter.cpp.tpl'
+ - '{{interface|lower}}backend.h': 'common/backend_simulation.h.tpl'
+ - '{{interface|lower}}backend.cpp': 'common/backend_simulation.cpp.tpl'
+ - '{{interface|upperfirst}}Simulation.qml': 'common/backend_simulation.qml.tpl'
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/adapter.cpp.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/adapter.cpp.tpl
index a006ae7..e5e1d6b 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/adapter.cpp.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/adapter.cpp.tpl
@@ -41,6 +41,9 @@
{% set class = '{0}QtRoAdapter'.format(interface) %}
{% set interface_zoned = interface.tags.config and interface.tags.config.zoned %}
#include "{{interface|lower}}adapter.h"
+
+#include <QIviPagingModelAddressWrapper>
+
Q_LOGGING_CATEGORY(qLcRO{{interface}}, "{{module|qml_type|lower}}.{{interface|lower}}backend.remoteobjects", QtInfoMsg)
/*
@@ -50,8 +53,15 @@ Q_LOGGING_CATEGORY(qLcRO{{interface}}, "{{module|qml_type|lower}}.{{interface|lo
* to inform the client that the return value is not yet ready. Once the QIviPendingReply is ready
* the value is send with the pendingResultAvailable value
*/
+
{{class}}::{{class}}({{interface}}Backend *parent)
+ : {{class}}(QStringLiteral("{{interface.qualified_name}}"), parent)
+{
+}
+
+{{class}}::{{class}}(const QString &remoteObjectsLookupName, {{interface}}Backend *parent)
: {{interface}}Source(parent)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_backend(parent)
, m_helper(this, qLcRO{{interface}}())
{
@@ -65,6 +75,49 @@ Q_LOGGING_CATEGORY(qLcRO{{interface}}, "{{module|qml_type|lower}}.{{interface|lo
{% endfor %}
}
+QString {{class}}::remoteObjectsLookupName() const
+{
+ return m_remoteObjectsLookupName;
+}
+
+void {{class}}::enableRemoting(QRemoteObjectHostBase *node)
+{
+ node->enableRemoting<{{interface}}AddressWrapper>(this);
+{% set vars = { 'models': False } %}
+{% for property in interface.properties %}
+{% if property.type.is_model %}
+{% if vars.update({ 'models': True}) %}{% endif %}
+ auto {{property|lowerfirst}}Adapter = new QIviPagingModelQtRoAdapter(QStringLiteral("{{interface.qualified_name}}.{{property}}"), m_backend->{{property|getter_name}}());
+ node->enableRemoting<QIviPagingModelAddressWrapper>({{property|lowerfirst}}Adapter);
+ m_modelAdapters.insert(node, {{property|lowerfirst}}Adapter);
+{% endif %}
+{% endfor %}
+{% if vars.models and interface_zoned %}
+ // When this is called the backend should already been initialized
+ const QStringList zones = m_backend->availableZones();
+ for (const QString &zone : zones) {
+{% for property in interface.properties %}
+{% if property.type.is_model %}
+ auto {{property|lowerfirst}}Adapter = new QIviPagingModelQtRoAdapter(QStringLiteral("{{interface.qualified_name}}.{{property}}.") + zone, m_backend->zoneAt(zone)->{{property|getter_name}}());
+ node->enableRemoting<QIviPagingModelAddressWrapper>({{property|lowerfirst}}Adapter);
+ m_modelAdapters.insert(node, {{property|lowerfirst}}Adapter);
+{% endif %}
+{% endfor %}
+ }
+{% endif %}
+}
+
+void {{class}}::disableRemoting(QRemoteObjectHostBase *node)
+{
+ node->disableRemoting(this);
+ const auto adapterList = m_modelAdapters.values(node);
+ for (QIviPagingModelQtRoAdapter *adapter : adapterList) {
+ node->disableRemoting(adapter);
+ delete adapter;
+ }
+ m_modelAdapters.remove(node);
+}
+
{% if interface_zoned %}
QStringList {{class}}::availableZones()
{
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/adapter.h.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/adapter.h.tpl
index 27ccc31..1c20792 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/adapter.h.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/adapter.h.tpl
@@ -48,7 +48,7 @@
#include "{{interface|lower}}backend.h"
#include "rep_{{interface|lower}}_source.h"
-#include "rep_pagingmodel_source.h"
+#include "rep_qivipagingmodel_source.h"
QT_BEGIN_NAMESPACE
@@ -59,27 +59,23 @@ QT_BEGIN_NAMESPACE
*/
template <class ObjectType>
struct {{interface}}AddressWrapper: public {{interface}}SourceAPI<ObjectType> {
- {{interface}}AddressWrapper(ObjectType *object, const QString &name = QStringLiteral("{{interface.qualified_name}}"))
- : {{interface}}SourceAPI<ObjectType>(object, name)
- {}
-};
-{% for property in interface.properties %}
-{% if property.type.is_model %}
-template <class ObjectType>
-struct {{interface}}{{property}}ModelAddressWrapper: public PagingModelSourceAPI<ObjectType> {
- {{interface}}{{property}}ModelAddressWrapper(ObjectType *object, const QString &name = QStringLiteral("{{interface.qualified_name}}.{{property}}"))
- : PagingModelSourceAPI<ObjectType>(object, name)
+ {{interface}}AddressWrapper(ObjectType *object)
+ : {{interface}}SourceAPI<ObjectType>(object, object->remoteObjectsLookupName())
{}
};
-{% endif %}
-{% endfor %}
+class QIviPagingModelQtRoAdapter;
class {{class}} : public {{interface}}Source
{
Q_OBJECT
public:
- {{class}}({{interface}}Backend *parent = nullptr);
+ {{class}}({{interface}}Backend *parent);
+ {{class}}(const QString &remoteObjectsLookupName, {{interface}}Backend *parent);
+
+ QString remoteObjectsLookupName() const;
+ void enableRemoting(QRemoteObjectHostBase *node);
+ void disableRemoting(QRemoteObjectHostBase *node);
{% if interface_zoned %}
Q_INVOKABLE QStringList availableZones() override;
@@ -113,7 +109,9 @@ public Q_SLOTS:
{% endfor %}
private:
+ QString m_remoteObjectsLookupName;
{{interface}}Backend *m_backend;
+ QMultiHash<QRemoteObjectHostBase *, QIviPagingModelQtRoAdapter *> m_modelAdapters;
QIviRemoteObjectSourceHelper<{{class}}> m_helper;
};
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/core.cpp.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/core.cpp.tpl
index a792bd8..a792bd8 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/core.cpp.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/core.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/core.h.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/core.h.tpl
index a16fff3..a16fff3 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/core.h.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/core.h.tpl
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/main.cpp.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/main.cpp.tpl
index dfed9b6..8da233a 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/main.cpp.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/main.cpp.tpl
@@ -88,13 +88,10 @@ int main(int argc, char *argv[])
//Start Remoting the backends
{% for interface in module.interfaces %}
- Core::instance()->host()->enableRemoting<{{interface}}AddressWrapper>(new {{interface}}QtRoAdapter({{interface|lowerfirst}}Instance));
-{% for property in interface.properties %}
-{% if property.type.is_model %}
- Core::instance()->host()->enableRemoting<{{interface}}{{property}}ModelAddressWrapper>(qobject_cast<{{property|upperfirst}}ModelBackend *>({{interface|lowerfirst}}Instance->{{property|getter_name}}()));
-{% endif %}
-{% endfor %}
+ auto {{interface|lowerfirst}}Adapter = new {{interface}}QtRoAdapter({{interface|lowerfirst}}Instance);
+ {{interface|lowerfirst}}Adapter->enableRemoting(Core::instance()->host());
{% endfor %}
+
return app.exec();
}
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator/server.pri.tpl b/src/tools/ivigenerator/templates/server_qtro_simulator/server.pri.tpl
index b126fd6..5e8b66a 100644
--- a/src/tools/ivigenerator/templates_server_qtro_simulator/server.pri.tpl
+++ b/src/tools/ivigenerator/templates/server_qtro_simulator/server.pri.tpl
@@ -59,7 +59,6 @@ SOURCES += \
$$PWD/main.cpp \
REPC_SOURCE += \
- $$PWD/pagingmodel.rep \
{% for interface in module.interfaces %}
$$PWD/{{interface|lower}}.rep \
{% endfor %}
diff --git a/src/tools/ivigenerator/templates/test.yaml b/src/tools/ivigenerator/templates/test.yaml
new file mode 100644
index 0000000..fbd2801
--- /dev/null
+++ b/src/tools/ivigenerator/templates/test.yaml
@@ -0,0 +1,9 @@
+test:
+ module:
+ documents:
+ - "{{srcBase|lower}}.pri": "module.pri.tpl"
+ - 'main.cpp': 'main.cpp.tpl'
+ interface:
+ documents:
+ - 'tst_{{interface|lower}}.cpp': 'tst_test.cpp.tpl'
+ - 'tst_{{interface|lower}}.h': 'tst_test.h.tpl'
diff --git a/src/tools/ivigenerator/templates_test/main.cpp.tpl b/src/tools/ivigenerator/templates/test/main.cpp.tpl
index 3a767b2..3a767b2 100644
--- a/src/tools/ivigenerator/templates_test/main.cpp.tpl
+++ b/src/tools/ivigenerator/templates/test/main.cpp.tpl
diff --git a/src/tools/ivigenerator/templates_test/module.pri.tpl b/src/tools/ivigenerator/templates/test/module.pri.tpl
index d249ffc..d249ffc 100644
--- a/src/tools/ivigenerator/templates_test/module.pri.tpl
+++ b/src/tools/ivigenerator/templates/test/module.pri.tpl
diff --git a/src/tools/ivigenerator/templates_test/pagingmodel.h.tpl b/src/tools/ivigenerator/templates/test/pagingmodel.h.tpl
index 0e4bc11..0e4bc11 100644
--- a/src/tools/ivigenerator/templates_test/pagingmodel.h.tpl
+++ b/src/tools/ivigenerator/templates/test/pagingmodel.h.tpl
diff --git a/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl b/src/tools/ivigenerator/templates/test/tst_test.cpp.tpl
index d8bd0ee..d725b8b 100644
--- a/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl
+++ b/src/tools/ivigenerator/templates/test/tst_test.cpp.tpl
@@ -259,6 +259,7 @@ private:
{{interface}}Test::{{interface}}Test()
: QObject()
{
+ QCoreApplication::setLibraryPaths(QStringList());
{{module.module_name|upperfirst}}Module::registerTypes();
manager = QIviServiceManager::instance();
}
diff --git a/src/tools/ivigenerator/templates_test/tst_test.h.tpl b/src/tools/ivigenerator/templates/test/tst_test.h.tpl
index cfd145f..cfd145f 100644
--- a/src/tools/ivigenerator/templates_test/tst_test.h.tpl
+++ b/src/tools/ivigenerator/templates/test/tst_test.h.tpl
diff --git a/src/tools/ivigenerator/templates_backend_qtro.yaml b/src/tools/ivigenerator/templates_backend_qtro.yaml
deleted file mode 100644
index f8c0010..0000000
--- a/src/tools/ivigenerator/templates_backend_qtro.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "{{module.module_name|lower}}plugin.h"
- template_file: "plugin.h.tpl"
- - dest_file: "{{module.module_name|lower}}plugin.cpp"
- template_file: "plugin.cpp.tpl"
- - dest_file: "{{module.module_name|lower}}.json"
- template_file: "plugin.json"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "plugin.pri.tpl"
- - dest_file: "pagingmodel.rep"
- template_file: "common/pagingmodel.rep.tpl"
- interface_rules:
- - dest_file: '{{interface|lower}}backend.h'
- template_file: 'backend.h.tpl'
- - dest_file: '{{interface|lower}}backend.cpp'
- template_file: 'backend.cpp.tpl'
- - dest_file: "{{interface|lower}}.rep"
- template_file: "common/interface.rep.tpl"
- struct_rules:
diff --git a/src/tools/ivigenerator/templates_backend_simulator.yaml b/src/tools/ivigenerator/templates_backend_simulator.yaml
deleted file mode 100644
index 4c47848..0000000
--- a/src/tools/ivigenerator/templates_backend_simulator.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "{{module.module_name|lower}}plugin.h"
- template_file: "plugin.h.tpl"
- - dest_file: "{{module.module_name|lower}}plugin.cpp"
- template_file: "plugin.cpp.tpl"
- - dest_file: "{{module.module_name|lower}}_simulation.qml"
- template_file: "common/module_simulation.qml.tpl"
- - dest_file: "{{module.module_name|lower}}.json"
- template_file: "plugin.json"
- - dest_file: "{{module.module_name|lower}}_simulation_data.json"
- template_file: "common/simulation_data.json.tpl"
- - dest_file: "{{module.module_name|lower}}_simulation.qrc"
- template_file: "common/simulation.qrc.tpl"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "plugin.pri.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/simulation/plugins.qmltypes"
- template_file: "common/simulation.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/simulation/qmldir"
- template_file: "common/qmldir.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes"
- template_file: "common/plugins.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/qmldir"
- template_file: "common/qmldir.tpl"
- interface_rules:
- - dest_file: '{{interface|lower}}backend.h'
- template_file: 'common/backend_simulation.h.tpl'
- - dest_file: '{{interface|lower}}backend.cpp'
- template_file: 'common/backend_simulation.cpp.tpl'
- - dest_file: '{{interface|upperfirst}}Simulation.qml'
- template_file: 'common/backend_simulation.qml.tpl'
- struct_rules:
-
diff --git a/src/tools/ivigenerator/templates_frontend.yaml b/src/tools/ivigenerator/templates_frontend.yaml
deleted file mode 100644
index c455e21..0000000
--- a/src/tools/ivigenerator/templates_frontend.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "{{module.module_name|lower}}global.h"
- template_file: "global.h.tpl"
- - dest_file: "{{module.module_name|lower}}module.h"
- template_file: "module.h.tpl"
- - dest_file: "{{module.module_name|lower}}module.cpp"
- template_file: "module.cpp.tpl"
- - dest_file: "{{module.module_name|lower}}module_enum.qdocinc"
- template_file: "module_qml_enum.qdocinc.tpl"
- - dest_file: "{{module.module_name|lower}}modulefactory.h"
- template_file: "modulefactory.h.tpl"
- - dest_file: "{{module.module_name|lower}}modulefactory.cpp"
- template_file: "modulefactory.cpp.tpl"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "module.pri.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes"
- template_file: "common/plugins.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/qmldir"
- template_file: "common/qmldir.tpl"
- interface_rules:
- - dest_file: '{{interface|lower}}backendinterface.h'
- template_file: 'backendinterface.h.tpl'
- - dest_file: '{{interface|lower}}backendinterface.cpp'
- template_file: 'backendinterface.cpp.tpl'
- - dest_file: '{{interface|lower}}.h'
- template_file: 'interface.h.tpl'
- - dest_file: '{{interface|lower}}_p.h'
- template_file: 'interface_p.h.tpl'
- - dest_file: '{{interface|lower}}.cpp'
- template_file: 'interface.cpp.tpl'
- struct_rules:
- - dest_file: '{{struct|lower}}.h'
- template_file: 'struct.h.tpl'
- - dest_file: '{{struct|lower}}.cpp'
- template_file: 'struct.cpp.tpl'
diff --git a/src/tools/ivigenerator/templates_qmlplugin.yaml b/src/tools/ivigenerator/templates_qmlplugin.yaml
deleted file mode 100644
index 136f3cd..0000000
--- a/src/tools/ivigenerator/templates_qmlplugin.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "plugin.cpp"
- template_file: "plugin.cpp.tpl"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "module.pri.tpl"
- - dest_file: "plugins.qmltypes"
- template_file: "common/plugins.qmltypes.tpl"
- - dest_file: "qmldir"
- template_file: "qmldir_plugin.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes"
- template_file: "common/plugins.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/qmldir"
- template_file: "qmldir_plugin.tpl"
- interface_rules:
- struct_rules:
diff --git a/src/tools/ivigenerator/templates_server_qtro.yaml b/src/tools/ivigenerator/templates_server_qtro.yaml
deleted file mode 100644
index 3b2955d..0000000
--- a/src/tools/ivigenerator/templates_server_qtro.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "core.cpp"
- template_file: "core.cpp.tpl"
- - dest_file: "core.h"
- template_file: "core.h.tpl"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "server.pri.tpl"
- - dest_file: "pagingmodel.rep"
- template_file: "common/pagingmodel.rep.tpl"
- interface_rules:
- - dest_file: "{{interface|lower}}.rep"
- template_file: "common/interface.rep.tpl"
- struct_rules:
diff --git a/src/tools/ivigenerator/templates_server_qtro_simulator.yaml b/src/tools/ivigenerator/templates_server_qtro_simulator.yaml
deleted file mode 100644
index 5f7ab45..0000000
--- a/src/tools/ivigenerator/templates_server_qtro_simulator.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "core.cpp"
- template_file: "core.cpp.tpl"
- - dest_file: "core.h"
- template_file: "core.h.tpl"
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "server.pri.tpl"
- - dest_file: "pagingmodel.rep"
- template_file: "common/pagingmodel.rep.tpl"
- - dest_file: "main.cpp"
- template_file: "main.cpp.tpl"
- - dest_file: "{{module.module_name|lower}}_simulation.qml"
- template_file: "common/module_simulation.qml.tpl"
- - dest_file: "{{module.module_name|lower}}_simulation_data.json"
- template_file: "common/simulation_data.json.tpl"
- - dest_file: "{{module.module_name|lower}}_simulation.qrc"
- template_file: "common/simulation.qrc.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/simulation/plugins.qmltypes"
- template_file: "common/simulation.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/simulation/qmldir"
- template_file: "common/qmldir.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/plugins.qmltypes"
- template_file: "common/plugins.qmltypes.tpl"
- - dest_file: "qml/{{module|qml_type|replace('.', '/')}}/qmldir"
- template_file: "common/qmldir.tpl"
- interface_rules:
- - dest_file: "{{interface|lower}}.rep"
- template_file: "common/interface.rep.tpl"
- - dest_file: '{{interface|lower}}adapter.h'
- template_file: 'adapter.h.tpl'
- - dest_file: '{{interface|lower}}adapter.cpp'
- template_file: 'adapter.cpp.tpl'
- - dest_file: '{{interface|lower}}backend.h'
- template_file: 'common/backend_simulation.h.tpl'
- - dest_file: '{{interface|lower}}backend.cpp'
- template_file: 'common/backend_simulation.cpp.tpl'
- - dest_file: '{{interface|upperfirst}}Simulation.qml'
- template_file: 'common/backend_simulation.qml.tpl'
- struct_rules:
diff --git a/src/tools/ivigenerator/templates_test.yaml b/src/tools/ivigenerator/templates_test.yaml
deleted file mode 100644
index f7b6b64..0000000
--- a/src/tools/ivigenerator/templates_test.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-generate_rules:
- module_rules:
- - dest_file: "{{srcBase|lower}}.pri"
- template_file: "module.pri.tpl"
- - dest_file: 'main.cpp'
- template_file: 'main.cpp.tpl'
- interface_rules:
- - dest_file: 'tst_{{interface|lower}}.cpp'
- template_file: 'tst_test.cpp.tpl'
- - dest_file: 'tst_{{interface|lower}}.h'
- template_file: 'tst_test.h.tpl'
- struct_rules:
diff --git a/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.cpp b/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.cpp
index 98fc70d..926d2bb 100644
--- a/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.cpp
+++ b/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.cpp
@@ -47,7 +47,13 @@
#include <QRemoteObjectRegistryHost>
QIviMediaDiscoveryModelQtRoAdapter::QIviMediaDiscoveryModelQtRoAdapter(MediaDiscoveryBackend *parent)
- : QIviMediaDiscoveryModelSource (parent)
+ : QIviMediaDiscoveryModelQtRoAdapter(QStringLiteral("QtIviMedia.QIviMediaDiscoveryModel"), parent)
+{
+}
+
+QIviMediaDiscoveryModelQtRoAdapter::QIviMediaDiscoveryModelQtRoAdapter(const QString &remoteObjectsLookupName, MediaDiscoveryBackend *parent)
+ : QIviMediaDiscoveryModelSource(parent)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_backend(parent)
{
QMap<QString, QIviServiceObject*> deviceMap = m_backend->deviceMap();
@@ -62,6 +68,12 @@ QIviMediaDiscoveryModelQtRoAdapter::QIviMediaDiscoveryModelQtRoAdapter(MediaDisc
connect(m_backend, &MediaDiscoveryBackend::deviceRemoved, this, &QIviMediaDiscoveryModelQtRoAdapter::onDeviceRemoved);
}
+
+QString QIviMediaDiscoveryModelQtRoAdapter::remoteObjectsLookupName() const
+{
+ return m_remoteObjectsLookupName;
+}
+
QStringList QIviMediaDiscoveryModelQtRoAdapter::devices() const
{
return QStringList(m_hostMap.keys());
@@ -98,7 +110,7 @@ void QIviMediaDiscoveryModelQtRoAdapter::createDeviceAdapter(QIviMediaDevice *de
QIviSearchAndBrowseModelInterface *searchAndBrowseBackend = qivi_interface_cast<QIviSearchAndBrowseModelInterface *>(device->interfaceInstance(QStringLiteral(QIviSearchAndBrowseModel_iid)));
searchAndBrowseBackend->initialize();
- auto instance = new QIviSearchAndBrowseModelQtRoAdapter(searchAndBrowseBackend, QStringLiteral("QIviSearchAndBrowseModel_") + device->name());
+ auto instance = new QIviSearchAndBrowseModelQtRoAdapter(QStringLiteral("QIviSearchAndBrowseModel_") + device->name(), searchAndBrowseBackend);
Core::instance()->host()->enableRemoting<QIviSearchAndBrowseModelAddressWrapper>(instance);
m_hostMap.insert(device->name(), instance);
diff --git a/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.h b/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.h
index d295ac9..0debec0 100644
--- a/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.h
+++ b/src/tools/media-simulation-server/qivimediadiscoveryqtroadapter.h
@@ -49,8 +49,8 @@
template <class ObjectType>
struct QIviMediaDiscoveryModelAddressWrapper: public QIviMediaDiscoveryModelSourceAPI<ObjectType> {
- QIviMediaDiscoveryModelAddressWrapper(ObjectType *object, const QString &name = QStringLiteral("QtIviMedia.QIviMediaDiscoveryModel"))
- : QIviMediaDiscoveryModelSourceAPI<ObjectType>(object, name)
+ QIviMediaDiscoveryModelAddressWrapper(ObjectType *object)
+ : QIviMediaDiscoveryModelSourceAPI<ObjectType>(object, object->remoteObjectsLookupName())
{}
};
@@ -58,6 +58,9 @@ class QIviMediaDiscoveryModelQtRoAdapter : public QIviMediaDiscoveryModelSource
{
public:
QIviMediaDiscoveryModelQtRoAdapter(MediaDiscoveryBackend *parent);
+ QIviMediaDiscoveryModelQtRoAdapter(const QString& remoteObjectsLookupName, MediaDiscoveryBackend *parent);
+
+ QString remoteObjectsLookupName() const;
public Q_SLOTS:
QStringList devices() const override;
@@ -67,6 +70,7 @@ public Q_SLOTS:
private:
void createDeviceAdapter(QIviMediaDevice *device);
+ QString m_remoteObjectsLookupName;
MediaDiscoveryBackend *m_backend;
QHash<QString, QObject*> m_hostMap;
};
diff --git a/src/tools/media-simulation-server/qivimediaindexerqtroadapter.cpp b/src/tools/media-simulation-server/qivimediaindexerqtroadapter.cpp
index 4b7552c..087d2b3 100644
--- a/src/tools/media-simulation-server/qivimediaindexerqtroadapter.cpp
+++ b/src/tools/media-simulation-server/qivimediaindexerqtroadapter.cpp
@@ -42,13 +42,24 @@
#include "qivimediaindexerqtroadapter.h"
QIviMediaIndexerQtRoAdapter::QIviMediaIndexerQtRoAdapter(MediaIndexerBackend *parent)
- : QIviMediaIndexerSource (parent)
+ : QIviMediaIndexerQtRoAdapter(QStringLiteral("QtIviMedia.QIviMediaIndexer"), parent)
+{
+}
+
+QIviMediaIndexerQtRoAdapter::QIviMediaIndexerQtRoAdapter(const QString& remoteObjectsLookupName, MediaIndexerBackend *parent)
+ : QIviMediaIndexerSource(parent)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_backend(parent)
{
connect(m_backend, &MediaIndexerBackend::progressChanged, this, &QIviMediaIndexerQtRoAdapter::progressChanged);
connect(m_backend, &MediaIndexerBackend::stateChanged, this, &QIviMediaIndexerQtRoAdapter::stateChanged);
}
+QString QIviMediaIndexerQtRoAdapter::remoteObjectsLookupName() const
+{
+ return m_remoteObjectsLookupName;
+}
+
QIviMediaIndexerControl::State QIviMediaIndexerQtRoAdapter::state() const
{
return m_backend->state();
diff --git a/src/tools/media-simulation-server/qivimediaindexerqtroadapter.h b/src/tools/media-simulation-server/qivimediaindexerqtroadapter.h
index ac5b6ed..192b55a 100644
--- a/src/tools/media-simulation-server/qivimediaindexerqtroadapter.h
+++ b/src/tools/media-simulation-server/qivimediaindexerqtroadapter.h
@@ -47,8 +47,8 @@
template <class ObjectType>
struct QIviMediaIndexerAddressWrapper: public QIviMediaIndexerSourceAPI<ObjectType> {
- QIviMediaIndexerAddressWrapper(ObjectType *object, const QString &name = QStringLiteral("QtIviMedia.QIviMediaIndexer"))
- : QIviMediaIndexerSourceAPI<ObjectType>(object, name)
+ QIviMediaIndexerAddressWrapper(ObjectType *object)
+ : QIviMediaIndexerSourceAPI<ObjectType>(object, object->remoteObjectsLookupName())
{}
};
@@ -56,7 +56,9 @@ class QIviMediaIndexerQtRoAdapter : public QIviMediaIndexerSource
{
public:
QIviMediaIndexerQtRoAdapter(MediaIndexerBackend *parent);
+ QIviMediaIndexerQtRoAdapter(const QString& remoteObjectsLookupName, MediaIndexerBackend *parent);
+ QString remoteObjectsLookupName() const;
QIviMediaIndexerControl::State state() const override;
qreal progress() const override;
@@ -65,6 +67,7 @@ public Q_SLOTS:
QVariant resume() override;
private:
+ QString m_remoteObjectsLookupName;
MediaIndexerBackend *m_backend;
};
diff --git a/src/tools/media-simulation-server/qivimediaplayerqtroadapter.cpp b/src/tools/media-simulation-server/qivimediaplayerqtroadapter.cpp
index 64b86da..79871ec 100644
--- a/src/tools/media-simulation-server/qivimediaplayerqtroadapter.cpp
+++ b/src/tools/media-simulation-server/qivimediaplayerqtroadapter.cpp
@@ -43,7 +43,13 @@
#include "qiviqmlconversion_helper.h"
QIviMediaPlayerQtRoAdapter::QIviMediaPlayerQtRoAdapter(MediaPlayerBackend *parent)
+ : QIviMediaPlayerQtRoAdapter(QStringLiteral("QtIviMedia.QIviMediaPlayer"), parent)
+{
+}
+
+QIviMediaPlayerQtRoAdapter::QIviMediaPlayerQtRoAdapter(const QString& remoteObjectsLookupName, MediaPlayerBackend *parent)
: QIviMediaPlayerSource(parent)
+ , m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_backend(parent)
, m_helper(this)
{
@@ -62,6 +68,12 @@ QIviMediaPlayerQtRoAdapter::QIviMediaPlayerQtRoAdapter(MediaPlayerBackend *paren
connect(m_backend, &MediaPlayerBackend::countChanged, this, &QIviMediaPlayerQtRoAdapter::countChanged);
}
+
+QString QIviMediaPlayerQtRoAdapter::remoteObjectsLookupName() const
+{
+ return m_remoteObjectsLookupName;
+}
+
QIviMediaPlayer::PlayMode QIviMediaPlayerQtRoAdapter::playMode() const
{
return m_backend->playMode();
diff --git a/src/tools/media-simulation-server/qivimediaplayerqtroadapter.h b/src/tools/media-simulation-server/qivimediaplayerqtroadapter.h
index fb32bcf..b2786e8 100644
--- a/src/tools/media-simulation-server/qivimediaplayerqtroadapter.h
+++ b/src/tools/media-simulation-server/qivimediaplayerqtroadapter.h
@@ -50,8 +50,8 @@
template <class ObjectType>
struct QIviMediaPlayerAddressWrapper: public QIviMediaPlayerSourceAPI<ObjectType> {
- QIviMediaPlayerAddressWrapper(ObjectType *object, const QString &name = QStringLiteral("QtIviMedia.QIviMediaPlayer"))
- : QIviMediaPlayerSourceAPI<ObjectType>(object, name)
+ QIviMediaPlayerAddressWrapper(ObjectType *object)
+ : QIviMediaPlayerSourceAPI<ObjectType>(object, object->remoteObjectsLookupName())
{}
};
@@ -59,6 +59,9 @@ class QIviMediaPlayerQtRoAdapter : public QIviMediaPlayerSource
{
public:
QIviMediaPlayerQtRoAdapter(MediaPlayerBackend *parent);
+ QIviMediaPlayerQtRoAdapter(const QString& remoteObjectsLookupName, MediaPlayerBackend *parent);
+
+ QString remoteObjectsLookupName() const;
public:
QIviMediaPlayer::PlayMode playMode() const override;
@@ -89,6 +92,7 @@ public Q_SLOTS:
void move(int currentIndex, int newIndex) override;
private:
+ QString m_remoteObjectsLookupName;
MediaPlayerBackend *m_backend;
QIviRemoteObjectSourceHelper<QIviMediaPlayerQtRoAdapter> m_helper;
};
diff --git a/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.cpp b/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.cpp
index 0eaf3cd..e458d1e 100644
--- a/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.cpp
+++ b/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.cpp
@@ -44,7 +44,12 @@
Q_LOGGING_CATEGORY(qLcROQIviSearchAndBrowseModel, "qt.ivi.qivisearchandbrowsemodel.remoteobjects", QtInfoMsg)
-QIviSearchAndBrowseModelQtRoAdapter::QIviSearchAndBrowseModelQtRoAdapter(QIviSearchAndBrowseModelInterface *parent, const QString &remoteObjectsLookupName)
+QIviSearchAndBrowseModelQtRoAdapter::QIviSearchAndBrowseModelQtRoAdapter(QIviSearchAndBrowseModelInterface *parent)
+ : QIviSearchAndBrowseModelQtRoAdapter(QStringLiteral("QIviSearchAndBrowseModel"), parent)
+{
+}
+
+QIviSearchAndBrowseModelQtRoAdapter::QIviSearchAndBrowseModelQtRoAdapter(const QString &remoteObjectsLookupName, QIviSearchAndBrowseModelInterface *parent)
: QIviSearchAndBrowseModelSource(parent)
, m_remoteObjectsLookupName(remoteObjectsLookupName)
, m_backend(parent)
@@ -145,5 +150,3 @@ QVariant QIviSearchAndBrowseModelQtRoAdapter::indexOf(const QUuid &identifier, c
qCDebug(qLcROQIviSearchAndBrowseModel) << Q_FUNC_INFO;
return m_helper.fromPendingReply(pendingReply);
}
-
-
diff --git a/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.h b/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.h
index d665204..fdb0a0d 100644
--- a/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.h
+++ b/src/tools/media-simulation-server/qivisearchandbrowsemodelqtroadapter.h
@@ -57,7 +57,8 @@ struct QIviSearchAndBrowseModelAddressWrapper: public QIviSearchAndBrowseModelSo
class QIviSearchAndBrowseModelQtRoAdapter : public QIviSearchAndBrowseModelSource
{
public:
- QIviSearchAndBrowseModelQtRoAdapter(QIviSearchAndBrowseModelInterface *parent, const QString& remoteObjectsLookupName = QStringLiteral("QIviSearchAndBrowseModel"));
+ QIviSearchAndBrowseModelQtRoAdapter(QIviSearchAndBrowseModelInterface *parent);
+ QIviSearchAndBrowseModelQtRoAdapter(const QString& remoteObjectsLookupName, QIviSearchAndBrowseModelInterface *parent);
QString remoteObjectsLookupName() const;
QStringList availableContentTypes() const override;
diff --git a/sync.profile b/sync.profile
index 10ca36e..f35fed8 100644
--- a/sync.profile
+++ b/sync.profile
@@ -26,3 +26,7 @@
"qtmultimedia" => ""
);
+%inject_headers = (
+ "$basedir/src/helper/remoteobjects" => [ "rep_qivipagingmodel_source.h", "rep_qivipagingmodel_replica.h" ]
+)
+
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
index 43c91c2..98fecbd 100644
--- a/tests/auto/core/core.pro
+++ b/tests/auto/core/core.pro
@@ -7,6 +7,7 @@ SUBDIRS = servicemanagertest \
qivipagingmodel \
qivisearchandbrowsemodel \
qivisimulationengine \
+ qivisimulationglobalobject \
QT_FOR_CONFIG += ivicore
qtConfig(ivigenerator): SUBDIRS += ivigenerator
diff --git a/tests/auto/core/ivigenerator/include-test.qface b/tests/auto/core/ivigenerator/include-test.qface
new file mode 100644
index 0000000..dd13fe3
--- /dev/null
+++ b/tests/auto/core/ivigenerator/include-test.qface
@@ -0,0 +1,115 @@
+/**
+ * module
+ */
+module include.test 1.0
+
+import Common 1.0
+
+/**
+ * \brief the brief
+ * the description
+ * continues \l http://qt.io
+ */
+interface IncludeTester {
+ readonly string lastMessage;
+ int intValue;
+ var varValue;
+ @config_simulator: {minimum: 10.}
+ real floatValue1;
+ @config_simulator: {maximum: 10.}
+ real floatValue2;
+ string stringValue;
+
+ model<NestedStruct> nestedStructModel;
+ model<NestedImportedStruct> nestedImportedStructModel;
+ list<int> intList;
+ list<Common.CommonStruct> commonStructList;
+ list<NestedImportedStruct> nestedImportedStructList;
+ TestEnum testEnum;
+ Common.CommonEnum commonEnum;
+
+ string echo(string msg);
+ string id() const;
+ NestedStruct getNestedStruct();
+ NestedImportedStruct getNestedImportedStruct();
+ Common.CommonStruct getCommonStruct();
+ void voidSlot();
+ void voidSlot2(int param);
+ void timer(int interval);
+ Common.CommonFlag flagMethod(Common.CommonFlag testFlag);
+ Common.CommonEnum enumMethod(Common.CommonEnum testEnum);
+
+ signal anotherChanged(NestedImportedStruct another);
+ signal foobar(string foo);
+ signal somethingHappened();
+ signal newValueAvailable(var newValue);
+}
+
+@config: { zoned: true }
+interface IncludeTesterZoned {
+ readonly string lastMessage;
+ int intValue;
+ var varValue;
+ @config_simulator: {minimum: 10.}
+ real floatValue1;
+ @config_simulator: {maximum: 10.}
+ real floatValue2;
+ string stringValue;
+
+ model<NestedStruct> nestedStructModel;
+ model<NestedImportedStruct> nestedImportedStructModel;
+ list<int> intList;
+ list<Common.CommonStruct> commonStructList;
+ list<NestedImportedStruct> nestedImportedStructList;
+ TestEnum testEnum;
+ Common.CommonEnum commonEnum;
+
+ string echo(string msg);
+ string id() const;
+ NestedStruct getNestedStruct();
+ NestedImportedStruct getNestedImportedStruct();
+ Common.CommonStruct getCommonStruct();
+ void voidSlot();
+ void voidSlot2(int param);
+ void timer(int interval);
+ Common.CommonFlag flagMethod(Common.CommonFlag testFlag);
+ Common.CommonEnum enumMethod(Common.CommonEnum testEnum);
+
+ signal anotherChanged(NestedImportedStruct another);
+ signal foobar(string foo);
+ signal somethingHappened();
+ signal newValueAvailable(var newValue);
+}
+
+/**
+ * \brief A TestFlag
+ */
+flag TestFlag {
+ /**
+ * \brief The first value
+ */
+ TestFlagValue = 1,
+ /**
+ * \brief The second value
+ */
+ TestFlagValue = 2,
+}
+
+enum TestEnum {
+ FirstEnumValue = 1,
+ SecondEnumValue = 2
+}
+
+struct NestedStruct {
+ AnotherStruct anotherStruct;
+ TestEnum testEnum;
+}
+
+struct AnotherStruct {
+ int justANumber;
+}
+
+struct NestedImportedStruct {
+ Common.CommonStruct commonStruct;
+ TestFlag testFlag;
+}
diff --git a/tests/auto/core/ivigenerator/ivigenerator.pro b/tests/auto/core/ivigenerator/ivigenerator.pro
index 00f5307..26f1401 100644
--- a/tests/auto/core/ivigenerator/ivigenerator.pro
+++ b/tests/auto/core/ivigenerator/ivigenerator.pro
@@ -6,4 +6,5 @@ SUBDIRS = projects \
OTHER_FILES = org.example.echo.qface \
org.example.echo.yaml \
org.example.echo.noannotation.qface \
- no-private.yaml
+ no-private.yaml \
+ include-test.qface \
diff --git a/tests/auto/core/ivigenerator/org.example.echo.qface b/tests/auto/core/ivigenerator/org.example.echo.qface
index 17a519c..faed373 100644
--- a/tests/auto/core/ivigenerator/org.example.echo.qface
+++ b/tests/auto/core/ivigenerator/org.example.echo.qface
@@ -34,6 +34,9 @@ interface Echo {
WeekDay weekDay;
TestEnum testEnum;
real UPPERCASEPROPERTY;
+ /* AUTOSUITE-1340 */
+ @config_simulator: { default: ["Hello Qt"] }
+ OnlyAStringInAStruct stringInAStructProperty;
string echo(string msg);
string id() const;
@@ -144,3 +147,8 @@ struct Combo {
struct AnotherStruct {
int justANumber;
}
+
+/* AUTOSUITE-1340 */
+struct OnlyAStringInAStruct {
+ string myString;
+}
diff --git a/tests/auto/core/ivigenerator/projects/include-test/backend_qtro/backend_qtro.pro b/tests/auto/core/ivigenerator/projects/include-test/backend_qtro/backend_qtro.pro
new file mode 100644
index 0000000..fe69f82
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/backend_qtro/backend_qtro.pro
@@ -0,0 +1,16 @@
+TEMPLATE=lib
+TARGET = $$qtLibraryTarget(include_test_qtro)
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_frontend) -l$$qtLibraryTarget(include_test_common)
+DESTDIR = ../qtivi
+
+CONFIG += warn_off ivigenerator plugin
+
+INCLUDEPATH += $$OUT_PWD/../frontend $$OUT_PWD/../common
+PLUGIN_TYPE = qtivi
+PLUGIN_CLASS_NAME = IncludeTestQtROPlugin
+
+QT += core ivicore
+
+QFACE_FORMAT = backend_qtro
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
diff --git a/tests/auto/core/ivigenerator/projects/include-test/backend_simulator/backend_simulator.pro b/tests/auto/core/ivigenerator/projects/include-test/backend_simulator/backend_simulator.pro
new file mode 100644
index 0000000..b48d2c8
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/backend_simulator/backend_simulator.pro
@@ -0,0 +1,16 @@
+TEMPLATE=lib
+TARGET = $$qtLibraryTarget(include_test_simulator)
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_frontend) -l$$qtLibraryTarget(include_test_common)
+DESTDIR = ../qtivi
+
+CONFIG += warn_off ivigenerator plugin
+
+INCLUDEPATH += $$OUT_PWD/../frontend $$OUT_PWD/../common
+PLUGIN_TYPE = qtivi
+PLUGIN_CLASS_NAME = IncludeTestSimulatorPlugin
+
+QT += core ivicore
+
+QFACE_FORMAT = backend_simulator
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
diff --git a/tests/auto/core/ivigenerator/projects/include-test/common/common.pro b/tests/auto/core/ivigenerator/projects/include-test/common/common.pro
new file mode 100644
index 0000000..306669a
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/common/common.pro
@@ -0,0 +1,14 @@
+TEMPLATE=lib
+TARGET= $$qtLibraryTarget(include_test_common)
+DESTDIR = ../
+
+CONFIG += ivigenerator
+
+QT += ivicore ivicore-private qml quick
+
+DEFINES += QT_BUILD_COMMON_LIB
+
+macos: QMAKE_SONAME_PREFIX = @rpath
+
+QFACE_SOURCES = "../../../qface imports/common.qface"
+
diff --git a/tests/auto/core/ivigenerator/projects/include-test/frontend/frontend.pro b/tests/auto/core/ivigenerator/projects/include-test/frontend/frontend.pro
new file mode 100644
index 0000000..e287e47
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/frontend/frontend.pro
@@ -0,0 +1,17 @@
+TEMPLATE=lib
+TARGET= $$qtLibraryTarget(include_test_frontend)
+DESTDIR = ../
+
+CONFIG += ivigenerator
+
+QT += ivicore ivicore-private qml quick
+
+DEFINES += QT_BUILD_INCLUDE_TEST_LIB
+INCLUDEPATH += $$OUT_PWD/../common
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_common)
+
+macos: QMAKE_SONAME_PREFIX = @rpath
+
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
+
diff --git a/tests/auto/core/ivigenerator/projects/include-test/include-test.pro b/tests/auto/core/ivigenerator/projects/include-test/include-test.pro
new file mode 100644
index 0000000..3febe98
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/include-test.pro
@@ -0,0 +1,22 @@
+TEMPLATE = subdirs
+
+SUBDIRS = common \
+ frontend \
+ qmlplugin \
+ backend_simulator \
+ test \
+
+frontend.depends = common
+backend_simulator.depends = frontend
+test.depends = frontend
+qmlplugin.depends = frontend
+
+QT_FOR_CONFIG += ivicore
+
+qtConfig(remoteobjects) {
+ SUBDIRS += backend_qtro \
+ simulation_server_qtro
+
+ backend_qtro.depends = frontend
+ simulation_server_qtro.depends = frontend
+}
diff --git a/tests/auto/core/ivigenerator/projects/include-test/qmlplugin/qmlplugin.pro b/tests/auto/core/ivigenerator/projects/include-test/qmlplugin/qmlplugin.pro
new file mode 100644
index 0000000..b0a45d8
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/qmlplugin/qmlplugin.pro
@@ -0,0 +1,12 @@
+TEMPLATE = lib
+QT = ivicore
+CONFIG += c++11 plugin
+
+INCLUDEPATH += $$OUT_PWD/../frontend $$OUT_PWD/../common
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_frontend) -l$$qtLibraryTarget(include_test_common)
+
+QFACE_FORMAT = qmlplugin
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
+
+load(ivigenerator)
diff --git a/tests/auto/core/ivigenerator/projects/include-test/simulation_server_qtro/simulation_server_qtro.pro b/tests/auto/core/ivigenerator/projects/include-test/simulation_server_qtro/simulation_server_qtro.pro
new file mode 100644
index 0000000..2618076
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/simulation_server_qtro/simulation_server_qtro.pro
@@ -0,0 +1,16 @@
+TEMPLATE = app
+TARGET = org-example-echo-qtro-simulation-server
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_frontend) -l$$qtLibraryTarget(include_test_common)
+
+DESTDIR = ..
+
+CONFIG += c++11 ivigenerator
+CONFIG -= app_bundle
+
+INCLUDEPATH += $$OUT_PWD/../frontend $$OUT_PWD/../common
+
+QT += qml quick core ivicore
+
+QFACE_FORMAT = server_qtro_simulator
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
diff --git a/tests/auto/core/ivigenerator/projects/include-test/test/test.pro b/tests/auto/core/ivigenerator/projects/include-test/test/test.pro
new file mode 100644
index 0000000..6b7e344
--- /dev/null
+++ b/tests/auto/core/ivigenerator/projects/include-test/test/test.pro
@@ -0,0 +1,15 @@
+TARGET = tst_include
+QMAKE_PROJECT_NAME = $$TARGET
+DESTDIR = ../
+
+QT += testlib core ivicore
+CONFIG += c++11 ivigenerator testcase
+
+INCLUDEPATH += $$OUT_PWD/../frontend $$OUT_PWD/../common
+LIBS += -L$$OUT_PWD/.. -l$$qtLibraryTarget(include_test_frontend) -l$$qtLibraryTarget(include_test_common)
+
+QMAKE_RPATHDIR += $$OUT_PWD/..
+
+QFACE_FORMAT = test
+QFACE_SOURCES = ../../../include-test.qface
+QFACE_IMPORT_PATH += "../../../qface imports"
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_qtro/backend_qtro.pro b/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_qtro/backend_qtro.pro
index 4f13551..3fd1d44 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_qtro/backend_qtro.pro
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_qtro/backend_qtro.pro
@@ -7,7 +7,7 @@ CONFIG += warn_off ivigenerator plugin
INCLUDEPATH += $$OUT_PWD/../frontend
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = EchoPlugin
+PLUGIN_CLASS_NAME = EchoQtROPlugin
QT += core ivicore
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_simulator/backend_simulator.pro b/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_simulator/backend_simulator.pro
index ffefda0..e8eedb7 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_simulator/backend_simulator.pro
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-noannotation/backend_simulator/backend_simulator.pro
@@ -7,7 +7,7 @@ CONFIG += warn_off ivigenerator plugin
INCLUDEPATH += $$OUT_PWD/../frontend
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = EchoPlugin
+PLUGIN_CLASS_NAME = EchoSimulatorPlugin
QT += core ivicore
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-noprivate/backend_simulator/backend_simulator.pro b/tests/auto/core/ivigenerator/projects/org-example-echo-noprivate/backend_simulator/backend_simulator.pro
index c3ac195..fe5ec81 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-noprivate/backend_simulator/backend_simulator.pro
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-noprivate/backend_simulator/backend_simulator.pro
@@ -7,7 +7,7 @@ CONFIG += warn_off ivigenerator plugin
INCLUDEPATH += $$OUT_PWD/../frontend
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = EchoPlugin
+PLUGIN_CLASS_NAME = EchoSimulatorPlugin
QT += core ivicore
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/backend_qtro/backend_qtro.pro b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/backend_qtro/backend_qtro.pro
index 09efc01..3c84052 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/backend_qtro/backend_qtro.pro
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/backend_qtro/backend_qtro.pro
@@ -7,7 +7,7 @@ CONFIG += warn_off ivigenerator plugin
INCLUDEPATH += $$OUT_PWD/../frontend
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = EchoPlugin
+PLUGIN_CLASS_NAME = EchoQtROPlugin
QT += core ivicore
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.cpp b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.cpp
index 2e7d542..78584de 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.cpp
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.cpp
@@ -30,7 +30,7 @@
#include "contactsmodelservice.h"
ContactsModelService::ContactsModelService(QObject* parent)
- : PagingModelSimpleSource(parent)
+ : QIviPagingModelSimpleSource(parent)
{
}
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.h b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.h
index 5a257f5..6578fa8 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.h
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/contactsmodelservice.h
@@ -31,9 +31,9 @@
#define CONTACTSMODELSERVICE_H
#include "contact.h"
-#include "rep_pagingmodel_source.h"
+#include "rep_qivipagingmodel_source.h"
-class ContactsModelService : public PagingModelSimpleSource
+class ContactsModelService : public QIviPagingModelSimpleSource
{
public:
ContactsModelService(QObject* parent = nullptr);
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/tst_echoqtro.cpp b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/tst_echoqtro.cpp
index 6f16ae2..2befbe2 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/tst_echoqtro.cpp
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo-qtro/server_qtro_test/tst_echoqtro.cpp
@@ -28,7 +28,6 @@
****************************************************************************/
#include "tst_echoqtro.h"
-#include "echoplugin.h"
#include "server.h"
#include "echo.h"
#include "echozoned.h"
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.cpp b/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.cpp
index f0dca77..d2bb99f 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.cpp
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.cpp
@@ -1,10 +1,10 @@
#include "echobackend.h"
#include "echozonedbackend.h"
-#include "echoplugin.h"
+#include "echosimulatorplugin.h"
QT_BEGIN_NAMESPACE
-extern QVector<QIviFeatureInterface *> echoInterfaceBuilder(EchoPlugin *plugin)
+extern QVector<QIviFeatureInterface *> echoInterfaceBuilder(EchoSimulatorPlugin *plugin)
{
QVector<QIviFeatureInterface *> res;
res << new EchoBackend(plugin);
diff --git a/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.pro b/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.pro
index 9922d05..242a073 100644
--- a/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.pro
+++ b/tests/auto/core/ivigenerator/projects/org-example-echo/backend_simulator/backend_simulator.pro
@@ -7,7 +7,7 @@ CONFIG += warn_off ivigenerator plugin
INCLUDEPATH += $$OUT_PWD/../frontend
PLUGIN_TYPE = qtivi
-PLUGIN_CLASS_NAME = EchoPlugin
+PLUGIN_CLASS_NAME = EchoSimulatorPlugin
QT += core ivicore
diff --git a/tests/auto/core/ivigenerator/projects/projects.pro b/tests/auto/core/ivigenerator/projects/projects.pro
index bc349a5..eb8d2b7 100644
--- a/tests/auto/core/ivigenerator/projects/projects.pro
+++ b/tests/auto/core/ivigenerator/projects/projects.pro
@@ -5,6 +5,7 @@ QT_FOR_CONFIG += ivicore
SUBDIRS = org-example-echo \
org-example-echo-noprivate \
org-example-echo-noannotation \
+ include-test \
qtConfig(remoteobjects) {
SUBDIRS += org-example-echo-qtro
diff --git a/tests/auto/core/ivigenerator/qface imports/common.qface b/tests/auto/core/ivigenerator/qface imports/common.qface
new file mode 100644
index 0000000..b9cee0c
--- /dev/null
+++ b/tests/auto/core/ivigenerator/qface imports/common.qface
@@ -0,0 +1,20 @@
+module Common 1.0;
+
+struct CommonStruct {
+ string name
+ OtherCommonStruct otherStruct
+}
+
+struct OtherCommonStruct {
+ bool checked
+}
+
+enum CommonEnum {
+ CommonValue1,
+ CommonValue2
+}
+
+flag CommonFlag {
+ FlagValue1 = 1,
+ FlagValue2 = 2
+}
diff --git a/tests/auto/core/qivisimulationengine/invalid-data.json b/tests/auto/core/qivisimulationengine/invalid-data.json
new file mode 100644
index 0000000..a39ad5e
--- /dev/null
+++ b/tests/auto/core/qivisimulationengine/invalid-data.json
@@ -0,0 +1,20 @@
+{
+ "AddressBook": {
+ "contacts": {
+ "default": [
+ {
+ "type": "Contact",
+ "value": [
+ "John",
+ "Doe",
+ "12345"
+ ]
+ },
+ {
+ "type": "Contact",
+ "value": [
+ "Jane",
+ "Doe",
+ "67890"
+ ]
+ }
diff --git a/tests/auto/core/qivisimulationengine/qivisimulationengine.pro b/tests/auto/core/qivisimulationengine/qivisimulationengine.pro
index 86245de..e77167f 100644
--- a/tests/auto/core/qivisimulationengine/qivisimulationengine.pro
+++ b/tests/auto/core/qivisimulationengine/qivisimulationengine.pro
@@ -8,3 +8,6 @@ TEMPLATE = app
SOURCES += \
tst_qivisimulationengine.cpp
+
+RESOURCES += \
+ resource.qrc
diff --git a/tests/auto/core/qivisimulationengine/resource.qrc b/tests/auto/core/qivisimulationengine/resource.qrc
new file mode 100644
index 0000000..c77f7d5
--- /dev/null
+++ b/tests/auto/core/qivisimulationengine/resource.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>invalid-data.json</file>
+ <file>simple.json</file>
+ <file>simple.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/core/qivisimulationengine/simple.json b/tests/auto/core/qivisimulationengine/simple.json
new file mode 100644
index 0000000..5786c26
--- /dev/null
+++ b/tests/auto/core/qivisimulationengine/simple.json
@@ -0,0 +1,3 @@
+{
+ "bool": true
+}
diff --git a/tests/auto/core/qivisimulationengine/simple.qml b/tests/auto/core/qivisimulationengine/simple.qml
new file mode 100644
index 0000000..f3dc525
--- /dev/null
+++ b/tests/auto/core/qivisimulationengine/simple.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+
+}
diff --git a/tests/auto/core/qivisimulationengine/tst_qivisimulationengine.cpp b/tests/auto/core/qivisimulationengine/tst_qivisimulationengine.cpp
index 18784ad..79e149a 100644
--- a/tests/auto/core/qivisimulationengine/tst_qivisimulationengine.cpp
+++ b/tests/auto/core/qivisimulationengine/tst_qivisimulationengine.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2019 Luxoft Sweden AB
** Copyright (C) 2018 Pelagicore AG
@@ -34,6 +34,9 @@
#include <QQmlContext>
#include <QQmlComponent>
#include <QScopedPointer>
+#include <QJsonDocument>
+
+#include <private/qivisimulationglobalobject_p.h>
class BaseClass : public QObject
{
@@ -237,9 +240,17 @@ class tst_QIviSimulationEngine : public QObject
{
Q_OBJECT
+ QVariant parseJson(const QString &json, QString &error) const;
+
private Q_SLOTS:
void testUsageInCorrectEngine();
+ //QIviSimulationEngine
+ void testOverrideEnvVariables();
+ void testLoadSimulationData_data();
+ void testLoadSimulationData();
+
+ //QML integration
void testPropertyRead_data();
void testPropertyRead();
void testPropertyReadDerived_data();
@@ -264,6 +275,16 @@ private Q_SLOTS:
void testMultipleInstances();
};
+QVariant tst_QIviSimulationEngine::parseJson(const QString &json, QString& error) const
+{
+ QJsonParseError pe;
+ QVariantMap data = QJsonDocument::fromJson(json.toUtf8(), &pe).toVariant().toMap();
+ if (pe.error != QJsonParseError::NoError)
+ error = pe.errorString();
+
+ return data;
+}
+
void tst_QIviSimulationEngine::testUsageInCorrectEngine()
{
QIviSimulationEngine engine;
@@ -290,6 +311,51 @@ void tst_QIviSimulationEngine::testUsageInCorrectEngine()
QCOMPARE(testObject.propertyInBase(), -1);
}
+void tst_QIviSimulationEngine::testOverrideEnvVariables()
+{
+ qputenv("QTIVI_SIMULATION_OVERRIDE", "testEngine=test.qml;testEngine=invalidQml=;overrideTest=:/simple.qml");
+ qputenv("QTIVI_SIMULATION_DATA_OVERRIDE", "testEngine=test.json;testEngine=invalid=;overrideTest=:/simple.json");
+ QIviSimulationEngine engine(QStringLiteral("overrideTest"));
+
+ QTest::ignoreMessage(QtWarningMsg, "Ignoring malformed override: File does not exist: 'test.json'");
+ QTest::ignoreMessage(QtWarningMsg, "Ignoring malformed override: 'testEngine=invalid='");
+ QTest::ignoreMessage(QtWarningMsg, "Ignoring malformed override: File does not exist: 'test.qml'");
+ QTest::ignoreMessage(QtWarningMsg, "Ignoring malformed override: 'testEngine=invalidQml='");
+
+ QTest::ignoreMessage(QtWarningMsg, "Detected matching simulation data override: overrideTest=:/simple.json");
+ engine.loadSimulationData(QStringLiteral("invalid.json"));
+
+ auto globalObject = engine.rootContext()->contextProperty(QStringLiteral("IviSimulator")).value<QIviSimulationGlobalObject*>();
+ QVariant simulationData = globalObject->simulationData();
+ QVERIFY(simulationData.isValid());
+
+ QTest::ignoreMessage(QtWarningMsg, "Detected matching simulation override: overrideTest=qrc:/simple.qml");
+ engine.loadSimulation(QStringLiteral("invalid.qml"));
+}
+
+void tst_QIviSimulationEngine::testLoadSimulationData_data()
+{
+ QTest::addColumn<QString>("simulationData");
+ QTest::addColumn<QStringList>("expectedErrors");
+ QTest::newRow("no such file") << "no-file.json" << QStringList("Cannot open the simulation data file no-file.json:*");
+ QTest::newRow("invalid json") << ":/invalid-data.json" << QStringList({ "Error parsing the simulation data in :/invalid-data.json: unterminated array", "Error context:\n.*" });
+ QTest::newRow("valid json") << ":/simple.json" << QStringList();
+}
+
+void tst_QIviSimulationEngine::testLoadSimulationData()
+{
+ QFETCH(QString, simulationData);
+ QFETCH(QStringList, expectedErrors);
+
+ QIviSimulationEngine engine(QStringLiteral("loadingTest"));
+ for (const QString &error : expectedErrors)
+ QTest::ignoreMessage(QtCriticalMsg, QRegularExpression(error));
+ engine.loadSimulationData(simulationData);
+
+ auto globalObject = engine.rootContext()->contextProperty(QStringLiteral("IviSimulator")).value<QIviSimulationGlobalObject*>();
+ QCOMPARE(globalObject->simulationData().isValid(), expectedErrors.isEmpty());
+}
+
void tst_QIviSimulationEngine::testPropertyRead_data()
{
QTest::addColumn<QByteArray>("property");
diff --git a/tests/auto/core/qivisimulationglobalobject/qivisimulationglobalobject.pro b/tests/auto/core/qivisimulationglobalobject/qivisimulationglobalobject.pro
new file mode 100644
index 0000000..ad61137
--- /dev/null
+++ b/tests/auto/core/qivisimulationglobalobject/qivisimulationglobalobject.pro
@@ -0,0 +1,10 @@
+QT += testlib ivicore ivicore-private qml
+
+TARGET = tst_qivisimulationglobalobject
+QMAKE_PROJECT_NAME = $$TARGET
+CONFIG += testcase
+
+TEMPLATE = app
+
+SOURCES += \
+ tst_qivisimulationglobalobject.cpp
diff --git a/tests/auto/core/qivisimulationglobalobject/tst_qivisimulationglobalobject.cpp b/tests/auto/core/qivisimulationglobalobject/tst_qivisimulationglobalobject.cpp
new file mode 100644
index 0000000..546520a
--- /dev/null
+++ b/tests/auto/core/qivisimulationglobalobject/tst_qivisimulationglobalobject.cpp
@@ -0,0 +1,490 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtIvi module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT-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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QQmlEngine>
+#include <QQmlContext>
+#include <QQmlComponent>
+#include <QScopedPointer>
+#include <QJsonDocument>
+
+#include <private/qivisimulationglobalobject_p.h>
+
+class InvalidStruct {
+ Q_GADGET
+ Q_PROPERTY(int intProperty READ intProperty)
+
+public:
+ int intProperty() const { return m_intProperty; }
+
+private:
+ int m_intProperty = -1;
+};
+
+
+class InvalidStruct2 {
+ Q_GADGET
+ Q_PROPERTY(int intProperty READ intProperty)
+
+public:
+ int intProperty() const { return m_intProperty; }
+
+private:
+ int m_intProperty = -1;
+};
+
+class TestStruct {
+ Q_GADGET
+ Q_PROPERTY(int intProperty READ intProperty)
+ Q_PROPERTY(bool boolProperty READ boolProperty)
+
+public:
+ TestStruct(int intProperty = -1, bool boolProperty = false)
+ : m_intProperty(intProperty)
+ , m_boolProperty(boolProperty)
+ {
+ static bool once = false;
+ if (!once)
+ QMetaType::registerEqualsComparator<TestStruct>();
+ once = true;
+ }
+
+ int intProperty() const { return m_intProperty; }
+ bool boolProperty() const { return m_boolProperty; }
+
+ bool operator==(const TestStruct& other) const {
+ return (m_intProperty == other.m_intProperty &&
+ m_boolProperty == other.m_boolProperty);
+ }
+
+protected:
+ Q_INVOKABLE void fromJSON(const QVariant &variant) {
+ QVariant value = qtivi_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();
+ if (map.contains(QStringLiteral("intProperty")))
+ m_intProperty = map.value(QStringLiteral("intProperty")).value<int>();
+ if (map.contains(QStringLiteral("boolProperty")))
+ m_boolProperty = map.value(QStringLiteral("boolProperty")).value<bool>();
+ } else if (value.type() == QVariant::List) {
+ QVariantList values = value.toList();
+ m_intProperty = values.value(0).value<int>();
+ m_boolProperty = values.value(1).value<bool>();
+ }
+ }
+
+private:
+ int m_intProperty = -1;
+ bool m_boolProperty = false;
+};
+
+class TestStructModelBackend : public QIviPagingModelInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ TestStructModelBackend(QObject* parent)
+ : QIviPagingModelInterface(parent)
+ {
+ qRegisterMetaType<QIviPagingModelInterface*>();
+ }
+
+ void initialize() override {
+ Q_EMIT initializationDone();
+ }
+
+ void registerInstance(const QUuid &identifier) override {
+ Q_EMIT countChanged(identifier, m_list.count());
+ }
+
+ void unregisterInstance(const QUuid &identifier) override {
+ Q_UNUSED(identifier)
+ }
+
+ void fetchData(const QUuid &identifier, int start, int count) override {
+ Q_UNUSED(identifier)
+ Q_UNUSED(start)
+ Q_UNUSED(count)
+ }
+
+ Q_INVOKABLE void insert(int index, const TestStruct &item) {
+ m_list.insert(index, item);
+
+ Q_EMIT dataChanged(QUuid(), { QVariant::fromValue(item) }, index, 0);
+ Q_EMIT countChanged(QUuid(), m_list.count());
+ }
+
+ int count() const {
+ return m_list.count();
+ }
+
+private:
+ QList<TestStruct> m_list;
+};
+
+class SimpleAPI: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int testProperty READ testProperty WRITE setTestProperty NOTIFY testPropertyChanged)
+ Q_PROPERTY(QIviPagingModelInterface *modelProperty READ modelProperty CONSTANT)
+
+public:
+ enum TestEnum {
+ EnumValue0 = 0,
+ EnumValue1 = 1,
+ EnumValue2 = 2
+ };
+ Q_ENUM(TestEnum)
+
+ int testProperty() const { return m_testProperty; }
+
+ QIviPagingModelInterface *modelProperty() const { return m_modelProperty; }
+
+public slots:
+ void setTestProperty(int testProperty)
+ {
+ if (m_testProperty == testProperty)
+ return;
+
+ m_testProperty = testProperty;
+ emit testPropertyChanged(testProperty);
+ }
+
+signals:
+ void testPropertyChanged(int testProperty);
+
+public:
+ int m_testProperty = -1;
+ QIviPagingModelInterface *m_modelProperty = new TestStructModelBackend(this);
+};
+
+class Zone: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int testProperty READ testProperty WRITE setTestProperty NOTIFY testPropertyChanged)
+
+public:
+ Zone(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ }
+
+ int testProperty() const { return m_testProperty; }
+
+public slots:
+ void setTestProperty(int testProperty)
+ {
+ if (m_testProperty == testProperty)
+ return;
+
+ m_testProperty = testProperty;
+ emit testPropertyChanged(testProperty);
+ }
+
+signals:
+ void testPropertyChanged(int testProperty);
+
+public:
+ int m_testProperty = -1;
+};
+
+class ZonedAPI: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlPropertyMap *zones READ zones CONSTANT)
+
+public:
+ ZonedAPI()
+ {
+ m_zones->insert("leftZone", QVariant::fromValue(new Zone(this)));
+ }
+
+ QQmlPropertyMap *zones() const { return m_zones; }
+
+public:
+ QQmlPropertyMap *m_zones = new QQmlPropertyMap(this);
+};
+
+class tst_QIviSimulationGlobalObject : public QObject
+{
+ Q_OBJECT
+
+ QVariant parseJson(const QString &json, QString &error) const;
+
+private Q_SLOTS:
+ void testFindData_data();
+ void testFindData();
+ void testConvertFromJSONErrors_data();
+ void testConvertFromJSONErrors();
+ void testParseDomainValue_data();
+ void testParseDomainValue();
+ void testInitializeDefault();
+ void testCheckSettings_data();
+ void testCheckSettings();
+ void testConstraint_data();
+ void testConstraint();
+};
+
+QVariant tst_QIviSimulationGlobalObject::parseJson(const QString &json, QString& error) const
+{
+ QJsonParseError pe;
+ QVariantMap data = QJsonDocument::fromJson(json.toUtf8(), &pe).toVariant().toMap();
+ if (pe.error != QJsonParseError::NoError)
+ error = pe.errorString();
+
+ return data;
+}
+void tst_QIviSimulationGlobalObject::testFindData_data()
+{
+ QTest::addColumn<QString>("searchString");
+ QTest::addColumn<QVariantMap>("expectedResult");
+ QTest::newRow("simple") << "Dummy" << QVariantMap({{"test", QVariant(true)}});
+ QTest::newRow("fully-qualified") << "qt-project.ClimateControl" << QVariantMap({{"test", QVariant(false)}});
+ QTest::newRow("partial match") << "org.qt-project.ClimateControl" << QVariantMap({{"test", QVariant(false)}});
+ QTest::newRow("not data") << "AddressBook" << QVariantMap();
+ QTest::newRow("not data complex") << "org.qt-project.AddressBook" << QVariantMap();
+}
+
+void tst_QIviSimulationGlobalObject::testFindData()
+{
+ QFETCH(QString, searchString);
+ QFETCH(QVariantMap, expectedResult);
+
+ QString error;
+ QVariant data = parseJson("{ \"Dummy\": { \"test\": true }, \"qt-project.ClimateControl\": { \"test\": false } }", error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ QIviSimulationGlobalObject globalObject;
+
+ QVariantMap foundData = globalObject.findData(data.toMap(), searchString);
+ QCOMPARE(foundData, expectedResult);
+}
+
+void tst_QIviSimulationGlobalObject::testConvertFromJSONErrors_data()
+{
+ qRegisterMetaType<SimpleAPI*>();
+ qRegisterMetaType<InvalidStruct2>();
+
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QStringList>("warnings");
+
+ QTest::newRow("invalid Struct") << "{ \"type\": \"InvalidStruct\", \"value\": [ 100, true ] }" <<
+ QStringList({"Couldn't retrieve MetaObject for struct parsing: *",
+ "Please make sure InvalidStruct is registered in *"});
+
+ QTest::newRow("no fromJSON") << "{ \"type\": \"InvalidStruct2\", \"value\": [ 100, true ] }" <<
+ QStringList("Couldn't find method: InvalidStruct2::fromJSON(QVariant)*");
+
+ QTest::newRow("invalid Enum") << "{ \"type\": \"enum\", \"value\": \"InvalidEnum::Foo\" }" <<
+ QStringList({"Couldn't retrieve MetaObject for enum parsing: *",
+ "Please make sure InvalidEnum\\* is registered in *"});
+
+ QTest::newRow("invalid Enum Value") << "{ \"type\": \"enum\", \"value\": \"SimpleAPI::Foo\" }" <<
+ QStringList("Couldn't parse the enum definition *");
+}
+
+void tst_QIviSimulationGlobalObject::testConvertFromJSONErrors()
+{
+ QFETCH(QString, json);
+ QFETCH(QStringList, warnings);
+
+ QString error;
+ QVariant data = parseJson(json, error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ for (const QString &warning : warnings)
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning));
+ QVariant result = qtivi_convertFromJSON(data);
+}
+
+void tst_QIviSimulationGlobalObject::testParseDomainValue_data()
+{
+ qRegisterMetaType<SimpleAPI*>();
+
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QVariant>("expectedResult");
+ QTest::newRow("float") << "15.6" << QVariant(15.6);
+ QTest::newRow("string") << "\"testString\"" << QVariant("testString");
+ QTest::newRow("int list") << "[ 1, 2, 3]" << QVariant(QVariantList({ 1, 2, 3}));
+ QTest::newRow("map") << "{ \"key1\": 1, \"key2\": \"string\" }" << QVariant(QVariantMap({ {"key1", 1}, {"key2", "string"} }));
+ QTest::newRow("TestEnum") << "{ \"type\": \"enum\", \"value\": \"SimpleAPI::EnumValue1\" }"
+ << QVariant::fromValue(SimpleAPI::EnumValue1);
+ QTest::newRow("TestStruct by list") << "{ \"type\": \"TestStruct\", \"value\": [ 100, true ] }"
+ << QVariant::fromValue(TestStruct(100, true));
+ QTest::newRow("TestStruct by map") << "{ \"type\": \"TestStruct\", \"value\": { \"intProperty\": 100, \"boolProperty\": true } }"
+ << QVariant::fromValue(TestStruct(100, true));
+}
+
+void tst_QIviSimulationGlobalObject::testParseDomainValue()
+{
+ QFETCH(QString, json);
+ QFETCH(QVariant, expectedResult);
+
+ QIviSimulationGlobalObject globalObject;
+
+ // Test normal unzoned data
+ QString error;
+ QVariant data = parseJson(QString("{ \"default\": %1 }").arg(json), error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ QVariant foundData = globalObject.parseDomainValue(data.toMap(), "default");
+ QCOMPARE(foundData, expectedResult);
+
+ // Test zoned data
+ data = parseJson(QString("{\"default\": { \"leftZone\": %1, \"=\": %1 }}").arg(json), error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ // Left zone
+ foundData = globalObject.parseDomainValue(data.toMap(), "default", "leftZone");
+ QCOMPARE(foundData, expectedResult);
+
+ // General zone
+ foundData = globalObject.parseDomainValue(data.toMap(), "default");
+ QCOMPARE(foundData, expectedResult);
+}
+
+void tst_QIviSimulationGlobalObject::testInitializeDefault()
+{
+ QIviSimulationGlobalObject globalObject;
+ SimpleAPI simple;
+ ZonedAPI zoned;
+
+ //Simple Property
+ QString error;
+ QVariant data = parseJson(QString("{ \"testProperty\": { \"default\": 100 } }"), error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ QSignalSpy spy(&simple, &SimpleAPI::testPropertyChanged);
+ globalObject.initializeDefault(data.toMap(), &simple);
+ QVERIFY(spy.count());
+ QVERIFY(spy.at(0).count());
+ QCOMPARE(spy.at(0).at(0).toInt(), 100);
+
+ //Model Property
+ data = parseJson(QString("{ \"modelProperty\": { \"default\": [{ \"type\": \"TestStruct\", \"value\": [ 100, true ] }] } }"), error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ QSignalSpy modelspy(simple.modelProperty(), &TestStructModelBackend::countChanged);
+ globalObject.initializeDefault(data.toMap(), &simple);
+ QVERIFY(modelspy.count());
+ QCOMPARE(modelspy.at(0).count(), 2);
+ QCOMPARE(modelspy.at(0).at(1).toInt(), 1);
+
+ //Zoned Property
+
+ // This is the simplified version which would apply the same default value to all available
+ // zones within the 'zones' list
+ data = parseJson(QString(" { \"zones\": [\"leftZone\"], \"testProperty\": { \"default\": 100 } }"), error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ Zone *leftZone = zoned.zones()->value("leftZone").value<Zone*>();
+ QVERIFY(leftZone);
+
+ QSignalSpy zoneSpy(leftZone, &Zone::testPropertyChanged);
+ globalObject.initializeDefault(data.toMap(), &zoned);
+ QVERIFY(zoneSpy.count());
+ QVERIFY(zoneSpy.at(0).count());
+ QCOMPARE(zoneSpy.at(0).at(0).toInt(), 100);
+}
+
+void tst_QIviSimulationGlobalObject::testCheckSettings_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QVariant>("value");
+ QTest::addColumn<bool>("expectedResult");
+ QTest::newRow("unsupported") << "{ \"unsupported\": true }" << QVariant(1) << false;
+ QTest::newRow("unsupported false") << "{ \"unsupported\": false }" << QVariant(1) << true;
+ QTest::newRow("minDomain") << "{ \"minimum\": 10 }" << QVariant(11) << true;
+ QTest::newRow("minDomain false") << "{ \"minimum\": 10 }" << QVariant(1) << false;
+ QTest::newRow("maxDomain") << "{ \"maximum\": 10 }" << QVariant(10) << true;
+ QTest::newRow("maxDomain false") << "{ \"maximum\": 10 }" << QVariant(11) << false;
+ QTest::newRow("range") << "{ \"range\": [0, 10] }" << QVariant(5) << true;
+ QTest::newRow("range low") << "{ \"range\": [0, 10] }" << QVariant(-5) << false;
+ QTest::newRow("range high") << "{ \"range\": [0, 10] }" << QVariant(15) << false;
+ QTest::newRow("min, max") << "{ \"minimum\": 0, \"maximum\": 10 }" << QVariant(5) << true;
+ QTest::newRow("min, max low") << "{ \"minimum\": 0, \"maximum\": 10 }" << QVariant(-5) << false;
+ QTest::newRow("min, max high") << "{ \"minimum\": 0, \"maximum\": 10 }" << QVariant(15) << false;
+ QTest::newRow("domain") << "{ \"domain\": [\"string1\", \"string2\"] }" << QVariant("string1") << true;
+ QTest::newRow("domain false") << "{ \"domain\": [\"string1\", \"string2\"] }" << QVariant("invalid") << false;
+}
+
+void tst_QIviSimulationGlobalObject::testCheckSettings()
+{
+ QFETCH(QString, json);
+ QFETCH(QVariant, value);
+ QFETCH(bool, expectedResult);
+
+ QIviSimulationGlobalObject globalObject;
+
+ QString error;
+ QVariant data = parseJson(json, error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ bool result = globalObject.checkSettings(data.toMap(), value);
+ QCOMPARE(result, expectedResult);
+}
+
+void tst_QIviSimulationGlobalObject::testConstraint_data()
+{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QString>("expectedResult");
+ QTest::newRow("unsupported") << "{ \"unsupported\": true }" << "unsupported";
+ QTest::newRow("minDomain") << "{ \"minimum\": 10 }" << ">= 10";
+ QTest::newRow("maxDomain") << "{ \"maximum\": 10 }" << "<= 10";
+ QTest::newRow("range") << "{ \"range\": [0, 10] }" << "[0-10]";
+ QTest::newRow("min, max") << "{ \"minimum\": 0, \"maximum\": 10 }" << "[0-10]";
+ QTest::newRow("domain") << "{ \"domain\": [\"string1\", \"string2\"] }" << "[\"string1\",\"string2\"]";
+}
+
+void tst_QIviSimulationGlobalObject::testConstraint()
+{
+ QFETCH(QString, json);
+ QFETCH(QString, expectedResult);
+
+ QIviSimulationGlobalObject globalObject;
+
+ QString error;
+ QVariant data = parseJson(json, error);
+ QVERIFY2(error.isEmpty(), qPrintable(error));
+
+ QString result = globalObject.constraint(data.toMap());
+ QCOMPARE(result, expectedResult);
+}
+
+QTEST_MAIN(tst_QIviSimulationGlobalObject)
+
+#include "tst_qivisimulationglobalobject.moc"
+
diff --git a/tests/auto/core/servicemanagertest/tst_servicemanagertest.cpp b/tests/auto/core/servicemanagertest/tst_servicemanagertest.cpp
index 1923ee6..5c0ba96 100644
--- a/tests/auto/core/servicemanagertest/tst_servicemanagertest.cpp
+++ b/tests/auto/core/servicemanagertest/tst_servicemanagertest.cpp
@@ -87,6 +87,9 @@ class ServiceManagerTest : public QObject
public:
ServiceManagerTest();
+ void ignoreStaticPluginWarnings();
+ void ignoreDynamicPluginWarnings();
+
private Q_SLOTS:
void initTestCase();
void cleanup();
@@ -110,35 +113,63 @@ ServiceManagerTest::ServiceManagerTest()
{
}
+void ServiceManagerTest::ignoreStaticPluginWarnings()
+{
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in static plugin '.*'. MetaData must contain a list of interfaces"));
+}
+
+void ServiceManagerTest::ignoreDynamicPluginWarnings()
+{
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in '.*'. MetaData must contain a list of interfaces"));
+#ifdef DEBUG_AND_RELEASE
+# ifndef Q_OS_WIN
+ // Because the plugin is build in both configurations, the error is also emitted twice
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in '.*'. MetaData must contain a list of interfaces"));
+# endif
+
+ QTest::ignoreMessage(QtInfoMsg, QRegularExpression("Found the same plugin in two configurations. Using the '.*' configuration: .*"));
+#endif
+}
+
void ServiceManagerTest::initTestCase()
{
- QStringList origList = QCoreApplication::libraryPaths();
+ // Make sure the dynamic plugins can't be found in the beginning
QCoreApplication::setLibraryPaths(QStringList());
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in static plugin '.*'. MetaData must contain a list of interfaces"));
- QTest::ignoreMessage(QtWarningMsg, "No plugins found in search path: \"\"");
+ ignoreStaticPluginWarnings();
manager = QIviServiceManager::instance();
QList<QIviServiceObject *> services = manager->findServiceByInterface("simple_plugin");
QCOMPARE(services.count(), 0);
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in static plugin '.*'. MetaData must contain a list of interfaces"));
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in '.*'. MetaData must contain a list of interfaces"));
-#ifdef DEBUG_AND_RELEASE
- QTest::ignoreMessage(QtInfoMsg, QRegularExpression("Found the same plugin in two configurations. Using the '.*' configuration: .*"));
-#endif
- //Reset original setting
- QCoreApplication::setLibraryPaths(origList);
- QIviServiceManagerPrivate::get(manager)->searchPlugins();
+ // Unload all plugins and don't search for the static plugins to trigger the 'no plugins found' warning
+ manager->unloadAllBackends();
+ QIviServiceManagerPrivate::get(manager)->m_staticLoaded = true;
+
+ QTest::ignoreMessage(QtWarningMsg, "No plugins found in search path: \"\"");
+ services = manager->findServiceByInterface("simple_plugin_static");
+ QCOMPARE(services.count(), 0);
+
+ // Change the library path to the current directory to be able to test loading dynamic plugins
+ QCoreApplication::setLibraryPaths({QDir::currentPath()});
+ ignoreDynamicPluginWarnings();
- //Save the id of the service object. This needed in the pluginLoaderTest
+ // This needs to trigger a search for new plugins in the library path, as it is supposed to
+ // reevaluate QCoreApplication::libraryPaths();
services = manager->findServiceByInterface("simple_plugin");
QCOMPARE(services.count(), 1);
+ // Save the id of the service object. This needed in the pluginLoaderTest
m_simplePluginID = services.at(0)->id();
}
void ServiceManagerTest::cleanup()
{
manager->unloadAllBackends();
+
+ // Make sure to search for all plugins here explicitly to catch all expected warning messages
+ // Otherwise a findServiceByInterface call will implictly trigger it.
+ ignoreStaticPluginWarnings();
+ ignoreDynamicPluginWarnings();
+ QIviServiceManagerPrivate::get(manager)->searchPlugins();
}
void ServiceManagerTest::testRetakeSingleton()
@@ -251,10 +282,14 @@ void ServiceManagerTest::testRegisterNonServiceBackendInterfaceObject()
*/
void ServiceManagerTest::testManagerListModel()
{
+ // Because of the plugin loading test and the static plugins, we always have some backends already
+ // in the list
+ const int backendCount = manager->rowCount();
+
QSignalSpy managerModelSpy(manager, SIGNAL(rowsInserted(QModelIndex,int,int)));
// Sanity check
- QCOMPARE(manager->rowCount(), 0);
+ QCOMPARE(manager->rowCount(), backendCount);
QCOMPARE(managerModelSpy.count(), 0);
QCOMPARE(manager->data(QModelIndex(), QIviServiceManager::NameRole), QVariant());
QCOMPARE(manager->data(QModelIndex(), QIviServiceManager::ServiceObjectRole), QVariant());
@@ -264,11 +299,11 @@ void ServiceManagerTest::testManagerListModel()
MockServiceBackend *backend0 = new MockServiceBackend(manager);
bool regResult = manager->registerService(backend0, QStringList() << "Interface0");
QCOMPARE(regResult, true);
- QCOMPARE(manager->rowCount(), 1);
+ QCOMPARE(manager->rowCount(), backendCount + 1);
//QCOMPARE(manager->data(manager->index(0), Qt::DisplayRole).value<QIviServiceInterface*>(), backend0);
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend0);
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface0");
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend0);
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface0");
QCOMPARE(managerModelSpy.count(), 1);
// Extendend sanity check
QCOMPARE(manager->data(manager->index(0,0), Qt::UserRole + 200), QVariant());
@@ -277,32 +312,25 @@ void ServiceManagerTest::testManagerListModel()
MockServiceBackend *backend1 = new MockServiceBackend(manager);
regResult = manager->registerService(backend1, QStringList() << "Interface1" << "Interface2");
QCOMPARE(regResult, true);
- QCOMPARE(manager->rowCount(), 2);
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend0);
- QCOMPARE(manager->data(manager->index(0), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface0");
- QCOMPARE(manager->data(manager->index(1), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
- QCOMPARE(manager->data(manager->index(1), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend1);
- QCOMPARE(manager->data(manager->index(1), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface1" << "Interface2");
+ QCOMPARE(manager->rowCount(), backendCount + 2);
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend0);
+ QCOMPARE(manager->data(manager->index(backendCount), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface0");
+ QCOMPARE(manager->data(manager->index(backendCount + 1), QIviServiceManager::NameRole).toString(), QStringLiteral("MockServiceBackend"));
+ QCOMPARE(manager->data(manager->index(backendCount + 1), QIviServiceManager::ServiceObjectRole).value<QIviProxyServiceObject*>()->d_ptr->m_serviceInterface, backend1);
+ QCOMPARE(manager->data(manager->index(backendCount + 1), QIviServiceManager::InterfacesRole).toStringList(), QStringList() << "Interface1" << "Interface2");
QCOMPARE(managerModelSpy.count(), 2);
// Register backend-2 with 'Interface1' and 'Interface2'. Should not result in any model changes
MockServiceBackend *backend2 = new MockServiceBackend(manager);
regResult = manager->registerService(backend2, QStringList() << "Interface1" << "Interface2");
QCOMPARE(regResult, true);
- QCOMPARE(manager->rowCount(), 3);
+ QCOMPARE(manager->rowCount(), backendCount + 3);
QCOMPARE(managerModelSpy.count(), 3);
}
void ServiceManagerTest::pluginLoaderTest()
{
- //Test the error message for plugins with invalid metadata
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in '(.*)wrongmetadata_plugin(.*)'. MetaData must contain a list of interfaces"));
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression("PluginManager - Malformed metaData in static plugin 'WrongMetadataStaticPlugin'. MetaData must contain a list of interfaces"));
-#ifdef DEBUG_AND_RELEASE
- QTest::ignoreMessage(QtInfoMsg, QRegularExpression("Found the same plugin in two configurations. Using the '.*' configuration: .*"));
-#endif
- QIviServiceManagerPrivate::get(manager)->searchPlugins();
QVERIFY(manager->hasInterface("simple_plugin"));
QList<QIviServiceObject *> services = manager->findServiceByInterface("simple_plugin", QIviServiceManager::IncludeProductionBackends);
QCOMPARE(services.count(), 1);
@@ -320,10 +348,7 @@ void ServiceManagerTest::pluginLoaderTest()
//Test that the plugin is unloaded (or at least removed from the registry)
manager->unloadAllBackends();
- services = manager->findServiceByInterface("simple_plugin");
- QCOMPARE(services.count(), 0);
- services = manager->findServiceByInterface("simple_plugin_static");
- QCOMPARE(services.count(), 0);
+ QCOMPARE(manager->rowCount(), 0);
}
Q_IMPORT_PLUGIN(SimpleStaticPlugin)