Browse Source

Add class types registration.

Tatyana Borisova 6 years ago
parent
commit
a597068588

+ 1 - 1
CMakeLists.txt

@@ -46,7 +46,7 @@ if (MAKE_TESTS)
         include_directories("src/lib")
         add_custom_command(TARGET ${testgeneration} POST_BUILD
             COMMAND ${PROTOBUF_INSTALATION_PATH}/bin/protoc.exe --plugin=protoc-gen-${PROJECT_NAME}=${CMAKE_BINARY_DIR}/qtprotobuf.exe --qtprotobuf_out=${CMAKE_CURRENT_BINARY_DIR}/tests
-            *.proto
+            simpletest.proto
             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/proto/
             COMMENT "Generating test headers"
             )

+ 4 - 9
src/generator/classgeneratorbase.cpp

@@ -86,13 +86,6 @@ void ClassGeneratorBase::encloseNamespaces()
     encloseNamespaces(mNamespaces.size());
 }
 
-void ClassGeneratorBase::printConstructor()
-{
-    mPrinter.Print({{"classname", mClassName}},
-                   ConstructorTemplate);
-    mPrinter.Print(EmptyBlockTemplate);
-}
-
 void ClassGeneratorBase::printPublic()
 {
     mPrinter.Print(PublicBlockTemplate);
@@ -107,7 +100,9 @@ void ClassGeneratorBase::printMetaTypeDeclaration()
         }
         namespaces = namespaces.append(mNamespaces[i]);
     }
-    mPrinter.Print({{"type", mClassName},
-                    {"namespaces", namespaces}}, DeclareMetaTypeTemplate);
+    mPrinter.Print({{"classname", mClassName}, {"namespaces", namespaces}},
+                   DeclareMetaTypeTemplate);
+    mPrinter.Print({{"classname", mClassName}, {"namespaces", namespaces}},
+                   DeclareComplexListTypeTemplate);
 }
 

+ 0 - 1
src/generator/classgeneratorbase.h

@@ -58,7 +58,6 @@ protected:
     void printNamespaces();
     void printNamespaces(const std::vector<std::string> &namespaces);
     void printClassDeclaration();
-    void printConstructor();
     void printPublic();
     void encloseClass();
     void printMetaTypeDeclaration();

+ 13 - 0
src/generator/generator.cpp

@@ -60,6 +60,7 @@ public:
         printClassHeaderInclude();
         printNamespaces();
         printFieldsOrdering();
+        printRegisterBody();
         encloseNamespaces();
     }
 
@@ -85,6 +86,18 @@ public:
         Outdent();
         mPrinter.Print(SemicolonBlockEnclosureTemplate);
     }
+
+    void printRegisterBody()
+    {
+        std::string namespaces;
+        for(int i = 0; i < mNamespaces.size(); i++) {
+            if(i > 0) {
+                namespaces = namespaces.append("::");
+            }
+            namespaces = namespaces.append(mNamespaces[i]);
+        }
+        mPrinter.Print({{"classname", mClassName}, {"namespaces", namespaces}}, ComplexTypeRegistrationTemplate);
+    }
 };
 
 bool QtGenerator::Generate(const FileDescriptor *file,

+ 23 - 8
src/generator/protobufclassgenerator.cpp

@@ -204,10 +204,10 @@ std::string ProtobufClassGenerator::getTypeName(const FieldDescriptor *field)
     assert(field != nullptr);
     std::string typeName;
     if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        typeName = field->message_type()->name();
         if (field->is_repeated()) {
-            return VariantList;
+            return typeName.append("List");
         }
-        typeName = field->message_type()->name();
     } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
         if (field->is_repeated()) {
             return VariantList;
@@ -274,6 +274,11 @@ bool ProtobufClassGenerator::isComplexType(const FieldDescriptor *field)
             || field->type() == FieldDescriptor::TYPE_BYTES;
 }
 
+void ProtobufClassGenerator::printConstructor()
+{
+    mPrinter.Print({{"classname", mClassName}}, ConstructorTemplate);
+    mPrinter.Print(ConstructorContentTemplate);
+}
 
 void ProtobufClassGenerator::printProperties()
 {
@@ -282,11 +287,9 @@ void ProtobufClassGenerator::printProperties()
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor* field = mMessage->field(i);
-        if (!isListType(field)) {
-            const char* propertyTemplate = field->type() == FieldDescriptor::TYPE_MESSAGE ? MessagePropertyTemplate :
-                                                                                            PropertyTemplate;
-            printField(field, propertyTemplate);
-        }
+        const char* propertyTemplate = field->type() == FieldDescriptor::TYPE_MESSAGE ? MessagePropertyTemplate :
+                                                                                        PropertyTemplate;
+        printField(field, propertyTemplate);
     }
     for (int i = 0; i < mMessage->field_count(); i++) {
         printField(mMessage->field(i), MemberTemplate);
@@ -328,6 +331,16 @@ void ProtobufClassGenerator::printProperties()
     Outdent();
 }
 
+void ProtobufClassGenerator::printRegisterTypes()
+{
+    mPrinter.Print(ComplexTypeRegistrationMethodTemplate);
+}
+
+void ProtobufClassGenerator::printListType()
+{
+    mPrinter.Print({{"classname", mClassName}}, ComplexListTypeUsingTemplate);
+}
+
 void ProtobufClassGenerator::printFieldsOrderingDefinition()
 {
     Indent();
@@ -355,10 +368,12 @@ void ProtobufClassGenerator::run()
     printIncludes(extractModels());
     printNamespaces();
     printClassDeclaration();
+    printRegisterTypes();
     printProperties();
     printPublic();
     printFieldsOrderingDefinition();
     encloseClass();
-    encloseNamespaces(mNamespaces.size());
+    printListType();
+    encloseNamespaces();
     printMetaTypeDeclaration();
 }

+ 3 - 0
src/generator/protobufclassgenerator.h

@@ -59,6 +59,9 @@ public:
     void printField(const ::google::protobuf::FieldDescriptor *field, const char *fieldTemplate);
     void printProperties();
     void printFieldsOrderingDefinition();
+    void printRegisterTypes();
+    void printConstructor();
+    void printListType();
 
     std::set<std::string> extractModels() const;
 

+ 18 - 3
src/generator/templates.h

@@ -38,13 +38,27 @@ static const char *DefaultProtobufIncludesTemplate = "#include <QMetaType>\n"
 
 static const char *PreambleTemplate = "/* This file is autogenerated. DO NOT CHANGE. All changes will be lost */\n\n"
                                       "#pragma once\n\n"
-                                      "#include <QObject>\n";
+                                      "#include <QObject>\n"
+                                      "#include <QMetaType>\n"
+                                      "#include <protobufobject.h>\n"
+                                      "#include <unordered_map>\n\n";
 
 static const char *InternalIncludeTemplate =  "#include \"$type_lower$.h\"\n";
 static const char *ExternalIncludeTemplate = "#include <$type$>\n";
 static const char *ListModelsIncludeTemplate = "#include <QList>\n";
 
 static const char *UsingQtProtobufNamespaceTemplate = "\nusing namespace qtprotobuf;\n";
+static const char *ComplexTypeRegistrationMethodTemplate = "\nstatic void registerTypes();\n";
+static const char *ComplexTypeRegistrationTemplate = "void $classname$::registerTypes()\n{\n"
+                                                     "    static bool registationDone = false;\n"
+                                                     "    if (!registationDone) {\n\n"
+                                                     "        qRegisterMetaType<$classname$>(\"$classname$\");\n"
+                                                     "        qRegisterMetaType<$classname$List>(\"$classname$List\");\n"
+                                                     "        qRegisterMetaType<$namespaces$::$classname$>(\"$namespaces$::$classname$\");\n"
+                                                     "        qRegisterMetaType<$namespaces$::$classname$List>(\"$namespaces$::$classname$List\");\n"
+                                                     "    }\n}\n";
+static const char *ComplexListTypeUsingTemplate = "using $classname$List = QList<$classname$>;\n";
+
 static const char *NamespaceTemplate = "\nnamespace $namespace$ {\n";
 
 static const char *NonProtoClassDefinitionTemplate = "\nclass $classname$ : public QObject\n"
@@ -107,9 +121,10 @@ static const char *EnumTemplate = "$type$";
 static const char *SimpleBlockEnclosureTemplate = "}\n\n";
 static const char *SemicolonBlockEnclosureTemplate = "};\n";
 static const char *EmptyBlockTemplate = "{}\n\n";
+static const char *ConstructorContentTemplate = "{\n    registerTypes();\n}\n";
 
-static const char *DeclareMetaTypeTemplate = "#include <QMetaType>\n"
-                                             "Q_DECLARE_METATYPE($namespaces$::$type$)\n";
+static const char *DeclareMetaTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$)\n";
+static const char *DeclareComplexListTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$List)\n";
 
 static const char *QEnumTemplate = "Q_ENUM($type$)\n";
 

+ 1 - 1
src/lib/CMakeLists.txt

@@ -18,7 +18,7 @@ add_library(qtprotobufsupport
     qtprotobuf.cpp
     qtprotobuflogging.cpp)
 
-set_target_properties(qtprotobufsupport PROPERTIES PUBLIC_HEADER "universallistmodelbase.h;universallistmodel.h;protobufobject.h;qtprotobuftypes.h;qtprotobuf.h")
+set_target_properties(qtprotobufsupport PROPERTIES PUBLIC_HEADER "universallistmodelbase.h;universallistmodel.h;protobufobject.h;qtprotobuftypes.h;qtprotobuf.h;qtprotobuflogging.h")
 
 install(TARGETS qtprotobufsupport
     ARCHIVE DESTINATION lib

+ 4 - 3
tests/CMakeLists.txt

@@ -37,15 +37,16 @@ file(GLOB GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/*.cpp)
 list(FILTER GENERATED_SOURCES EXCLUDE REGEX "moc_.*cpp")
 QT5_WRAP_CPP(MOC_SOURCES ${GENERATED_HEADERS})
 
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/lib)
+
 if (WIN32)
     #Set  path to GTest build libraries
     set(GTEST_BOTH_LIBRARIES "")
     #Set  path to GTest include directory
     include_directories(${GTEST_INCLUDE_PATHS} "/")
     #Need for generated code
-    include_directories(${CMAKE_CURRENT_BINARY_DIR})
 elseif (UNIX)
-    include_directories(${GTEST_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/lib)
+    include_directories(${GTEST_INCLUDE_DIRS})
 endif()
 
 file(GLOB HEADERS ${TESTS_OUT_DIR})
@@ -59,7 +60,7 @@ file(GLOB PROTOS proto/*.proto)
 
 add_executable(${testtarget} ${SOURCES} ${MOC_SOURCES} ${GENERATED_SOURCES} ${PROTOS})
 if (WIN32)
-    target_link_libraries(${testtarget} "${GTEST_BOTH_LIBRARIES}/gmock_main.lib" "${GTEST_BOTH_LIBRARIES}/gmock.lib"  Qt5::Core)
+    target_link_libraries(${testtarget} "${GTEST_BOTH_LIBRARIES}/gmock_main.lib" "${GTEST_BOTH_LIBRARIES}/gmock.lib" qtprotobufsupport Qt5::Core)
 elseif (UNIX)
     target_link_libraries(${testtarget} gtest qtprotobufsupport Qt5::Core)
 endif()

+ 2 - 1
tests/deserializationtest.cpp

@@ -228,9 +228,10 @@ TEST_F(DeserializationTest, StringMessageDeserializeTest)
 
 TEST_F(DeserializationTest, ComplexTypeDeserializeTest)
 {
-    qRegisterMetaType<SimpleStringMessage>("SimpleStringMessage");
     ComplexMessage test;
 
+    qRegisterMetaType<SimpleStringMessage>("SimpleStringMessage");
+
     test.deserialize(QByteArray::fromHex("120832067177657274790859"));
     ASSERT_EQ(-45, test.testFieldInt());
     ASSERT_TRUE(QString::fromUtf8("qwerty") == test.testComplexField().testFieldString());

+ 2 - 1
tests/serializationtest.cpp

@@ -425,7 +425,6 @@ TEST_F(SerializationTest, StringMessageSerializeTest)
 
 TEST_F(SerializationTest, ComplexTypeSerializeTest)
 {
-    qRegisterMetaType<SimpleStringMessage>("SimpleStringMessage");
     SimpleStringMessage stringMsg;
     stringMsg.setTestFieldString("qwerty");
 
@@ -533,6 +532,7 @@ TEST_F(SerializationTest, RepeatedFloatMessageTest)
 TEST_F(SerializationTest, RepeatedComplexMessageTest)
 {
     return;//disabled
+#if 0
     SimpleStringMessage stringMsg;
     stringMsg.setTestFieldString("qwerty");
     ComplexMessage msg;
@@ -548,4 +548,5 @@ TEST_F(SerializationTest, RepeatedComplexMessageTest)
     test.setTestRepeatedComplex(QVariantList());
     result = test.serialize();
     ASSERT_TRUE(result.isEmpty());
+#endif
 }