├── .gitignore ├── LICENSE ├── README.md ├── compiler ├── compiler.pro ├── insertion_point_writer.cpp ├── insertion_point_writer.h ├── main.cpp ├── protobuf_qt_generator.cpp ├── protobuf_qt_generator.h ├── repeated_field_adaptor.h └── repeated_fields.h ├── include ├── include.pri └── include.pro ├── protobuf_qt.pro └── tests ├── main_test.cpp ├── test_messages_proto3.proto └── tests.pro /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.dll 10 | *.dylib 11 | 12 | # Qt-es 13 | object_script.*.Release 14 | object_script.*.Debug 15 | *_plugin_import.cpp 16 | /.qmake.cache 17 | /.qmake.stash 18 | *.pro.user 19 | *.pro.user.* 20 | *.qbs.user 21 | *.qbs.user.* 22 | *.moc 23 | moc_*.cpp 24 | moc_*.h 25 | qrc_*.cpp 26 | ui_*.h 27 | *.qmlc 28 | *.jsc 29 | Makefile* 30 | *build-* 31 | 32 | # Qt unit tests 33 | target_wrapper.* 34 | 35 | # QtCreator 36 | *.autosave 37 | 38 | # QtCreator Qml 39 | *.qmlproject.user 40 | *.qmlproject.user.* 41 | 42 | # QtCreator CMake 43 | CMakeLists.txt.user* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Anton Lashkov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Protobuf-Qt 2 | 3 | This lib should help with usage of generated sources from Google Protobuf files with Qt and QML. 4 | 5 | ## Idea 6 | Just write plugin for current C++ generator: 7 | 8 | + Add getter/setter for std::string as QString 9 | + Mark all messages classes as QObject 10 | + Add Q_PROPERTY for all messages fields 11 | - Wrap repeated fields by QQmlListProperty 12 | - Add signals for fields changes 13 | 14 | ## Usage 15 | + Build compiler 16 | + Generate sources; example command: 17 | ```sh 18 | protoc --plugin=protoc-gen-qt=protoc-gen-qt --cpp_out=. --qt_out=. Test.proto 19 | ``` 20 | + Profit 21 | 22 | ## List of known insertion points (look at orignal C++ generator) 23 | 24 | `$full_name$` mean: 25 | 26 | + `package.ClassName` for message type 27 | + `package.ClassName.field_name` for field 28 | 29 | ### File (google/protobuf/compiler/cpp/cpp_file.cc) 30 | + includes 31 | + namespace_scope 32 | + global_scope 33 | 34 | ### Message type (google/protobuf/compiler/cpp/cpp_message.cc) 35 | + class_definition:$full_name$ 36 | + dep_base_class_definition:$full_name$ 37 | + class_scope:$full_name$ 38 | + constructor:$full_name$ 39 | + arena_constructor:$full_name$ 40 | + copy_constructor:$full_name$ 41 | + destructor:$full_name$ 42 | + message_clear_start:$full_name$ 43 | + one_of_clear_start:$full_name$ 44 | + generalized_merge_from_start:$full_name$ 45 | + generalized_merge_from_cast_fail:$full_name$ 46 | + generalized_merge_from_cast_success:$full_name$ 47 | + class_specific_merge_from_start:$full_name$ 48 | + generalized_copy_from_start:$full_name$ 49 | + class_specific_copy_from_start:$full_name$ 50 | + parse_start:$full_name$ 51 | + parse_success:$full_name$ 52 | + parse_failure:$full_name$ 53 | + serialize_start:$full_name$ 54 | + serialize_end:$full_name$ 55 | + serialize_to_array_start:$full_name$ 56 | + serialize_to_array_end:$full_name$ 57 | + message_set_byte_size_start:$full_name$ 58 | + required_fields_byte_size_fallback_start:$full_name$ 59 | + message_byte_size_start:$full_name$ 60 | 61 | ### Primitive field (google/protobuf/compiler/cpp/cpp_primitive_field.cc) 62 | + field_get:$full_name$ 63 | + field_set:$full_name$ 64 | 65 | ### Primitive repeated field (google/protobuf/compiler/cpp/cpp_primitive_field.cc) 66 | + field_get:$full_name$ 67 | + field_set:$full_name$ 68 | + field_add:$full_name$ 69 | + field_list:$full_name$ 70 | + field_mutable_list:$full_name$ 71 | 72 | ### String field (google/protobuf/compiler/cpp/cpp_string_field.cc) 73 | + field_get:$full_name$ 74 | + field_set:$full_name$ 75 | + field_set_rvalue:$full_name$ 76 | + field_set_char:$full_name$ 77 | + field_set_pointer:$full_name$ 78 | + field_mutable:$full_name$ 79 | + field_release:$full_name$ 80 | + field_set_allocated:$full_name$ 81 | + field_unsafe_arena_release:$full_name$ 82 | + field_unsafe_arena_set_allocated:$full_name$ 83 | 84 | ### String repeated field (google/protobuf/compiler/cpp/cpp_string_field.cc) 85 | + field_get:$full_name$ 86 | + field_set:$full_name$ 87 | + field_set_rvalue:$full_name$ 88 | + field_set_char:$full_name$ 89 | + field_set_pointer:$full_name$ 90 | + field_mutable:$full_name$ 91 | + field_add_mutable:$full_name$ 92 | + field_add:$full_name$ 93 | + field_add_char:$full_name$ 94 | + field_add_pointer:$full_name$ 95 | + field_list:$full_name$ 96 | + field_mutable_list:$full_name$ 97 | 98 | ### Enum field (google/protobuf/compiler/cpp/cpp_enum_field.cc) 99 | + field_get:$full_name$ 100 | + field_set:$full_name$ 101 | 102 | ### Enum repeated field (google/protobuf/compiler/cpp/cpp_enum_field.cc) 103 | + field_get:$full_name$ 104 | + field_set:$full_name$ 105 | + field_add:$full_name$ 106 | + field_list:$full_name$ 107 | + field_mutable_list:$full_name$ 108 | 109 | ### Map field (google/protobuf/compiler/cpp/cpp_map_field.cc) 110 | + field_map:$full_name$ 111 | + field_mutable_map:$full_name$ 112 | 113 | ### Message field (google/protobuf/compiler/cpp/cpp_message_field.cc) 114 | + field_unsafe_arena_set_allocated:$full_name$ 115 | + field_get:$full_name$ 116 | + field_release:$full_name$ 117 | + field_unsafe_arena_release:$full_name$ 118 | + field_mutable:$full_name$ 119 | + field_set_allocated:$full_name$ 120 | 121 | ### Message repeated field (google/protobuf/compiler/cpp/cpp_message_field.cc) 122 | + field_add:$full_name$ 123 | + field_mutable:$full_name$ 124 | + field_get:$full_name$ 125 | + field_list:$full_name$ -------------------------------------------------------------------------------- /compiler/compiler.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++11 c++14 c++17 c++1z 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | TARGET = protoc-gen-qt 7 | 8 | win32:INCLUDEPATH += $${PROTOBUF_SRC} 9 | win32:LIBS += -L$${PROTOBUF_LIBS} 10 | 11 | CONFIG(debug, debug|release) { 12 | unix:LIBS += -lprotobuf -lprotoc 13 | win32:LIBS += -llibprotobufd -llibprotocd 14 | } else { 15 | unix:LIBS += -lprotobuf -lprotoc 16 | win32:LIBS += -llibprotobuf -llibprotoc 17 | } 18 | 19 | SOURCES += main.cpp \ 20 | protobuf_qt_generator.cpp \ 21 | insertion_point_writer.cpp 22 | 23 | HEADERS += \ 24 | protobuf_qt_generator.h \ 25 | insertion_point_writer.h \ 26 | repeated_field_adaptor.h \ 27 | repeated_fields.h 28 | -------------------------------------------------------------------------------- /compiler/insertion_point_writer.cpp: -------------------------------------------------------------------------------- 1 | #include "insertion_point_writer.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | InsertionPointWriter::InsertionPointWriter(google::protobuf::compiler::GeneratorContext *generator_context, 8 | const std::string &filename, const std::string &insertion_point) 9 | : _stream(generator_context->OpenForInsert(filename, insertion_point)) 10 | , _printer(std::make_unique(_stream.get(), '$')) 11 | { 12 | } 13 | 14 | InsertionPointWriter::~InsertionPointWriter() = default; 15 | InsertionPointWriter::InsertionPointWriter(InsertionPointWriter &&) = default; 16 | InsertionPointWriter &InsertionPointWriter::operator=(InsertionPointWriter &&) = default; 17 | 18 | void InsertionPointWriter::write(const char *str) 19 | { 20 | _printer->Print(str); 21 | } 22 | 23 | void InsertionPointWriter::write(const char *str, const std::map ¶ms) 24 | { 25 | _printer->Print(params, str); 26 | } 27 | 28 | void InsertionPointWriter::writeln(const char *str) 29 | { 30 | _printer->Print(str); 31 | _printer->Print("\n"); 32 | } 33 | 34 | void InsertionPointWriter::writeln(const char *str, const std::map ¶ms) 35 | { 36 | _printer->Print(params, str); 37 | _printer->Print("\n"); 38 | } 39 | 40 | void InsertionPointWriter::indent() 41 | { 42 | _printer->Indent(); 43 | } 44 | 45 | void InsertionPointWriter::outdent() 46 | { 47 | _printer->Outdent(); 48 | } 49 | 50 | InsertionPointWriterFactory::InsertionPointWriterFactory(const std::string &filename, 51 | google::protobuf::compiler::GeneratorContext *generator_context) 52 | : _generator_context(generator_context) 53 | { 54 | auto filename_without_proto = filename.substr(0, filename.size() - strlen("proto")); 55 | _header = filename_without_proto + "pb.h"; 56 | _source = filename_without_proto + "pb.cc"; 57 | } 58 | 59 | InsertionPointWriter InsertionPointWriterFactory::make_header_writer(const std::string &insertion_point) 60 | { 61 | return InsertionPointWriter(_generator_context, _header, insertion_point); 62 | } 63 | 64 | InsertionPointWriter InsertionPointWriterFactory::make_source_writer(const std::string &insertion_point) 65 | { 66 | return InsertionPointWriter(_generator_context, _source, insertion_point); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /compiler/insertion_point_writer.h: -------------------------------------------------------------------------------- 1 | #ifndef INSERTION_POINT_WRITER_H 2 | #define INSERTION_POINT_WRITER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace google 8 | { 9 | namespace protobuf 10 | { 11 | namespace compiler 12 | { 13 | class GeneratorContext; 14 | } 15 | namespace io 16 | { 17 | class ZeroCopyOutputStream; 18 | class Printer; 19 | } 20 | } 21 | } 22 | 23 | class InsertionPointWriter 24 | { 25 | public: 26 | InsertionPointWriter(google::protobuf::compiler::GeneratorContext *generator_context, 27 | const std::string &filename, 28 | const std::string &insertion_point); 29 | 30 | ~InsertionPointWriter(); 31 | InsertionPointWriter(InsertionPointWriter &&); 32 | InsertionPointWriter &operator=(InsertionPointWriter &&); 33 | 34 | void write(const char *str); 35 | void write(const char *str, const std::map ¶ms); 36 | void writeln(const char *str); 37 | void writeln(const char *str, const std::map ¶ms); 38 | 39 | void indent(); 40 | void outdent(); 41 | 42 | private: 43 | std::unique_ptr _stream; 44 | std::unique_ptr _printer; 45 | }; 46 | 47 | class InsertionPointWriterFactory 48 | { 49 | public: 50 | InsertionPointWriterFactory(const std::string &filename, 51 | google::protobuf::compiler::GeneratorContext *generator_context); 52 | 53 | InsertionPointWriter make_header_writer(const std::string &insertion_point); 54 | InsertionPointWriter make_source_writer(const std::string &insertion_point); 55 | 56 | private: 57 | google::protobuf::compiler::GeneratorContext *_generator_context; 58 | 59 | std::string _header; 60 | std::string _source; 61 | }; 62 | 63 | #endif // INSERTION_POINT_WRITER_H 64 | -------------------------------------------------------------------------------- /compiler/main.cpp: -------------------------------------------------------------------------------- 1 | #include "protobuf_qt_generator.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | ProtobufQtGenerator generator; 10 | return google::protobuf::compiler::PluginMain(argc, argv, &generator); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /compiler/protobuf_qt_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "protobuf_qt_generator.h" 2 | 3 | #include "insertion_point_writer.h" 4 | #include "repeated_fields.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace 13 | { 14 | std::string dot_to_colon(const std::string &str) 15 | { 16 | const static std::regex regex(R"(\.)"); 17 | return std::regex_replace(str, regex, "::"); 18 | } 19 | 20 | std::string snake_to_camel(const std::string &str) 21 | { 22 | std::string result; 23 | result.reserve(str.size()); 24 | 25 | bool uppercase_next = false; 26 | for (char c : str) 27 | { 28 | if (c == '_') 29 | { 30 | uppercase_next = true; 31 | } 32 | else 33 | { 34 | result += uppercase_next ? static_cast(std::toupper(static_cast(c))) : c; 35 | uppercase_next = false; 36 | } 37 | } 38 | 39 | return result; 40 | } 41 | 42 | std::string to_lowercase(std::string str) 43 | { 44 | std::transform(str.begin(), str.end(), str.begin(), [](char c) 45 | { 46 | return static_cast(std::tolower(static_cast(c))); 47 | }); 48 | return str; 49 | } 50 | 51 | std::string cpp_type(const google::protobuf::Descriptor &message_descriptor) 52 | { 53 | return dot_to_colon(message_descriptor.full_name()); 54 | } 55 | 56 | std::string cpp_type(const google::protobuf::EnumDescriptor &enum_descriptor) 57 | { 58 | return dot_to_colon(enum_descriptor.full_name()); 59 | } 60 | 61 | std::string cpp_type(const google::protobuf::FieldDescriptor &field_descriptor) 62 | { 63 | google::protobuf::FieldDescriptor::CppType type = field_descriptor.cpp_type(); 64 | switch (type) 65 | { 66 | case google::protobuf::FieldDescriptor::CPPTYPE_INT32: 67 | return "qint32"; 68 | case google::protobuf::FieldDescriptor::CPPTYPE_INT64: 69 | return "qint64"; 70 | case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: 71 | return "quint32"; 72 | case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: 73 | return "quint64"; 74 | case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: 75 | return "qreal"; 76 | case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: 77 | return "qreal"; 78 | case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: 79 | return cpp_type(*field_descriptor.enum_type()); 80 | case google::protobuf::FieldDescriptor::CPPTYPE_STRING: 81 | return "QString"; 82 | case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: 83 | return cpp_type(*field_descriptor.message_type()); 84 | case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: 85 | return "bool"; 86 | } 87 | 88 | throw std::runtime_error("cpp_type: invalid field type"); 89 | } 90 | 91 | std::string cpp_wrapper_type(const google::protobuf::EnumDescriptor &enum_descriptor) 92 | { 93 | if (enum_descriptor.containing_type()) // enum in message 94 | { 95 | return cpp_type(*enum_descriptor.containing_type()) + "Wrapper::" + enum_descriptor.name(); 96 | } 97 | else // global enum 98 | { 99 | return cpp_type(enum_descriptor) + "Wrapper::" + enum_descriptor.name(); 100 | } 101 | } 102 | 103 | void generate_global_enum_declaration(InsertionPointWriter &writer, 104 | const google::protobuf::EnumDescriptor &enum_descriptor) 105 | { 106 | writer.write( 107 | "class $enum_name$Wrapper {\n" 108 | " Q_GADGET\n" 109 | "public:\n" 110 | " enum $enum_name$ {\n", 111 | { 112 | { "enum_name", enum_descriptor.name() } 113 | }); 114 | 115 | for (const google::protobuf::EnumValueDescriptor &enum_value : repeated_enum_value_adaptor(enum_descriptor)) 116 | { 117 | writer.write( 118 | " $enum_value$ = $source_enum_name$::$enum_value$,\n", 119 | { 120 | { "source_enum_name", cpp_type(enum_descriptor) }, 121 | { "enum_value", enum_value.name() } 122 | }); 123 | } 124 | 125 | writer.write( 126 | " };\n" 127 | " Q_ENUM($enum_name$)\n" 128 | "};\n" 129 | "\n", 130 | { 131 | { "enum_name", enum_descriptor.name() } 132 | }); 133 | } 134 | 135 | void generate_enum_declaration(InsertionPointWriter &writer, 136 | const google::protobuf::EnumDescriptor &enum_descriptor) 137 | { 138 | writer.write( 139 | " enum $enum_name$ {\n", 140 | { 141 | { "enum_name", enum_descriptor.name() } 142 | }); 143 | 144 | for (const google::protobuf::EnumValueDescriptor &enum_value : repeated_enum_value_adaptor(enum_descriptor)) 145 | { 146 | writer.write( 147 | " $enum_value$ = $source_enum_name$::$enum_value$,\n", 148 | { 149 | { "source_enum_name", cpp_type(*enum_descriptor.containing_type()) }, 150 | { "enum_value", enum_value.name() } 151 | }); 152 | } 153 | 154 | writer.write( 155 | " };\n" 156 | " Q_ENUM($enum_name$)\n" 157 | "\n", 158 | { 159 | { "enum_name", enum_descriptor.name() } 160 | }); 161 | } 162 | 163 | void generate_property_declaration(InsertionPointWriter &writer, 164 | const google::protobuf::FieldDescriptor &field) 165 | { 166 | if (field.is_map()) 167 | { 168 | 169 | } 170 | else if (field.is_repeated()) 171 | { 172 | 173 | } 174 | else 175 | { 176 | std::map params = 177 | { 178 | { "field_name", snake_to_camel(field.lowercase_name()) }, 179 | { "setter_name", snake_to_camel("set_" + field.lowercase_name()) } 180 | }; 181 | 182 | if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) 183 | { 184 | params["field_type"] = field.message_type()->name() + "Wrapper *"; 185 | return; 186 | } 187 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) 188 | { 189 | params["field_type"] = cpp_wrapper_type(*field.enum_type()); 190 | } 191 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) 192 | { 193 | if (field.options().has_ctype()) 194 | { 195 | return; 196 | } 197 | 198 | params["field_type"] = "QString"; 199 | } 200 | else 201 | { 202 | params["field_type"] = cpp_type(field); 203 | } 204 | 205 | writer.write(" Q_PROPERTY($field_type$ $field_name$ READ $field_name$ " 206 | "WRITE $setter_name$ NOTIFY $field_name$Changed)\n", params); 207 | } 208 | } 209 | 210 | void generate_signal_declaration(InsertionPointWriter &writer, 211 | const google::protobuf::FieldDescriptor &field) 212 | { 213 | if (field.is_map()) 214 | { 215 | 216 | } 217 | else if (field.is_repeated()) 218 | { 219 | 220 | } 221 | else 222 | { 223 | std::map params = 224 | { 225 | { "field_name", snake_to_camel(field.lowercase_name()) }, 226 | }; 227 | 228 | if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) 229 | { 230 | params["field_type"] = field.message_type()->name() + "Wrapper *"; 231 | return; 232 | } 233 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) 234 | { 235 | params["field_type"] = cpp_wrapper_type(*field.enum_type()); 236 | } 237 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) 238 | { 239 | if (field.options().has_ctype()) 240 | { 241 | return; 242 | } 243 | 244 | params["field_type"] = "QString"; 245 | } 246 | else 247 | { 248 | params["field_type"] = cpp_type(field); 249 | } 250 | 251 | writer.write(" void $field_name$Changed($field_type$ value);\n", params); 252 | } 253 | } 254 | 255 | void generate_setter_getter_declaration(InsertionPointWriter &writer, 256 | const google::protobuf::FieldDescriptor &field) 257 | { 258 | if (field.is_map()) 259 | { 260 | 261 | } 262 | else if (field.is_repeated()) 263 | { 264 | 265 | } 266 | else 267 | { 268 | std::map params = 269 | { 270 | { "field_name", snake_to_camel(field.lowercase_name()) }, 271 | { "setter_name", snake_to_camel("set_" + field.lowercase_name()) } 272 | }; 273 | 274 | if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) 275 | { 276 | params["field_type"] = field.message_type()->name() + "Wrapper *"; 277 | return; 278 | } 279 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) 280 | { 281 | params["field_type"] = cpp_wrapper_type(*field.enum_type()); 282 | } 283 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) 284 | { 285 | if (field.options().has_ctype()) 286 | { 287 | return; 288 | } 289 | 290 | params["field_type"] = "QString"; 291 | } 292 | else 293 | { 294 | params["field_type"] = cpp_type(field); 295 | } 296 | 297 | writer.write( 298 | " $field_type$ $field_name$() const;\n" 299 | " void $setter_name$($field_type$ value);\n", 300 | params); 301 | } 302 | } 303 | 304 | void generate_setter_getter_implementation(InsertionPointWriter &writer, 305 | const google::protobuf::FieldDescriptor &field, 306 | const std::string &class_name) 307 | { 308 | if (field.is_map()) 309 | { 310 | 311 | } 312 | else if (field.is_repeated()) 313 | { 314 | 315 | } 316 | else 317 | { 318 | std::map params = 319 | { 320 | { "field_name", snake_to_camel(field.lowercase_name()) }, 321 | { "setter_name", snake_to_camel("set_" + field.lowercase_name()) }, 322 | { "class_name", class_name }, 323 | { "source_class_name", dot_to_colon(field.containing_type()->full_name()) }, 324 | { "source_field_name", to_lowercase(field.name()) }, 325 | }; 326 | 327 | if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) 328 | { 329 | params["field_type"] = field.message_type()->name() + "Wrapper *"; 330 | return; 331 | } 332 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) 333 | { 334 | params["field_type"] = cpp_wrapper_type(*field.enum_type()); 335 | params["original_enum_type"] = dot_to_colon(field.enum_type()->full_name()); 336 | 337 | writer.write( 338 | " $field_type$ $class_name$Wrapper::$field_name$() const {\n" 339 | " return static_cast<$field_type$>($source_class_name$::$source_field_name$());\n" 340 | " }\n" 341 | "\n" 342 | " void $class_name$Wrapper::$setter_name$($field_type$ value) {\n" 343 | " $source_class_name$::set_$source_field_name$(static_cast<$original_enum_type$>(value));\n" 344 | " }\n" 345 | "\n" 346 | , params); 347 | } 348 | else if (field.cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) 349 | { 350 | if (field.options().has_ctype()) 351 | { 352 | return; 353 | } 354 | 355 | writer.write( 356 | " QString $class_name$Wrapper::$field_name$() const {\n" 357 | " return QString::fromStdString($source_class_name$::$source_field_name$());\n" 358 | " }\n" 359 | "\n" 360 | " void $class_name$Wrapper::$setter_name$(QString value) {\n" 361 | " $source_class_name$::set_$source_field_name$(value.toStdString());\n" 362 | " }\n" 363 | "\n" 364 | , params); 365 | } 366 | else 367 | { 368 | params["field_type"] = cpp_type(field); 369 | 370 | writer.write( 371 | " $field_type$ $class_name$Wrapper::$field_name$() const {\n" 372 | " return $source_class_name$::$source_field_name$();\n" 373 | " }\n" 374 | "\n" 375 | " void $class_name$Wrapper::$setter_name$($field_type$ value) {\n" 376 | " $source_class_name$::set_$source_field_name$(value);\n" 377 | " }\n" 378 | "\n" 379 | , params); 380 | } 381 | } 382 | } 383 | 384 | void generate_nested_typedef_declaration(InsertionPointWriter &writer, 385 | const google::protobuf::Descriptor &descriptor, 386 | const std::string &parent_class = "") 387 | { 388 | if (descriptor.options().map_entry()) 389 | { 390 | return; 391 | } 392 | 393 | const std::string class_name = parent_class.empty() 394 | ? descriptor.name() 395 | : parent_class + "_" + descriptor.name(); 396 | 397 | writer.write( 398 | " typedef $full_class_name$Wrapper $class_name$Wrapper;\n", 399 | { 400 | { "full_class_name", class_name }, 401 | { "class_name", descriptor.name() } 402 | }); 403 | } 404 | 405 | void generate_message_declaration(InsertionPointWriter &writer, 406 | const google::protobuf::Descriptor &descriptor, 407 | const std::string &parent_class = "") 408 | { 409 | if (descriptor.options().map_entry()) 410 | { 411 | return; 412 | } 413 | 414 | const std::string class_name = parent_class.empty() 415 | ? descriptor.name() 416 | : parent_class + "_" + descriptor.name(); 417 | 418 | for (const google::protobuf::Descriptor &nested_descriptor : repeated_nested_type_adaptor(descriptor)) 419 | { 420 | generate_message_declaration(writer, nested_descriptor, class_name); 421 | } 422 | 423 | writer.write( 424 | "class $class_name$Wrapper : public QObject, public $class_name$ {\n" 425 | " Q_OBJECT\n" 426 | , 427 | { 428 | { "class_name", class_name } 429 | }); 430 | 431 | writer.write( 432 | "\n" 433 | "public:\n" 434 | ); 435 | 436 | for (const google::protobuf::EnumDescriptor &enum_descriptor : repeated_enum_adaptor(descriptor)) 437 | { 438 | generate_enum_declaration(writer, enum_descriptor); 439 | } 440 | 441 | writer.write( 442 | "private:\n" 443 | ); 444 | 445 | for (const google::protobuf::FieldDescriptor &field : repeated_field_adaptor(descriptor)) 446 | { 447 | generate_property_declaration(writer, field); 448 | } 449 | 450 | writer.write( 451 | "\n" 452 | "public:\n" 453 | ); 454 | 455 | for (const google::protobuf::Descriptor &nested_descriptor : repeated_nested_type_adaptor(descriptor)) 456 | { 457 | generate_nested_typedef_declaration(writer, nested_descriptor, class_name); 458 | } 459 | 460 | writer.write( 461 | "\n" 462 | "signals:\n" 463 | ); 464 | 465 | for (const google::protobuf::FieldDescriptor &field : repeated_field_adaptor(descriptor)) 466 | { 467 | generate_signal_declaration(writer, field); 468 | } 469 | 470 | writer.write( 471 | "\n" 472 | "public:\n" 473 | ); 474 | 475 | for (const google::protobuf::FieldDescriptor &field : repeated_field_adaptor(descriptor)) 476 | { 477 | generate_setter_getter_declaration(writer, field); 478 | } 479 | 480 | writer.write( 481 | "};\n" 482 | "\n", 483 | { 484 | }); 485 | } 486 | 487 | void generate_message_implementation(InsertionPointWriter &writer, 488 | const google::protobuf::Descriptor &descriptor, 489 | const std::string &parent_class = "") 490 | { 491 | if (descriptor.options().map_entry()) 492 | { 493 | return; 494 | } 495 | 496 | const std::string class_name = parent_class.empty() 497 | ? descriptor.name() 498 | : parent_class + "_" + descriptor.name(); 499 | 500 | for (const google::protobuf::Descriptor &nested_descriptor : repeated_nested_type_adaptor(descriptor)) 501 | { 502 | generate_message_implementation(writer, nested_descriptor, class_name); 503 | } 504 | 505 | for (const google::protobuf::FieldDescriptor &field : repeated_field_adaptor(descriptor)) 506 | { 507 | generate_setter_getter_implementation(writer, field, class_name); 508 | } 509 | } 510 | 511 | void generate_forward_declaration(InsertionPointWriter &writer, 512 | const google::protobuf::Descriptor &descriptor, 513 | const std::string &parent_class = "") 514 | { 515 | if (descriptor.options().map_entry()) 516 | { 517 | return; 518 | } 519 | 520 | const std::string class_name = parent_class.empty() 521 | ? descriptor.name() 522 | : parent_class + "_" + descriptor.name(); 523 | 524 | writer.write("class $class_name$Wrapper;\n", {{"class_name", class_name}}); 525 | 526 | for (const google::protobuf::Descriptor &nested_descriptor : repeated_nested_type_adaptor(descriptor)) 527 | { 528 | generate_forward_declaration(writer, nested_descriptor, class_name); 529 | } 530 | } 531 | 532 | 533 | } 534 | 535 | bool ProtobufQtGenerator::Generate(const google::protobuf::FileDescriptor *file, 536 | const std::string &/*parameter*/, 537 | google::protobuf::compiler::GeneratorContext *generator_context, 538 | std::string *error) const 539 | { 540 | try 541 | { 542 | InsertionPointWriterFactory writer_factory(file->name(), generator_context); 543 | Generate(*file, writer_factory); 544 | } 545 | catch (const std::exception &ex) 546 | { 547 | *error = ex.what(); 548 | return false; 549 | } 550 | 551 | return true; 552 | } 553 | 554 | void ProtobufQtGenerator::Generate(const google::protobuf::FileDescriptor &file, 555 | InsertionPointWriterFactory &writer_factory) const 556 | { 557 | { 558 | auto writer = writer_factory.make_header_writer("includes"); 559 | writer.writeln("#include "); 560 | } 561 | 562 | auto header_writer = writer_factory.make_header_writer("namespace_scope"); 563 | auto source_writer = writer_factory.make_source_writer("namespace_scope"); 564 | 565 | for (const google::protobuf::Descriptor &descriptor : repeated_message_adaptor(file)) 566 | { 567 | generate_forward_declaration(header_writer, descriptor); 568 | } 569 | 570 | header_writer.write("\n"); 571 | 572 | for (const google::protobuf::EnumDescriptor &global_enum : repeated_enum_adaptor(file)) 573 | { 574 | generate_global_enum_declaration(header_writer, global_enum); 575 | } 576 | 577 | for (const google::protobuf::Descriptor &descriptor : repeated_message_adaptor(file)) 578 | { 579 | generate_message_declaration(header_writer, descriptor); 580 | generate_message_implementation(source_writer, descriptor); 581 | } 582 | } 583 | -------------------------------------------------------------------------------- /compiler/protobuf_qt_generator.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOBUF_QT_GENERATOR_H 2 | #define PROTOBUF_QT_GENERATOR_H 3 | 4 | #include 5 | 6 | class InsertionPointWriterFactory; 7 | 8 | class ProtobufQtGenerator : public google::protobuf::compiler::CodeGenerator 9 | { 10 | public: 11 | ProtobufQtGenerator() = default; 12 | 13 | bool Generate(const google::protobuf::FileDescriptor *file, 14 | const std::string ¶meter, 15 | google::protobuf::compiler::GeneratorContext *generator_context, 16 | std::string *error) const override; 17 | 18 | void Generate(const google::protobuf::FileDescriptor &file, 19 | InsertionPointWriterFactory &writer_factory) const; 20 | }; 21 | 22 | #endif // PROTOBUF_QT_GENERATOR_H 23 | -------------------------------------------------------------------------------- /compiler/repeated_field_adaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef REPEATED_FIELD_ADAPTOR_H 2 | #define REPEATED_FIELD_ADAPTOR_H 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class repeated_adaptor_impl 9 | { 10 | class iterator 11 | { 12 | public: 13 | iterator(const Object &object, GetFunction get_func, int index) 14 | : _object(object) 15 | , _get_func(get_func) 16 | , _index(index) 17 | { 18 | } 19 | 20 | iterator &operator++() 21 | { 22 | ++_index; 23 | return *this; 24 | } 25 | 26 | bool operator!=(const iterator &other) 27 | { 28 | return _index != other._index; 29 | } 30 | 31 | const auto &operator*() 32 | { 33 | return *(std::invoke(_get_func, std::ref(_object), _index)); 34 | } 35 | 36 | private: 37 | const Object &_object; 38 | GetFunction _get_func; 39 | int _index; 40 | }; 41 | 42 | public: 43 | repeated_adaptor_impl(const Object &object, CountFunction count_func, GetFunction get_func) 44 | : _object(object) 45 | , _count_func(count_func) 46 | , _get_func(get_func) 47 | { 48 | } 49 | 50 | auto begin() const 51 | { 52 | return iterator(_object, _get_func, 0); 53 | } 54 | 55 | auto begin() 56 | { 57 | return iterator(_object, _get_func, 0); 58 | } 59 | 60 | auto end() const 61 | { 62 | return iterator(_object, _get_func, std::invoke(_count_func, std::ref(_object))); 63 | } 64 | 65 | auto end() 66 | { 67 | return iterator(_object, _get_func, std::invoke(_count_func, std::ref(_object))); 68 | } 69 | 70 | private: 71 | const Object &_object; 72 | CountFunction _count_func; 73 | GetFunction _get_func; 74 | }; 75 | 76 | template 80 | repeated_adaptor_impl repeated_adaptor(const Object &object, 81 | int (Object::* count_func)() const, const Result * (Object::* get_func)(int) const) 82 | { 83 | return repeated_adaptor_impl(object, count_func, get_func); 84 | } 85 | 86 | #endif // REPEATED_FIELD_ADAPTOR_H 87 | -------------------------------------------------------------------------------- /compiler/repeated_fields.h: -------------------------------------------------------------------------------- 1 | #ifndef REPEATED_FIELDS_H 2 | #define REPEATED_FIELDS_H 3 | 4 | #include "repeated_field_adaptor.h" 5 | 6 | #include 7 | 8 | inline auto repeated_message_adaptor(const google::protobuf::FileDescriptor &file_descriptor) 9 | { 10 | return repeated_adaptor(file_descriptor, 11 | &google::protobuf::FileDescriptor::message_type_count, 12 | &google::protobuf::FileDescriptor::message_type); 13 | } 14 | 15 | inline auto repeated_enum_adaptor(const google::protobuf::FileDescriptor &file_descriptor) 16 | { 17 | return repeated_adaptor(file_descriptor, 18 | &google::protobuf::FileDescriptor::enum_type_count, 19 | &google::protobuf::FileDescriptor::enum_type); 20 | } 21 | 22 | inline auto repeated_enum_value_adaptor(const google::protobuf::EnumDescriptor &enum_descriptor) 23 | { 24 | return repeated_adaptor(enum_descriptor, 25 | &google::protobuf::EnumDescriptor::value_count, 26 | &google::protobuf::EnumDescriptor::value); 27 | } 28 | 29 | inline auto repeated_field_adaptor(const google::protobuf::Descriptor &message_descriptor) 30 | { 31 | return repeated_adaptor(message_descriptor, 32 | &google::protobuf::Descriptor::field_count, 33 | &google::protobuf::Descriptor::field); 34 | } 35 | 36 | inline auto repeated_oneof_adaptor(const google::protobuf::Descriptor &message_descriptor) 37 | { 38 | return repeated_adaptor(message_descriptor, 39 | &google::protobuf::Descriptor::oneof_decl_count, 40 | &google::protobuf::Descriptor::oneof_decl); 41 | } 42 | 43 | inline auto repeated_nested_type_adaptor(const google::protobuf::Descriptor &message_descriptor) 44 | { 45 | return repeated_adaptor(message_descriptor, 46 | &google::protobuf::Descriptor::nested_type_count, 47 | &google::protobuf::Descriptor::nested_type); 48 | } 49 | 50 | inline auto repeated_enum_adaptor(const google::protobuf::Descriptor &message_descriptor) 51 | { 52 | return repeated_adaptor(message_descriptor, 53 | &google::protobuf::Descriptor::enum_type_count, 54 | &google::protobuf::Descriptor::enum_type); 55 | } 56 | 57 | inline auto repeated_field_adaptor(const google::protobuf::OneofDescriptor &oneof_descriptor) 58 | { 59 | return repeated_adaptor(oneof_descriptor, 60 | &google::protobuf::OneofDescriptor::field_count, 61 | &google::protobuf::OneofDescriptor::field); 62 | } 63 | 64 | #endif // REPEATED_FIELDS_H 65 | -------------------------------------------------------------------------------- /include/include.pri: -------------------------------------------------------------------------------- 1 | 2 | #HEADERS += 3 | #SOURCES += 4 | -------------------------------------------------------------------------------- /include/include.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | include(include.pri) 4 | -------------------------------------------------------------------------------- /protobuf_qt.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | CONFIG += ordered 3 | 4 | SUBDIRS = \ 5 | include \ 6 | compiler \ 7 | tests 8 | 9 | tests.depends = compiler 10 | -------------------------------------------------------------------------------- /tests/main_test.cpp: -------------------------------------------------------------------------------- 1 | #include "test_messages_proto3.pb.h" 2 | 3 | #include 4 | 5 | int main(int /*argc*/, char */*argv*/[]) 6 | { 7 | protobuf_test_messages::proto3::TestAllTypes m1; 8 | Q_UNUSED(m1); 9 | protobuf_test_messages::proto3::ForeignMessage m2; 10 | Q_UNUSED(m2); 11 | protobuf_test_messages::proto3::ForeignEnum e1; 12 | Q_UNUSED(e1); 13 | } 14 | -------------------------------------------------------------------------------- /tests/test_messages_proto3.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | // Test schema for proto3 messages. This test schema is used by: 32 | // 33 | // - benchmarks 34 | // - fuzz tests 35 | // - conformance tests 36 | // 37 | 38 | syntax = "proto3"; 39 | 40 | package protobuf_test_messages.proto3; 41 | option java_package = "com.google.protobuf_test_messages.proto3"; 42 | 43 | // This is the default, but we specify it here explicitly. 44 | option optimize_for = SPEED; 45 | 46 | import "google/protobuf/any.proto"; 47 | import "google/protobuf/duration.proto"; 48 | import "google/protobuf/field_mask.proto"; 49 | import "google/protobuf/struct.proto"; 50 | import "google/protobuf/timestamp.proto"; 51 | import "google/protobuf/wrappers.proto"; 52 | 53 | option cc_enable_arenas = true; 54 | 55 | // This proto includes every type of field in both singular and repeated 56 | // forms. 57 | // 58 | // Also, crucially, all messages and enums in this file are eventually 59 | // submessages of this message. So for example, a fuzz test of TestAllTypes 60 | // could trigger bugs that occur in any message type in this file. We verify 61 | // this stays true in a unit test. 62 | message TestAllTypes { 63 | message NestedMessage { 64 | int32 a = 1; 65 | TestAllTypes corecursive = 2; 66 | } 67 | 68 | enum NestedEnum { 69 | FOO = 0; 70 | BAR = 1; 71 | BAZ = 2; 72 | NEG = -1; // Intentionally negative. 73 | } 74 | 75 | // Singular 76 | int32 optional_int32 = 1; 77 | int64 optional_int64 = 2; 78 | uint32 optional_uint32 = 3; 79 | uint64 optional_uint64 = 4; 80 | sint32 optional_sint32 = 5; 81 | sint64 optional_sint64 = 6; 82 | fixed32 optional_fixed32 = 7; 83 | fixed64 optional_fixed64 = 8; 84 | sfixed32 optional_sfixed32 = 9; 85 | sfixed64 optional_sfixed64 = 10; 86 | float optional_float = 11; 87 | double optional_double = 12; 88 | bool optional_bool = 13; 89 | string optional_string = 14; 90 | bytes optional_bytes = 15; 91 | 92 | NestedMessage optional_nested_message = 18; 93 | ForeignMessage optional_foreign_message = 19; 94 | 95 | NestedEnum optional_nested_enum = 21; 96 | ForeignEnum optional_foreign_enum = 22; 97 | 98 | string optional_string_piece = 24 [ctype=STRING_PIECE]; 99 | string optional_cord = 25 [ctype=CORD]; 100 | 101 | TestAllTypes recursive_message = 27; 102 | 103 | // Repeated 104 | repeated int32 repeated_int32 = 31; 105 | repeated int64 repeated_int64 = 32; 106 | repeated uint32 repeated_uint32 = 33; 107 | repeated uint64 repeated_uint64 = 34; 108 | repeated sint32 repeated_sint32 = 35; 109 | repeated sint64 repeated_sint64 = 36; 110 | repeated fixed32 repeated_fixed32 = 37; 111 | repeated fixed64 repeated_fixed64 = 38; 112 | repeated sfixed32 repeated_sfixed32 = 39; 113 | repeated sfixed64 repeated_sfixed64 = 40; 114 | repeated float repeated_float = 41; 115 | repeated double repeated_double = 42; 116 | repeated bool repeated_bool = 43; 117 | repeated string repeated_string = 44; 118 | repeated bytes repeated_bytes = 45; 119 | 120 | repeated NestedMessage repeated_nested_message = 48; 121 | repeated ForeignMessage repeated_foreign_message = 49; 122 | 123 | repeated NestedEnum repeated_nested_enum = 51; 124 | repeated ForeignEnum repeated_foreign_enum = 52; 125 | 126 | repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; 127 | repeated string repeated_cord = 55 [ctype=CORD]; 128 | 129 | // Map 130 | map < int32, int32> map_int32_int32 = 56; 131 | map < int64, int64> map_int64_int64 = 57; 132 | map < uint32, uint32> map_uint32_uint32 = 58; 133 | map < uint64, uint64> map_uint64_uint64 = 59; 134 | map < sint32, sint32> map_sint32_sint32 = 60; 135 | map < sint64, sint64> map_sint64_sint64 = 61; 136 | map < fixed32, fixed32> map_fixed32_fixed32 = 62; 137 | map < fixed64, fixed64> map_fixed64_fixed64 = 63; 138 | map map_sfixed32_sfixed32 = 64; 139 | map map_sfixed64_sfixed64 = 65; 140 | map < int32, float> map_int32_float = 66; 141 | map < int32, double> map_int32_double = 67; 142 | map < bool, bool> map_bool_bool = 68; 143 | map < string, string> map_string_string = 69; 144 | map < string, bytes> map_string_bytes = 70; 145 | map < string, NestedMessage> map_string_nested_message = 71; 146 | map < string, ForeignMessage> map_string_foreign_message = 72; 147 | map < string, NestedEnum> map_string_nested_enum = 73; 148 | map < string, ForeignEnum> map_string_foreign_enum = 74; 149 | 150 | oneof oneof_field { 151 | uint32 oneof_uint32 = 111; 152 | NestedMessage oneof_nested_message = 112; 153 | string oneof_string = 113; 154 | bytes oneof_bytes = 114; 155 | bool oneof_bool = 115; 156 | uint64 oneof_uint64 = 116; 157 | float oneof_float = 117; 158 | double oneof_double = 118; 159 | NestedEnum oneof_enum = 119; 160 | } 161 | 162 | // Well-known types 163 | google.protobuf.BoolValue optional_bool_wrapper = 201; 164 | google.protobuf.Int32Value optional_int32_wrapper = 202; 165 | google.protobuf.Int64Value optional_int64_wrapper = 203; 166 | google.protobuf.UInt32Value optional_uint32_wrapper = 204; 167 | google.protobuf.UInt64Value optional_uint64_wrapper = 205; 168 | google.protobuf.FloatValue optional_float_wrapper = 206; 169 | google.protobuf.DoubleValue optional_double_wrapper = 207; 170 | google.protobuf.StringValue optional_string_wrapper = 208; 171 | google.protobuf.BytesValue optional_bytes_wrapper = 209; 172 | 173 | repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; 174 | repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; 175 | repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; 176 | repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; 177 | repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; 178 | repeated google.protobuf.FloatValue repeated_float_wrapper = 216; 179 | repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; 180 | repeated google.protobuf.StringValue repeated_string_wrapper = 218; 181 | repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; 182 | 183 | google.protobuf.Duration optional_duration = 301; 184 | google.protobuf.Timestamp optional_timestamp = 302; 185 | google.protobuf.FieldMask optional_field_mask = 303; 186 | google.protobuf.Struct optional_struct = 304; 187 | google.protobuf.Any optional_any = 305; 188 | google.protobuf.Value optional_value = 306; 189 | 190 | repeated google.protobuf.Duration repeated_duration = 311; 191 | repeated google.protobuf.Timestamp repeated_timestamp = 312; 192 | repeated google.protobuf.FieldMask repeated_fieldmask = 313; 193 | repeated google.protobuf.Struct repeated_struct = 324; 194 | repeated google.protobuf.Any repeated_any = 315; 195 | repeated google.protobuf.Value repeated_value = 316; 196 | 197 | // Test field-name-to-JSON-name convention. 198 | // (protobuf says names can be any valid C/C++ identifier.) 199 | int32 fieldname1 = 401; 200 | int32 field_name2 = 402; 201 | int32 _field_name3 = 403; 202 | int32 field__name4_ = 404; 203 | int32 field0name5 = 405; 204 | int32 field_0_name6 = 406; 205 | int32 fieldName7 = 407; 206 | int32 FieldName8 = 408; 207 | int32 field_Name9 = 409; 208 | int32 Field_Name10 = 410; 209 | int32 FIELD_NAME11 = 411; 210 | int32 FIELD_name12 = 412; 211 | int32 __field_name13 = 413; 212 | int32 __Field_name14 = 414; 213 | int32 field__name15 = 415; 214 | int32 field__Name16 = 416; 215 | int32 field_name17__ = 417; 216 | int32 Field_name18__ = 418; 217 | } 218 | 219 | message ForeignMessage { 220 | int32 c = 1; 221 | } 222 | 223 | enum ForeignEnum { 224 | FOREIGN_FOO = 0; 225 | FOREIGN_BAR = 1; 226 | FOREIGN_BAZ = 2; 227 | } 228 | -------------------------------------------------------------------------------- /tests/tests.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++11 3 | CONFIG -= app_bundle 4 | QT += qml 5 | 6 | TARGET = protobuf_qt_test 7 | 8 | win32:INCLUDEPATH += $${PROTOBUF_SRC} 9 | win32:LIBS += -L$${PROTOBUF_LIBS} 10 | win32:LIBS += -llibprotobuf 11 | 12 | unix:LIBS += -lprotobuf 13 | 14 | SOURCES += main_test.cpp 15 | 16 | PROTOS = test_messages_proto3.proto 17 | 18 | PROTOC = protoc 19 | PROTOC_GEN_QT=../compiler/protoc-gen-qt 20 | 21 | protobuf_decl.name = protobuf headers 22 | protobuf_decl.input = PROTOS 23 | protobuf_decl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h 24 | protobuf_decl.commands = $${PROTOC} --plugin=protoc-gen-qt=$${PROTOC_GEN_QT} --cpp_out=${QMAKE_FILE_IN_PATH} --qt_out=${QMAKE_FILE_IN_PATH} -I=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_IN} 25 | protobuf_decl.variable_out = HEADERS 26 | QMAKE_EXTRA_COMPILERS += protobuf_decl 27 | 28 | protobuf_impl.name = protobuf sources 29 | protobuf_impl.input = PROTOS 30 | protobuf_impl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.cc 31 | protobuf_impl.depends = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h 32 | protobuf_impl.commands = $$escape_expand(\n) 33 | protobuf_impl.variable_out = SOURCES 34 | QMAKE_EXTRA_COMPILERS += protobuf_impl 35 | 36 | --------------------------------------------------------------------------------