4
4
// SPDX-License-Identifier: MIT OR Apache-2.0
5
5
6
6
use crate :: generator:: cpp:: { fragment:: CppFragmentPair , GeneratedCppBlocks } ;
7
+ use crate :: writer:: cpp:: namespace_pair;
7
8
use indoc:: formatdoc;
8
9
9
10
/// Extract the header from a given CppFragmentPair
@@ -33,6 +34,91 @@ fn create_block(block: &str, items: &[&str]) -> String {
33
34
}
34
35
}
35
36
37
+ /// For a given GeneratedCppBlocks write the forward declare
38
+ fn forward_declare ( generated : & GeneratedCppBlocks ) -> Vec < String > {
39
+ let ( namespace_start, namespace_end) = namespace_pair ( generated) ;
40
+
41
+ generated
42
+ . qobjects
43
+ . iter ( )
44
+ . map ( |qobject| {
45
+ formatdoc ! { r#"
46
+ {namespace_start}
47
+ class {ident};
48
+ using {cxx_qt_thread_ident} = rust::cxxqtlib1::CxxQtThread<{ident}>;
49
+ {namespace_end}
50
+ "# ,
51
+ ident = qobject. ident,
52
+ cxx_qt_thread_ident = qobject. cxx_qt_thread_ident,
53
+ namespace_start = namespace_start,
54
+ namespace_end = namespace_end,
55
+ }
56
+ } )
57
+ . collect :: < Vec < String > > ( )
58
+ }
59
+
60
+ /// For a given GeneratedCppBlocks write the classes
61
+ fn qobjects_header ( generated : & GeneratedCppBlocks ) -> Vec < String > {
62
+ let ( namespace_start, namespace_end) = namespace_pair ( generated) ;
63
+
64
+ generated. qobjects . iter ( ) . map ( |qobject| {
65
+ formatdoc ! { r#"
66
+ {namespace_start}
67
+ class {ident} : public {base_class}
68
+ {{
69
+ Q_OBJECT
70
+ {metaobjects}
71
+
72
+ public:
73
+ explicit {ident}(QObject* parent = nullptr);
74
+ ~{ident}();
75
+ const {rust_ident}& unsafeRust() const;
76
+ {rust_ident}& unsafeRustMut();
77
+ std::unique_ptr<{cxx_qt_thread_ident}> qtThread() const;
78
+
79
+ {methods}
80
+ {slots}
81
+ {signals}
82
+ private:
83
+ rust::Box<{rust_ident}> m_rustObj;
84
+ std::shared_ptr<std::mutex> m_rustObjMutex;
85
+ bool m_initialised = false;
86
+ std::shared_ptr<rust::cxxqtlib1::CxxQtGuardedPointer<{ident}>> m_cxxQtThreadObj;
87
+
88
+ {members}
89
+ }};
90
+
91
+ static_assert(std::is_base_of<QObject, {ident}>::value, "{ident} must inherit from QObject");
92
+ {namespace_end}
93
+
94
+ namespace {namespace_internals} {{
95
+ std::unique_ptr<{ident}>
96
+ newCppObject();
97
+ }} // namespace {namespace_internals}
98
+
99
+ Q_DECLARE_METATYPE({metatype}*)
100
+ "# ,
101
+ ident = qobject. ident,
102
+ cxx_qt_thread_ident = qobject. cxx_qt_thread_ident,
103
+ namespace_start = namespace_start,
104
+ namespace_end = namespace_end,
105
+ namespace_internals = qobject. namespace_internals,
106
+ rust_ident = qobject. rust_ident,
107
+ base_class = qobject. base_class,
108
+ metaobjects = qobject. metaobjects. join( "\n " ) ,
109
+ methods = create_block( "public" , & qobject. methods. iter( ) . map( pair_as_header) . collect:: <Vec <& str >>( ) ) ,
110
+ slots = create_block( "public Q_SLOTS" , & qobject. slots. iter( ) . map( pair_as_header) . collect:: <Vec <& str >>( ) ) ,
111
+ signals = create_block( "Q_SIGNALS" , & qobject. signals. iter( ) . map( AsRef :: as_ref) . collect:: <Vec <& str >>( ) ) ,
112
+ members = qobject. members. join( "\n " ) ,
113
+ metatype = if generated. namespace. is_empty( ) {
114
+ qobject. ident. clone( )
115
+ } else {
116
+ format!( "{namespace}::{ident}" , namespace = generated. namespace, ident = qobject. ident)
117
+ } ,
118
+ }
119
+ } ) . collect :: < Vec < String > > ( )
120
+ }
121
+
36
122
/// For a given GeneratedCppBlocks write this into a C++ header
37
123
pub fn write_cpp_header ( generated : & GeneratedCppBlocks ) -> String {
38
124
formatdoc ! { r#"
@@ -46,74 +132,14 @@ pub fn write_cpp_header(generated: &GeneratedCppBlocks) -> String {
46
132
class CxxQtThread;
47
133
}}
48
134
49
- {namespace_start}
50
- class {ident};
51
- using {cxx_qt_thread_ident} = rust::cxxqtlib1::CxxQtThread<{ident}>;
52
- {namespace_end}
53
-
135
+ {forward_declare}
54
136
#include "cxx-qt-gen/include/{cxx_stem}.cxx.h"
55
137
56
- {namespace_start}
57
- class {ident} : public {base_class}
58
- {{
59
- Q_OBJECT
60
- {metaobjects}
61
-
62
- public:
63
- explicit {ident}(QObject* parent = nullptr);
64
- ~{ident}();
65
- const {rust_ident}& unsafeRust() const;
66
- {rust_ident}& unsafeRustMut();
67
- std::unique_ptr<{cxx_qt_thread_ident}> qtThread() const;
68
-
69
- {methods}
70
- {slots}
71
- {signals}
72
- private:
73
- rust::Box<{rust_ident}> m_rustObj;
74
- std::shared_ptr<std::mutex> m_rustObjMutex;
75
- bool m_initialised = false;
76
- std::shared_ptr<rust::cxxqtlib1::CxxQtGuardedPointer<{ident}>> m_cxxQtThreadObj;
77
-
78
- {members}
79
- }};
80
-
81
- static_assert(std::is_base_of<QObject, {ident}>::value, "{ident} must inherit from QObject");
82
- {namespace_end}
83
-
84
- namespace {namespace_internals} {{
85
- std::unique_ptr<{ident}>
86
- newCppObject();
87
- }} // namespace {namespace_internals}
88
-
89
- Q_DECLARE_METATYPE({metatype}*)
138
+ {qobjects}
90
139
"# ,
91
140
cxx_stem = generated. cxx_stem,
92
- ident = generated. ident,
93
- cxx_qt_thread_ident = generated. cxx_qt_thread_ident,
94
- namespace_start = if generated. namespace. is_empty( ) {
95
- "" . to_owned( )
96
- } else {
97
- format!( "namespace {namespace} {{" , namespace = generated. namespace)
98
- } ,
99
- namespace_end = if generated. namespace. is_empty( ) {
100
- "" . to_owned( )
101
- } else {
102
- format!( "}} // namespace {namespace}" , namespace = generated. namespace)
103
- } ,
104
- namespace_internals = generated. namespace_internals,
105
- rust_ident = generated. rust_ident,
106
- base_class = generated. base_class,
107
- metaobjects = generated. metaobjects. join( "\n " ) ,
108
- methods = create_block( "public" , & generated. methods. iter( ) . map( pair_as_header) . collect:: <Vec <& str >>( ) ) ,
109
- slots = create_block( "public Q_SLOTS" , & generated. slots. iter( ) . map( pair_as_header) . collect:: <Vec <& str >>( ) ) ,
110
- signals = create_block( "Q_SIGNALS" , & generated. signals. iter( ) . map( AsRef :: as_ref) . collect:: <Vec <& str >>( ) ) ,
111
- members = generated. members. join( "\n " ) ,
112
- metatype = if generated. namespace. is_empty( ) {
113
- generated. ident. clone( )
114
- } else {
115
- format!( "{namespace}::{ident}" , namespace = generated. namespace, ident = generated. ident)
116
- } ,
141
+ forward_declare = forward_declare( generated) . join( "\n " ) ,
142
+ qobjects = qobjects_header( generated) . join( "\n " ) ,
117
143
}
118
144
}
119
145
@@ -122,7 +148,8 @@ mod tests {
122
148
use super :: * ;
123
149
124
150
use crate :: writer:: cpp:: tests:: {
125
- create_generated_cpp, create_generated_cpp_no_namespace, expected_header,
151
+ create_generated_cpp, create_generated_cpp_multi_qobjects,
152
+ create_generated_cpp_no_namespace, expected_header, expected_header_multi_qobjects,
126
153
expected_header_no_namespace,
127
154
} ;
128
155
use indoc:: indoc;
@@ -157,6 +184,13 @@ mod tests {
157
184
assert_str_eq ! ( output, expected_header( ) ) ;
158
185
}
159
186
187
+ #[ test]
188
+ fn test_write_cpp_header_multi_qobjects ( ) {
189
+ let generated = create_generated_cpp_multi_qobjects ( ) ;
190
+ let output = write_cpp_header ( & generated) ;
191
+ assert_str_eq ! ( output, expected_header_multi_qobjects( ) ) ;
192
+ }
193
+
160
194
#[ test]
161
195
fn test_write_cpp_header_no_namespace ( ) {
162
196
let generated = create_generated_cpp_no_namespace ( ) ;
0 commit comments