From 01221559b7e5d7db1362128f5888adddd8a23bda Mon Sep 17 00:00:00 2001 From: Dario Lipicar Date: Thu, 26 Mar 2026 10:12:18 -0300 Subject: [PATCH] add support for QVariantList and QVariantMap (#31) --- cpp-generator/generator_lib.cpp | 22 +++-- cpp/qt_provider_object.cpp | 12 +++ tests/generator/test_make_header.cpp | 80 +++++++++++++++++++ tests/generator/test_make_source.cpp | 76 ++++++++++++++++++ tests/generator/test_map_param_type.cpp | 2 + tests/generator/test_map_return_type.cpp | 2 + .../generator/test_to_qvariant_conversion.cpp | 10 +++ 7 files changed, 198 insertions(+), 6 deletions(-) diff --git a/cpp-generator/generator_lib.cpp b/cpp-generator/generator_lib.cpp index fa289ba..411fb3f 100644 --- a/cpp-generator/generator_lib.cpp +++ b/cpp-generator/generator_lib.cpp @@ -34,7 +34,7 @@ QString mapParamType(const QString& qtType) { const QString base = normalizeType(qtType); static const QSet known = { - "void","bool","int","double","float","QString","QStringList","QJsonArray","QVariant" + "void","bool","int","double","float","QString","QStringList","QJsonArray","QVariantList","QVariantMap","QVariant" }; if (known.contains(base)) return base; // Fallback to QVariant for unknown types @@ -46,7 +46,7 @@ QString mapReturnType(const QString& qtType) const QString base = normalizeType(qtType); if (base.isEmpty() || base == "void") return QString("void"); static const QSet known = { - "bool","int","double","float","QString","QStringList","QJsonArray","QVariant","LogosResult" + "bool","int","double","float","QString","QStringList","QJsonArray","QVariantList","QVariantMap","QVariant","LogosResult" }; if (known.contains(base)) return base; return QString("QVariant"); @@ -61,6 +61,8 @@ QString toQVariantConversion(const QString& type, const QString& argExpr) if (type == "QString") return argExpr + ".toString()"; if (type == "QStringList") return argExpr + ".toStringList()"; if (type == "QJsonArray") return "qvariant_cast(" + argExpr + ")"; + if (type == "QVariantList") return argExpr + ".toList()"; + if (type == "QVariantMap") return argExpr + ".toMap()"; if (type == "QVariant") return argExpr; if (type == "LogosResult") return argExpr + ".value()"; return argExpr + ".toString()"; @@ -75,6 +77,8 @@ QString makeHeader(const QString& moduleName, const QString& className, const QJ s << "#include \n"; s << "#include \n"; s << "#include \n"; + s << "#include \n"; + s << "#include \n"; s << "#include \n"; s << "#include \n"; s << "#include \"logos_types.h\"\n"; @@ -114,7 +118,7 @@ QString makeHeader(const QString& moduleName, const QString& className, const QJ QJsonObject p = params.at(i).toObject(); QString pt = mapParamType(p.value("type").toString()); QString pn = p.value("name").toString(); - if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray") { + if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray" || pt == "QVariantList" || pt == "QVariantMap") { s << "const " << pt << "& " << pn; } else { s << pt << " " << pn; @@ -129,7 +133,7 @@ QString makeHeader(const QString& moduleName, const QString& className, const QJ QJsonObject p = params.at(i).toObject(); QString pt = mapParamType(p.value("type").toString()); QString pn = p.value("name").toString(); - if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray") { + if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray" || pt == "QVariantList" || pt == "QVariantMap") { s << "const " << pt << "& " << pn; } else { s << pt << " " << pn; @@ -233,7 +237,7 @@ QString makeSource(const QString& moduleName, const QString& className, const QS QJsonObject p = params.at(i).toObject(); QString pt = mapParamType(p.value("type").toString()); QString pn = p.value("name").toString(); - if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray") { + if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray" || pt == "QVariantList" || pt == "QVariantMap") { s << "const " << pt << "& " << pn; } else { s << pt << " " << pn; @@ -301,6 +305,10 @@ QString makeSource(const QString& moduleName, const QString& className, const QS s << " return _result.toStringList();\n"; } else if (ret == "QJsonArray") { s << " return qvariant_cast(_result);\n"; + } else if (ret == "QVariantList") { + s << " return _result.toList();\n"; + } else if (ret == "QVariantMap") { + s << " return _result.toMap();\n"; }else if (ret == "LogosResult") { s << " return _result.value();\n"; } else { // QVariant @@ -313,7 +321,7 @@ QString makeSource(const QString& moduleName, const QString& className, const QS QJsonObject p = params.at(i).toObject(); QString pt = mapParamType(p.value("type").toString()); QString pn = p.value("name").toString(); - if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray") { + if (pt == "QString" || pt == "QStringList" || pt == "QJsonArray" || pt == "QVariantList" || pt == "QVariantMap") { s << "const " << pt << "& " << pn; } else { s << pt << " " << pn; @@ -346,6 +354,8 @@ QString makeSource(const QString& moduleName, const QString& className, const QS else if (ret == "QString") defaultVal = "QString()"; else if (ret == "QStringList") defaultVal = "QStringList()"; else if (ret == "QJsonArray") defaultVal = "QJsonArray()"; + else if (ret == "QVariantList") defaultVal = "QVariantList()"; + else if (ret == "QVariantMap") defaultVal = "QVariantMap()"; else defaultVal = ret + "{}"; if (ret == "QVariant") { s << " callback(v);\n"; diff --git a/cpp/qt_provider_object.cpp b/cpp/qt_provider_object.cpp index 37f7b70..eaeebd7 100644 --- a/cpp/qt_provider_object.cpp +++ b/cpp/qt_provider_object.cpp @@ -152,6 +152,10 @@ namespace { INVOKE_METHOD_WITH_RETURN(QVariant, QVariant); } else if (strcmp(returnTypeName, "QJsonArray") == 0) { INVOKE_METHOD_WITH_RETURN(QJsonArray, QJsonArray); + } else if (strcmp(returnTypeName, "QVariantList") == 0) { + INVOKE_METHOD_WITH_RETURN(QVariantList, QVariantList); + } else if (strcmp(returnTypeName, "QVariantMap") == 0) { + INVOKE_METHOD_WITH_RETURN(QVariantMap, QVariantMap); } else if (strcmp(returnTypeName, "QStringList") == 0) { INVOKE_METHOD_WITH_RETURN(QStringList, QStringList); } else { @@ -300,6 +304,14 @@ QVariant QtProviderObject::callMethod(const QString& methodName, const QVariantL QJsonArray v; success = invokeMethodByArgCount(m_module, methodName, args, &v, "QJsonArray"); if (success) result = QVariant(v); + } else if (returnType == QMetaType::fromType()) { + QVariantList v; + success = invokeMethodByArgCount(m_module, methodName, args, &v, "QVariantList"); + if (success) result = QVariant::fromValue(v); + } else if (returnType == QMetaType::fromType()) { + QVariantMap v; + success = invokeMethodByArgCount(m_module, methodName, args, &v, "QVariantMap"); + if (success) result = QVariant::fromValue(v); } else if (returnType == QMetaType::fromType()) { QStringList v; success = invokeMethodByArgCount(m_module, methodName, args, &v, "QStringList"); diff --git a/tests/generator/test_make_header.cpp b/tests/generator/test_make_header.cpp index abedebf..7f6a3f9 100644 --- a/tests/generator/test_make_header.cpp +++ b/tests/generator/test_make_header.cpp @@ -78,6 +78,8 @@ TEST(MakeHeaderTest, ContainsIncludes) EXPECT_TRUE(h.contains("#include \"logos_api.h\"")); EXPECT_TRUE(h.contains("#include \"logos_api_client.h\"")); EXPECT_TRUE(h.contains("#include \"logos_object.h\"")); + EXPECT_TRUE(h.contains("#include ")); + EXPECT_TRUE(h.contains("#include ")); } TEST(MakeHeaderTest, ContainsEventCallbackTypedefs) @@ -139,3 +141,81 @@ TEST(MakeHeaderTest, ConstRefForStringParams) QString h = makeHeader("mod", "Mod", methods); EXPECT_TRUE(h.contains("const QString& name")); } + +TEST(MakeHeaderTest, ConstRefForQVariantListParam) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "process"; + m["returnType"] = "void"; + m["isInvokable"] = true; + QJsonArray params; + QJsonObject p; + p["type"] = "QVariantList"; + p["name"] = "items"; + params.append(p); + m["parameters"] = params; + methods.append(m); + } + + QString h = makeHeader("mod", "Mod", methods); + EXPECT_TRUE(h.contains("const QVariantList& items")); +} + +TEST(MakeHeaderTest, ConstRefForQVariantMapParam) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "update"; + m["returnType"] = "void"; + m["isInvokable"] = true; + QJsonArray params; + QJsonObject p; + p["type"] = "QVariantMap"; + p["name"] = "data"; + params.append(p); + m["parameters"] = params; + methods.append(m); + } + + QString h = makeHeader("mod", "Mod", methods); + EXPECT_TRUE(h.contains("const QVariantMap& data")); +} + +TEST(MakeHeaderTest, QVariantListAsyncOverload) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "getItems"; + m["returnType"] = "QVariantList"; + m["isInvokable"] = true; + m["parameters"] = QJsonArray(); + methods.append(m); + } + + QString h = makeHeader("mod", "Mod", methods); + EXPECT_TRUE(h.contains("QVariantList getItems()")); + EXPECT_TRUE(h.contains("getItemsAsync(")); + EXPECT_TRUE(h.contains("std::function callback")); +} + +TEST(MakeHeaderTest, QVariantMapAsyncOverload) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "getData"; + m["returnType"] = "QVariantMap"; + m["isInvokable"] = true; + m["parameters"] = QJsonArray(); + methods.append(m); + } + + QString h = makeHeader("mod", "Mod", methods); + EXPECT_TRUE(h.contains("QVariantMap getData()")); + EXPECT_TRUE(h.contains("getDataAsync(")); + EXPECT_TRUE(h.contains("std::function callback")); +} diff --git a/tests/generator/test_make_source.cpp b/tests/generator/test_make_source.cpp index 82d940b..3229363 100644 --- a/tests/generator/test_make_source.cpp +++ b/tests/generator/test_make_source.cpp @@ -125,6 +125,82 @@ TEST(MakeSourceTest, QJsonArrayReturn) EXPECT_TRUE(src.contains("qvariant_cast(_result)")); } +TEST(MakeSourceTest, QVariantListReturn) +{ + QJsonArray methods; + methods.append(makeMethod("getItems", "QVariantList", 0)); + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("return _result.toList()")); +} + +TEST(MakeSourceTest, QVariantMapReturn) +{ + QJsonArray methods; + methods.append(makeMethod("getData", "QVariantMap", 0)); + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("return _result.toMap()")); +} + +TEST(MakeSourceTest, QVariantListAsync) +{ + QJsonArray methods; + methods.append(makeMethod("getItems", "QVariantList", 0)); + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("Mod::getItemsAsync(")); + EXPECT_TRUE(src.contains("std::function callback")); + EXPECT_TRUE(src.contains("QVariantList()")); +} + +TEST(MakeSourceTest, QVariantMapAsync) +{ + QJsonArray methods; + methods.append(makeMethod("getData", "QVariantMap", 0)); + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("Mod::getDataAsync(")); + EXPECT_TRUE(src.contains("std::function callback")); + EXPECT_TRUE(src.contains("QVariantMap()")); +} + +TEST(MakeSourceTest, QVariantListConstRefParam) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "process"; + m["returnType"] = "void"; + m["isInvokable"] = true; + QJsonArray params; + QJsonObject p; + p["type"] = "QVariantList"; + p["name"] = "items"; + params.append(p); + m["parameters"] = params; + methods.append(m); + } + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("const QVariantList& items")); +} + +TEST(MakeSourceTest, QVariantMapConstRefParam) +{ + QJsonArray methods; + { + QJsonObject m; + m["name"] = "update"; + m["returnType"] = "void"; + m["isInvokable"] = true; + QJsonArray params; + QJsonObject p; + p["type"] = "QVariantMap"; + p["name"] = "data"; + params.append(p); + m["parameters"] = params; + methods.append(m); + } + QString src = makeSource("mod", "Mod", "mod.h", methods); + EXPECT_TRUE(src.contains("const QVariantMap& data")); +} + TEST(MakeSourceTest, LogosResultReturn) { QJsonArray methods; diff --git a/tests/generator/test_map_param_type.cpp b/tests/generator/test_map_param_type.cpp index 7102f80..e981286 100644 --- a/tests/generator/test_map_param_type.cpp +++ b/tests/generator/test_map_param_type.cpp @@ -10,6 +10,8 @@ TEST(MapParamTypeTest, KnownTypes) EXPECT_EQ(mapParamType("QString"), "QString"); EXPECT_EQ(mapParamType("QStringList"), "QStringList"); EXPECT_EQ(mapParamType("QJsonArray"), "QJsonArray"); + EXPECT_EQ(mapParamType("QVariantList"), "QVariantList"); + EXPECT_EQ(mapParamType("QVariantMap"), "QVariantMap"); EXPECT_EQ(mapParamType("QVariant"), "QVariant"); EXPECT_EQ(mapParamType("void"), "void"); } diff --git a/tests/generator/test_map_return_type.cpp b/tests/generator/test_map_return_type.cpp index 1764b07..c9d2e54 100644 --- a/tests/generator/test_map_return_type.cpp +++ b/tests/generator/test_map_return_type.cpp @@ -10,6 +10,8 @@ TEST(MapReturnTypeTest, KnownTypes) EXPECT_EQ(mapReturnType("QString"), "QString"); EXPECT_EQ(mapReturnType("QStringList"), "QStringList"); EXPECT_EQ(mapReturnType("QJsonArray"), "QJsonArray"); + EXPECT_EQ(mapReturnType("QVariantList"), "QVariantList"); + EXPECT_EQ(mapReturnType("QVariantMap"), "QVariantMap"); EXPECT_EQ(mapReturnType("QVariant"), "QVariant"); EXPECT_EQ(mapReturnType("LogosResult"), "LogosResult"); } diff --git a/tests/generator/test_to_qvariant_conversion.cpp b/tests/generator/test_to_qvariant_conversion.cpp index fa25b48..cca24ce 100644 --- a/tests/generator/test_to_qvariant_conversion.cpp +++ b/tests/generator/test_to_qvariant_conversion.cpp @@ -36,6 +36,16 @@ TEST(ToQVariantConversionTest, QJsonArray) EXPECT_EQ(toQVariantConversion("QJsonArray", "arg"), "qvariant_cast(arg)"); } +TEST(ToQVariantConversionTest, QVariantList) +{ + EXPECT_EQ(toQVariantConversion("QVariantList", "v"), "v.toList()"); +} + +TEST(ToQVariantConversionTest, QVariantMap) +{ + EXPECT_EQ(toQVariantConversion("QVariantMap", "v"), "v.toMap()"); +} + TEST(ToQVariantConversionTest, QVariantPassthrough) { EXPECT_EQ(toQVariantConversion("QVariant", "v"), "v");