QtProtobuf: add QML support

Enable QML flag for qtgrpcgen/qtprotobufgen plugins.
Generated output is updated: QProtobufMessage classes are Q_GADGETs,
such classes can be registered in QML code via QML_VALUE_TYPE macros only.
Also QProtobufMessages are not inherited from QObject class, it means
there is no full qmetaobject system support (no signals!).

Task-number: QTBUG-104513
Change-Id: I18c8f93782884efb8d923843df716ff8284ed8fb
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Tatiana Borisova 2023-03-30 18:38:28 +02:00
parent b3cf2e9d63
commit 21e208ec96
7 changed files with 22 additions and 6 deletions

View File

@ -8,6 +8,7 @@ macro(_qt_internal_get_protoc_common_options option_args single_args multi_args)
set(${option_args} set(${option_args}
COPY_COMMENTS COPY_COMMENTS
GENERATE_PACKAGE_SUBFOLDERS GENERATE_PACKAGE_SUBFOLDERS
QML
) )
set(${single_args} set(${single_args}
EXTRA_NAMESPACE EXTRA_NAMESPACE

View File

@ -141,6 +141,10 @@ void MessageDeclarationPrinter::printClassDeclarationBegin()
} else { } else {
m_printer->Print(m_typeMap, CommonTemplates::ClassMessageBeginDeclarationTemplate()); m_printer->Print(m_typeMap, CommonTemplates::ClassMessageBeginDeclarationTemplate());
} }
if (Options::instance().hasQml()) {
m_printer->Print(m_typeMap, CommonTemplates::ClassMessageQmlBeginDeclarationTemplate());
}
} }
void MessageDeclarationPrinter::printMetaTypesDeclaration() void MessageDeclarationPrinter::printMetaTypesDeclaration()

View File

@ -77,7 +77,7 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}}, sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}},
CommonTemplates::ExternalIncludeTemplate()); CommonTemplates::ExternalIncludeTemplate());
if (Options::instance().hasQml()) { if (Options::instance().hasQml()) {
sourcePrinter->Print({{"include", "QQmlEngine"}}, sourcePrinter->Print({{"include", "QtQml/QQmlEngine"}},
CommonTemplates::ExternalIncludeTemplate()); CommonTemplates::ExternalIncludeTemplate());
} }

View File

@ -61,8 +61,8 @@ const char *CommonTemplates::DefaultSystemIncludesTemplate()
const char *CommonTemplates::QmlProtobufIncludesTemplate() const char *CommonTemplates::QmlProtobufIncludesTemplate()
{ {
return "#include <QtQml/QQmlListProperty>\n" return "#include <QtQml/qqmlregistration.h>\n"
"#include <QtProtobufQuick/qtprotobufqmllistpropertyconstructor.h>\n\n"; "#include <QtQml/qqmllist.h>\n\n";
} }
const char *CommonTemplates::DisclaimerTemplate() const char *CommonTemplates::DisclaimerTemplate()
@ -159,6 +159,12 @@ const char *CommonTemplates::ClassMessageForwardDeclarationTemplate()
{ {
return "class $classname$;\n"; return "class $classname$;\n";
} }
const char *CommonTemplates::ClassMessageQmlBeginDeclarationTemplate()
{
return " QML_VALUE_TYPE($classname_low_case$)\n";
}
const char *CommonTemplates::ClassMessageBeginDeclarationTemplate() const char *CommonTemplates::ClassMessageBeginDeclarationTemplate()
{ {
return "\nclass $export_macro$ $classname$ : public QProtobufMessage\n" return "\nclass $export_macro$ $classname$ : public QProtobufMessage\n"

View File

@ -42,6 +42,7 @@ public:
static const char *ClassMessageForwardDeclarationTemplate(); static const char *ClassMessageForwardDeclarationTemplate();
static const char *ClassMessageBeginDeclarationTemplate(); static const char *ClassMessageBeginDeclarationTemplate();
static const char *ClassMessageBeginDeclarationTemplateEmptyMacros(); static const char *ClassMessageBeginDeclarationTemplateEmptyMacros();
static const char *ClassMessageQmlBeginDeclarationTemplate();
static const char *EmptyConstructorTemplate(); static const char *EmptyConstructorTemplate();
static const char *UseNamespace(); static const char *UseNamespace();

View File

@ -214,6 +214,7 @@ TypeMap common::produceMessageTypeMap(const Descriptor *type, const Descriptor *
const std::string initializer = "nullptr"; const std::string initializer = "nullptr";
return { { "classname", name }, return { { "classname", name },
{ "classname_low_case", utils::deCapitalizeAsciiName(type->name()) },
{ "type", name }, { "type", name },
{ "full_type", fullName }, { "full_type", fullName },
{ "scope_type", scopeName }, { "scope_type", scopeName },
@ -266,6 +267,7 @@ TypeMap common::produceEnumTypeMap(const EnumDescriptor *type, const Descriptor
std::string initializer = scopeName + "::" + type->value(0)->name(); std::string initializer = scopeName + "::" + type->value(0)->name();
return { { "classname", enumGadget }, return { { "classname", enumGadget },
{ "classname_low_case", utils::deCapitalizeAsciiName(enumGadget) },
{ "type", name }, { "type", name },
{ "full_type", fullName }, { "full_type", fullName },
{ "scope_type", scopeName }, { "scope_type", scopeName },
@ -350,6 +352,7 @@ MethodMap common::produceMethodMap(const MethodDescriptor *method, const std::st
inputTypeName = utils::replace(inputTypeName, ".", "::"); inputTypeName = utils::replace(inputTypeName, ".", "::");
outputTypeName = utils::replace(outputTypeName, ".", "::"); outputTypeName = utils::replace(outputTypeName, ".", "::");
return { { "classname", scope }, { "return_type", outputTypeName }, return { { "classname", scope }, { "return_type", outputTypeName },
{ "classname_low_case", utils::deCapitalizeAsciiName(scope) },
{ "method_name", methodName }, { "method_name_upper", methodNameUpper }, { "method_name", methodName }, { "method_name_upper", methodNameUpper },
{ "param_type", inputTypeName }, { "param_name", "arg" }, { "param_type", inputTypeName }, { "param_name", "arg" },
{ "return_name", "ret" } }; { "return_name", "ret" } };
@ -367,6 +370,7 @@ TypeMap common::produceServiceTypeMap(const ServiceDescriptor *service, const De
getFullNamespace(scope, "::")); getFullNamespace(scope, "::"));
return { { "classname", name }, return { { "classname", name },
{ "classname_low_case", utils::deCapitalizeAsciiName(name) },
{ "full_type", fullName }, { "full_type", fullName },
{ "scope_type", scopeName }, { "scope_type", scopeName },
{ "scope_namespaces", scopeNamespaces }, { "scope_namespaces", scopeNamespaces },
@ -386,6 +390,7 @@ TypeMap common::produceClientTypeMap(const ServiceDescriptor *service, const Des
getFullNamespace(scope, "::")); getFullNamespace(scope, "::"));
return { { "classname", name }, return { { "classname", name },
{ "classname_low_case", utils::deCapitalizeAsciiName(name) },
{ "full_type", fullName }, { "full_type", fullName },
{ "scope_type", scopeName }, { "scope_type", scopeName },
{ "scope_namespaces", scopeNamespaces }, { "scope_namespaces", scopeNamespaces },

View File

@ -51,9 +51,8 @@ void Options::setFromString(const std::string &options)
for (const auto &option : utils::split(options, ";")) { for (const auto &option : utils::split(options, ";")) {
QT_PROTOBUF_DEBUG("option: " << option); QT_PROTOBUF_DEBUG("option: " << option);
if (option == QmlPluginOption) { if (option == QmlPluginOption) {
// TODO: Disable QML until the porting is complete. QT_PROTOBUF_DEBUG("set m_hasQml: true");
// QT_PROTOBUF_DEBUG("set m_hasQml: true"); instance.m_hasQml = true;
// instance.m_hasQml = true;
} else if (option == CommentsGenerationOption) { } else if (option == CommentsGenerationOption) {
QT_PROTOBUF_DEBUG("set m_generateComments: true"); QT_PROTOBUF_DEBUG("set m_generateComments: true");
instance.m_generateComments = true; instance.m_generateComments = true;