Skip to content

Commit 74b7a1f

Browse files
author
Leon Matthes
authored
Merge branch 'main' into wrapper-shorthand
2 parents 7b53406 + ad01647 commit 74b7a1f

File tree

29 files changed

+893
-741
lines changed

29 files changed

+893
-741
lines changed

.github/workflows/github-cxx-qt-tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ jobs:
290290
- name: Ubuntu 24.04 (gcc) Qt6
291291
os: ubuntu-24.04
292292
qt_version: 6
293-
aqt_version: '6.9.0'
293+
aqt_version: '6.9.3'
294294
aqt_arch: 'linux_gcc_64'
295295
aqt_host: 'linux'
296296
cores: 4
@@ -334,10 +334,10 @@ jobs:
334334
- name: macOS 14 (clang) Qt6
335335
os: macos-14
336336
qt_version: 6
337-
aqt_version: '6.9.0'
337+
aqt_version: '6.9.3'
338338
aqt_arch: 'clang_64'
339339
aqt_host: 'mac'
340-
dyld_framework_path: /Users/runner/work/cxx-qt/Qt/6.9.0/macos/lib
340+
dyld_framework_path: /Users/runner/work/cxx-qt/Qt/6.9.3/macos/lib
341341
# https://doc.qt.io/qt-6.7/macos.html#target-platforms
342342
macosx_deployment_target: '13.0'
343343
cores: 3
@@ -394,7 +394,7 @@ jobs:
394394
- name: Windows 2022 (MSVC2022) Qt6 Debug
395395
os: windows-2022
396396
qt_version: 6
397-
aqt_version: '6.9.0'
397+
aqt_version: '6.9.3'
398398
aqt_arch: 'win64_msvc2022_64'
399399
aqt_host: 'windows'
400400
cores: 4

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
- Support for `QMessageLogContext` and sending log messages to the Qt message handler.
3636
- Serde support for further types: `QByteArray`, `QSet`, `QStringList`, `QVector`, `QUrl`
3737
- Added `QEventLoop` to cxx-qt-lib-extras.
38-
- Add `QScopedMetaObjectConnectionGuard`, which is `QMetaObjectConnectionGuard` with a scoped lifetime. `QMetaObjectConnectionGuard` is now a type alias for `QScopedMetaObjectConnectionGuard<'static>`.
3938
- Support for setting Qt log message patterns with `q_set_message_pattern` and formatting log messages ith `q_format_log_message`.
4039
- Implement `IntoIterator` for `&QHash`, `&QList`, `&QMap`, `&QSet`, and `&QVector`.
4140
- Add `QByteArray:from_base64_encoding` and `QByteArray::to_base64`.

crates/cxx-qt-gen/src/generator/cpp/qenum.rs

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ use syn::Result;
1010

1111
use crate::{
1212
generator::{cfg::try_eval_attributes, GeneratedOpt},
13+
naming::Name,
1314
parser::qenum::ParsedQEnum,
1415
writer::cpp::namespaced,
16+
CppFragment,
1517
};
1618

1719
use super::{qobject::GeneratedCppQObjectBlocks, utils::Indent};
@@ -22,7 +24,8 @@ fn generate_definition(qenum: &ParsedQEnum) -> String {
2224
let enum_values = qenum
2325
.variants
2426
.iter()
25-
.map(ToString::to_string)
27+
.enumerate()
28+
.map(|(index, variant)| format!("{variant} = {index}"))
2629
.collect::<Vec<_>>()
2730
.join(",\n");
2831

@@ -38,16 +41,14 @@ pub fn generate_declaration(
3841
includes: &mut BTreeSet<String>,
3942
opt: &GeneratedOpt,
4043
) -> Result<String> {
44+
let is_standalone = qenum.qobject.is_none();
4145
// Skip if the cfg attributes are not resolved to true
42-
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.cfgs)? {
46+
if !is_standalone || !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.cfgs)? {
4347
return Ok(String::new());
4448
}
4549

46-
let is_standalone = qenum.qobject.is_none();
47-
if is_standalone {
48-
// required for Q_NAMESPACE and Q_ENUM_NS if we're not on a QObject
49-
includes.insert("#include <QtCore/QObject>".to_owned());
50-
}
50+
// required for Q_NAMESPACE and Q_ENUM_NS if we're not on a QObject
51+
includes.insert("#include <QtCore/QObject>".to_owned());
5152

5253
let enum_definition = generate_definition(qenum).indented(2);
5354
let enum_name = &qenum.name.cxx_unqualified();
@@ -56,19 +57,17 @@ pub fn generate_declaration(
5657
// The declaration must still include Q_NAMESPACE, as otherwise moc will complain.
5758
// This is redundant with `qnamespace!`, which is now only required if you want to specify
5859
// it as QML_ELEMENT.
59-
&if is_standalone {
60-
formatdoc! {r#"
60+
&formatdoc! {r#"
6161
Q_NAMESPACE
6262
{enum_definition}
63-
Q_ENUM_NS({enum_name}) "# }
64-
} else {
65-
enum_definition
63+
Q_ENUM_NS({enum_name}) "#
6664
},
6765
))
6866
}
6967

7068
pub fn generate_on_qobject<'a>(
7169
qenums: impl Iterator<Item = &'a ParsedQEnum>,
70+
qobject: &Name,
7271
opt: &GeneratedOpt,
7372
) -> Result<GeneratedCppQObjectBlocks> {
7473
let mut generated = GeneratedCppQObjectBlocks::default();
@@ -79,26 +78,27 @@ pub fn generate_on_qobject<'a>(
7978
continue;
8079
}
8180

82-
let mut qualified_name = qenum.name.cxx_qualified();
8381
let enum_name = qenum.name.cxx_unqualified();
82+
let mut qobject_name = qobject.cxx_qualified();
8483
// TODO: this is a workaround for cxx_qualified not returning a fully-qualified
8584
// identifier.
8685
// Once https://github.com/KDAB/cxx-qt/issues/619 is fixed, this can be removed.
87-
if !qualified_name.starts_with("::") {
88-
qualified_name.insert_str(0, "::");
86+
if !qobject_name.starts_with("::") {
87+
qobject_name.insert_str(0, "::");
8988
}
9089

9190
generated.includes.insert("#include <cstdint>".to_owned());
9291
let enum_definition = generate_definition(qenum);
9392
generated.metaobjects.push(formatdoc! {r#"
94-
#ifdef Q_MOC_RUN
9593
{enum_definition}
96-
Q_ENUM({enum_name})
97-
#else
98-
using {enum_name} = {qualified_name};
99-
Q_ENUM({enum_name})
100-
#endif
101-
"#, enum_definition = enum_definition.indented(2)});
94+
Q_ENUM({enum_name})"#, enum_definition = enum_definition.indented(2)});
95+
96+
generated
97+
.post_fragments
98+
.push(CppFragment::Header(namespaced(
99+
qenum.name.namespace().unwrap_or_default(),
100+
&format!("using {enum_name} = {qobject_name}::{enum_name};",),
101+
)));
102102
}
103103

104104
Ok(generated)
@@ -132,7 +132,7 @@ mod tests {
132132
let opt = GeneratedOpt {
133133
cfg_evaluator: Box::new(CfgEvaluatorTest::default()),
134134
};
135-
let generated = generate_on_qobject(qenums.iter(), &opt).unwrap();
135+
let generated = generate_on_qobject(qenums.iter(), &Name::mock("MyObject"), &opt).unwrap();
136136

137137
assert!(generated.methods.is_empty());
138138
}
@@ -151,26 +151,31 @@ mod tests {
151151
)
152152
.unwrap()];
153153

154-
let generated = generate_on_qobject(qenums.iter(), &GeneratedOpt::default()).unwrap();
154+
let generated = generate_on_qobject(
155+
qenums.iter(),
156+
&Name::mock("MyObject"),
157+
&GeneratedOpt::default(),
158+
)
159+
.unwrap();
155160
assert_eq!(generated.includes.len(), 1);
156161
assert!(generated.includes.contains("#include <cstdint>"));
157162
assert_eq!(generated.metaobjects.len(), 1);
158163
assert_str_eq!(
159164
indoc! {r#"
160-
#ifdef Q_MOC_RUN
161-
enum class MyEnum : ::std::int32_t {
162-
A,
163-
B,
164-
C
165-
};
166-
Q_ENUM(MyEnum)
167-
#else
168-
using MyEnum = ::MyEnum;
169-
Q_ENUM(MyEnum)
170-
#endif
171-
"#},
165+
enum class MyEnum : ::std::int32_t {
166+
A = 0,
167+
B = 1,
168+
C = 2
169+
};
170+
Q_ENUM(MyEnum)
171+
"#}
172+
.indented(2),
172173
generated.metaobjects[0],
173174
);
175+
assert_eq!(
176+
CppFragment::Header("using MyEnum = ::MyObject::MyEnum;".to_owned()),
177+
generated.post_fragments[0]
178+
);
174179
assert_eq!(generated.forward_declares.len(), 0);
175180
}
176181
}

crates/cxx-qt-gen/src/generator/cpp/qobject.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub struct GeneratedCppQObjectBlocks {
3434
pub forward_declares_namespaced: Vec<String>,
3535
/// List of fragments which are outside of the QObject namespace
3636
pub fragments: Vec<CppFragment>,
37+
/// List of fragments which are outside of the QObject namespace and after the class
38+
pub post_fragments: Vec<CppFragment>,
3739
/// Base class of the QObject
3840
pub base_classes: Vec<String>,
3941
/// List of Qt Meta Object items (eg Q_PROPERTY)
@@ -51,6 +53,7 @@ impl GeneratedCppQObjectBlocks {
5153
self.forward_declares_namespaced
5254
.append(&mut other.forward_declares_namespaced);
5355
self.fragments.append(&mut other.fragments);
56+
self.post_fragments.append(&mut other.post_fragments);
5457
self.base_classes.append(&mut other.base_classes);
5558
self.metaobjects.append(&mut other.metaobjects);
5659
self.methods.append(&mut other.methods);
@@ -160,6 +163,7 @@ impl GeneratedCppQObject {
160163
)?);
161164
generated.blocks.append(&mut qenum::generate_on_qobject(
162165
structured_qobject.qenums.iter().cloned(),
166+
&generated.name,
163167
opt,
164168
)?);
165169

crates/cxx-qt-gen/src/generator/rust/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@ use crate::parser::cxxqtdata::ParsedCxxQtData;
2222
use crate::parser::{parameter::ParsedFunctionParameter, Parser};
2323
use proc_macro2::{Ident, TokenStream};
2424
use quote::quote;
25-
use syn::{parse_quote, Item, ItemMod, Path, Result};
25+
use syn::{parse_quote, ItemMod, Result};
2626

2727
/// Representation of the generated Rust code for a QObject
2828
pub struct GeneratedRustBlocks {
2929
/// Module for the CXX bridge with passthrough items
3030
pub cxx_mod: ItemMod,
31-
/// Any global extra items for the CXX bridge
32-
pub cxx_mod_contents: Vec<Item>,
3331
/// Ident of the namespace of the QObject
3432
pub namespace: String,
3533
/// Rust fragments
@@ -93,9 +91,13 @@ impl GeneratedRustBlocks {
9391
#module
9492
};
9593

94+
let qenums = &parser.cxx_qt_data.qenums;
95+
if !qenums.is_empty() {
96+
fragments.extend(qenum::generate(qenums));
97+
}
98+
9699
Ok(GeneratedRustBlocks {
97100
cxx_mod,
98-
cxx_mod_contents: qenum::generate_cxx_mod_contents(&parser.cxx_qt_data.qenums),
99101
namespace,
100102
fragments,
101103
})
@@ -211,7 +213,6 @@ mod tests {
211213

212214
let rust = GeneratedRustBlocks::from(&parser).unwrap();
213215
assert!(rust.cxx_mod.content.is_none());
214-
assert_eq!(rust.cxx_mod_contents.len(), 0);
215216
assert_eq!(rust.namespace, "");
216217
assert_eq!(rust.fragments.len(), 2);
217218
}
@@ -231,7 +232,6 @@ mod tests {
231232

232233
let rust = GeneratedRustBlocks::from(&parser).unwrap();
233234
assert!(rust.cxx_mod.content.is_none());
234-
assert_eq!(rust.cxx_mod_contents.len(), 0);
235235
assert_eq!(rust.namespace, "cxx_qt");
236236
assert_eq!(rust.fragments.len(), 2);
237237
}
@@ -251,7 +251,6 @@ mod tests {
251251

252252
let rust = GeneratedRustBlocks::from(&parser).unwrap();
253253
assert!(rust.cxx_mod.content.is_none());
254-
assert_eq!(rust.cxx_mod_contents.len(), 0);
255254
assert_eq!(rust.namespace, "");
256255
assert_eq!(rust.fragments.len(), 2);
257256
}

0 commit comments

Comments
 (0)