Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cxx-qt-lib/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ fn main() {
"core/qvariant/qvariant_qlist_i64",
"core/qvariant/qvariant_qlist_i8",
"core/qvariant/qvariant_qlist_qobjectmutptr",
"core/qvariant/qvariant_qlist_qstring",
"core/qvariant/qvariant_qlist_u16",
"core/qvariant/qvariant_qlist_u32",
"core/qvariant/qvariant_qlist_u64",
Expand Down
1 change: 1 addition & 0 deletions crates/cxx-qt-lib/include/core/qvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ CXX_QT_QVARIANT_CAN_CONVERT(QList_u16)
CXX_QT_QVARIANT_CAN_CONVERT(QList_u32)
CXX_QT_QVARIANT_CAN_CONVERT(QList_u64)
CXX_QT_QVARIANT_CAN_CONVERT(QList_QObjectMutPtr)
CXX_QT_QVARIANT_CAN_CONVERT(QList_QString)

#ifdef CXX_QT_GUI_FEATURE
CXX_QT_QVARIANT_CAN_CONVERT(QColor)
Expand Down
34 changes: 20 additions & 14 deletions crates/cxx-qt-lib/src/core/qvariant/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,11 @@ EOF
rustfmt "$SCRIPTPATH/qvariant_$2.rs"
}

# $1: Unqualified rust type name, used as the suffix of the Rust monomorphized type and the C++ header.
# $2: Rust type ($1) in lowercase, used as the suffix of the Rust module name.
# $3: Qualified Rust type name, allowing the CXX bridge to be generated without additional `use` imports.
function generate_bridge_qlist() {
tee "$SCRIPTPATH/qvariant_qlist_$1.rs" <<EOF
tee "$SCRIPTPATH/qvariant_qlist_$2.rs" <<EOF
// SPDX-FileCopyrightText: 2026 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
// SPDX-FileContributor: Yuri Knigavko <yuri.knigavko@qt.io>
//
Expand All @@ -104,7 +107,7 @@ function generate_bridge_qlist() {
pub mod ffi {
unsafe extern "C++" {
include!("cxx-qt-lib/core/qlist/qlist_$1.h");
type QList_$1 = crate::QList<$1>;
type QList_$1 = crate::QList<$3>;

include!("cxx-qt-lib/qvariant.h");
type QVariant = crate::QVariant;
Expand Down Expand Up @@ -133,7 +136,7 @@ pub(crate) fn value_or_default(variant: &ffi::QVariant) -> ffi::QList_$1 {
ffi::value_or_default_QList_$1(variant)
}
EOF
rustfmt "$SCRIPTPATH/qvariant_qlist_$1.rs"
rustfmt "$SCRIPTPATH/qvariant_qlist_$2.rs"
}

generate_bridge_primitive "bool" "Bool"
Expand Down Expand Up @@ -182,14 +185,17 @@ generate_bridge_qt "QVector2D" "qvector2d"
generate_bridge_qt "QVector3D" "qvector3d"
generate_bridge_qt "QVector4D" "qvector4d"

generate_bridge_qlist "bool"
generate_bridge_qlist "f32"
generate_bridge_qlist "f64"
generate_bridge_qlist "i8"
generate_bridge_qlist "i16"
generate_bridge_qlist "i32"
generate_bridge_qlist "i64"
generate_bridge_qlist "u8"
generate_bridge_qlist "u16"
generate_bridge_qlist "u32"
generate_bridge_qlist "u64"
generate_bridge_qlist "bool" "bool" "bool"
generate_bridge_qlist "f32" "f32" "f32"
generate_bridge_qlist "f64" "f64" "f64"
generate_bridge_qlist "i8" "i8" "i8"
generate_bridge_qlist "i16" "i16" "i16"
generate_bridge_qlist "i32" "i32" "i32"
generate_bridge_qlist "i64" "i64" "i64"
generate_bridge_qlist "u8" "u8" "u8"
generate_bridge_qlist "u16" "u16" "u16"
generate_bridge_qlist "u32" "u32" "u32"
generate_bridge_qlist "u64" "u64" "u64"
generate_bridge_qlist "QObjectMutPtr" "qobjectmutptr" "crate::QObjectMutPtr"
# In Qt 5 (unlike Qt 6), QList<QString> and QStringList are distinct types.
generate_bridge_qlist "QString" "qstring" "crate::QString"
3 changes: 3 additions & 0 deletions crates/cxx-qt-lib/src/core/qvariant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ impl_qvariant_value!(crate::QList<u16>, qvariant_qlist_u16);
impl_qvariant_value!(crate::QList<u32>, qvariant_qlist_u32);
impl_qvariant_value!(crate::QList<u64>, qvariant_qlist_u64);
impl_qvariant_value!(crate::QList<QObjectMutPtr>, qvariant_qlist_qobjectmutptr);
// In Qt 5 QStringList is a subclass of QList<QString> but not an alias for it.
// Therefore, these two are distinct types and each needs its own implementation.
impl_qvariant_value!(crate::QList<crate::QString>, qvariant_qlist_qstring);
impl_qvariant_value!(crate::QList<QVariant>, qvariant_qvariantlist);
impl_qvariant_value!(
crate::QMap<crate::QMapPair_QString_QVariant>,
Expand Down
4 changes: 4 additions & 0 deletions crates/cxx-qt-lib/src/core/qvariant/qvariant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QList<::std::uint16_t>, QList_u16)
CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QList<::std::uint32_t>, QList_u32)
CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QList<::std::uint64_t>, QList_u64)
CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QList<::QObjectMutPtr>, QList_QObjectMutPtr)
// In Qt 5 QStringList is a subclass of QList<QString> but not an alias for it.
// Therefore, these two are distinct types and each needs its own
// implementation.
CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QList<::QString>, QList_QString)

#ifdef CXX_QT_GUI_FEATURE
CXX_QT_QVARIANT_CAN_CONVERT_IMPL(::QColor, QColor)
Expand Down
37 changes: 37 additions & 0 deletions crates/cxx-qt-lib/src/core/qvariant/qvariant_qlist_qstring.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions tests/qt_types_standalone/cpp/qvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonValue>
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QVariant>
#include <QtTest/QTest>

Expand Down Expand Up @@ -61,6 +63,20 @@ cppJsonValue()
return QJsonValue(QStringLiteral("C++ string"));
}

QList<QString>
rustStringList()
{
return QList<QString>{ QStringLiteral("Rust string 1"),
QStringLiteral("Rust string 2") };
}

QList<QString>
cppStringList()
{
return QList<QString>{ QStringLiteral("C++ string 1"),
QStringLiteral("C++ string 2") };
}

bool
test_constructed_qvariant(const QVariant& v, VariantTest test)
{
Expand Down Expand Up @@ -101,6 +117,8 @@ test_constructed_qvariant(const QVariant& v, VariantTest test)
return v.value<QJsonObject>() == rustJsonObject();
case VariantTest::QJsonValue:
return v.value<QJsonValue>() == rustJsonValue();
case VariantTest::QListQString:
return v.value<QList<QString>>() == rustStringList();
case VariantTest::QPoint:
return v.value<QPoint>().x() == 1 && v.value<QPoint>().y() == 3;
case VariantTest::QPointF:
Expand Down Expand Up @@ -170,6 +188,7 @@ private Q_SLOTS:
QTest::newRow("QJsonArray") << VariantTest::QJsonArray;
QTest::newRow("QJsonObject") << VariantTest::QJsonObject;
QTest::newRow("QJsonValue") << VariantTest::QJsonValue;
QTest::newRow("QListQString") << VariantTest::QListQString;
QTest::newRow("QPoint") << VariantTest::QPoint;
QTest::newRow("QPointF") << VariantTest::QPointF;
QTest::newRow("QRect") << VariantTest::QRect;
Expand Down Expand Up @@ -228,6 +247,9 @@ private Q_SLOTS:
QTest::newRow("QJsonValue")
<< QVariant::fromValue<QJsonValue>(cppJsonValue())
<< VariantTest::QJsonValue;
QTest::newRow("QListQString")
<< QVariant::fromValue<QList<QString>>(cppStringList())
<< VariantTest::QListQString;
QTest::newRow("QPoint")
<< QVariant::fromValue<QPoint>(QPoint(8, 9)) << VariantTest::QPoint;
QTest::newRow("QPointF") << QVariant::fromValue<QPointF>(QPointF(8.0, 9.0))
Expand Down
17 changes: 15 additions & 2 deletions tests/qt_types_standalone/rust/src/qvariant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use cxx_qt_lib::{
QByteArray, QColor, QDate, QDateTime, QJsonArray, QJsonObject, QJsonValue, QPoint, QPointF,
QRect, QRectF, QSize, QSizeF, QString, QTime, QTimeZone, QUrl, QVariant,
QByteArray, QColor, QDate, QDateTime, QJsonArray, QJsonObject, QJsonValue, QList, QPoint,
QPointF, QRect, QRectF, QSize, QSizeF, QString, QTime, QTimeZone, QUrl, QVariant,
};

#[cxx::bridge]
Expand All @@ -24,6 +24,7 @@ mod qvariant_cxx {
QJsonArray,
QJsonObject,
QJsonValue,
QListQString,
QPoint,
QPointF,
QRect,
Expand Down Expand Up @@ -73,6 +74,10 @@ fn construct_json_value() -> QJsonValue {
QJsonValue::from(&QString::from("Rust string"))
}

fn construct_qlist_qstring() -> QList<QString> {
QList::from(["Rust string 1".into(), "Rust string 2".into()])
}

fn construct_qvariant(test: VariantTest) -> QVariant {
match test {
VariantTest::Bool => QVariant::from(&true),
Expand All @@ -92,6 +97,7 @@ fn construct_qvariant(test: VariantTest) -> QVariant {
VariantTest::QJsonArray => QVariant::from(&construct_json_array()),
VariantTest::QJsonObject => QVariant::from(&construct_json_object()),
VariantTest::QJsonValue => QVariant::from(&construct_json_value()),
VariantTest::QListQString => QVariant::from(&construct_qlist_qstring()),
VariantTest::QPoint => QVariant::from(&QPoint::new(1, 3)),
VariantTest::QPointF => QVariant::from(&QPointF::new(1.0, 3.0)),
VariantTest::QRect => QVariant::from(&QRect::new(123, 456, 246, 912)),
Expand Down Expand Up @@ -183,6 +189,13 @@ fn read_qvariant(v: &cxx_qt_lib::QVariant, test: VariantTest) -> bool {
Some(value) => value.is_string() && value.to_string() == QString::from("C++ string"),
None => false,
},
VariantTest::QListQString => match v.value::<QList<QString>>() {
Some(list) => {
list.iter().cloned().collect::<Vec<QString>>()
== vec![QString::from("C++ string 1"), QString::from("C++ string 2")]
}
None => false,
},
VariantTest::QPoint => match v.value::<QPoint>() {
Some(point) => point.x() == 8 && point.y() == 9,
None => false,
Expand Down
Loading