Allow optional primitive object properties

master
Jos van den Oever 2018-05-15 21:45:05 +02:00
parent a051556990
commit 392153f9a9
21 changed files with 461 additions and 74 deletions

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;
@ -388,8 +388,8 @@ pub trait FibonacciListTrait {
fn new(emit: FibonacciListEmitter, model: FibonacciListList) -> Self;
fn emit(&self) -> &FibonacciListEmitter;
fn row_count(&self) -> usize;
fn insert_rows(&mut self, row: usize, count: usize) -> bool { false }
fn remove_rows(&mut self, row: usize, count: usize) -> bool { false }
fn insert_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn remove_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn can_fetch_more(&self) -> bool {
false
}
@ -619,6 +619,7 @@ pub extern "C" fn file_system_tree_path_set(ptr: *mut FileSystemTree, v: *const
set_string_from_utf16(&mut s, v, len);
o.set_path(Some(s));
}
#[no_mangle]
pub extern "C" fn file_system_tree_path_set_none(ptr: *mut FileSystemTree) {
let o = unsafe { &mut *ptr };
@ -1074,8 +1075,8 @@ pub trait TimeSeriesTrait {
fn new(emit: TimeSeriesEmitter, model: TimeSeriesList) -> Self;
fn emit(&self) -> &TimeSeriesEmitter;
fn row_count(&self) -> usize;
fn insert_rows(&mut self, row: usize, count: usize) -> bool { false }
fn remove_rows(&mut self, row: usize, count: usize) -> bool { false }
fn insert_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn remove_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn can_fetch_more(&self) -> bool {
false
}

View File

@ -516,8 +516,12 @@ private:
)";
for (auto p: o.properties) {
bool obj = p.type.type == BindingType::Object;
auto t = p.type.name;
if (p.optional && !p.type.isComplex()) {
t = "QVariant";
}
h << QString(" Q_PROPERTY(%1 %2 READ %2 %3NOTIFY %2Changed FINAL)")
.arg(p.type.name + (obj ?"*" :""),
.arg(t + (obj ?"*" :""),
p.name,
p.write ? writeProperty(p.name) :"")
<< endl;
@ -532,9 +536,15 @@ public:
h << " const " << p.type.name << "* " << p.name << "() const;" << endl;
h << " " << p.type.name << "* " << p.name << "();" << endl;
} else {
h << " " << p.type.name << " " << p.name << "() const;" << endl;
auto t = p.type.name;
auto t2 = p.type.cppSetType;
if (p.optional && !p.type.isComplex()) {
t = "QVariant";
t2 = "const QVariant&";
}
h << " " << t << " " << p.name << "() const;" << endl;
if (p.write) {
h << " void set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v);" << endl;
h << " void set" << upperInitial(p.name) << "(" << t2 << " v);" << endl;
}
}
}
@ -730,6 +740,9 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& co
} else if (p.type.isComplex()) {
cpp << QString(" void %2_get(const %1::Private*, %3);")
.arg(o.name, base, cGetType(p.type)) << endl;
} else if (p.optional) {
cpp << QString(" option_%3 %2_get(const %1::Private*);")
.arg(o.name, base, p.type.name) << endl;
} else {
cpp << QString(" %3 %2_get(const %1::Private*);")
.arg(o.name, base, p.type.name) << endl;
@ -868,20 +881,39 @@ void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf
cpp << " " << base << "_get(m_d, &v, set_" << p.type.name.toLower()
<< ");\n";
cpp << " return v;\n}\n";
} else if (p.optional) {
cpp << QString("QVariant %1::%2() const\n{\n").arg(o.name, p.name);
cpp << " QVariant v;\n";
cpp << QString(" auto r = %1_get(m_d);\n").arg(base);
cpp << " if (r.some) {\n";
cpp << " v.setValue(r.value);\n";
cpp << " }\n";
cpp << " return r;\n";
cpp << "}\n";
} else {
cpp << QString("%3 %1::%2() const\n{\n").arg(o.name, p.name, p.type.name);
cpp << QString(" return %1_get(m_d);\n}\n").arg(base);
}
if (p.write) {
cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v) {" << endl;
auto t = p.type.cppSetType;
if (p.optional && !p.type.isComplex()) {
t = "const QVariant&";
}
cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << t << " v) {" << endl;
if (p.optional) {
cpp << QString(" if (v.isNull()) {") << endl;
if (p.type.isComplex()) {
cpp << " if (v.isNull()) {" << endl;
} else {
cpp << QString(" if (v.isNull() || !v.canConvert<%1>()) {").arg(p.type.name) << endl;
}
cpp << QString(" %1_set_none(m_d);").arg(base) << endl;
cpp << QString(" } else {") << endl;
if (p.type.name == "QString") {
cpp << QString(" %1_set(m_d, reinterpret_cast<const ushort*>(v.data()), v.size());").arg(base) << endl;
} else if (p.type.name == "QByteArray") {
cpp << QString(" %1_set(m_d, v.data(), v.size());").arg(base) << endl;
} else if (p.optional) {
cpp << QString(" %1_set(m_d, v.value<%2>());").arg(base, p.type.name) << endl;
} else {
cpp << QString(" %1_set(m_d, v);").arg(base) << endl;
}

View File

@ -353,8 +353,8 @@ pub trait %1Trait {
}
if (o.type == ObjectType::List) {
r << R"( fn row_count(&self) -> usize;
fn insert_rows(&mut self, row: usize, count: usize) -> bool { false }
fn remove_rows(&mut self, row: usize, count: usize) -> bool { false }
fn insert_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn remove_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn can_fetch_more(&self) -> bool {
false
}
@ -470,11 +470,6 @@ pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_ushort, len: c_int) {
set_string_from_utf16(&mut s, v, len);
o.set_%3(Some(s));
}
#[no_mangle]
pub extern "C" fn %2_set_none(ptr: *mut %1) {
let o = unsafe { &mut *ptr };
o.set_%3(None);
}
)").arg(o.name, base, snakeCase(p.name));
} else if (p.write) {
r << QString(R"(
@ -484,13 +479,26 @@ pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_char, len: c_int) {
let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) };
o.set_%3(Some(v.into()));
}
#[no_mangle]
pub extern "C" fn %2_set_none(ptr: *mut %1) {
let o = unsafe { &mut *ptr };
o.set_%3(None);
}
)").arg(o.name, base, snakeCase(p.name));
}
} else if (p.optional) {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_get(ptr: *const %1) -> COption<%4> {
match (&*ptr).%3() {
Some(value) => COption { data: value, some: true },
None => COption { data: %4::default(), some: false}
}
}
)").arg(o.name, base, snakeCase(p.name), p.type.rustType);
if (p.write) {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_set(ptr: *mut %1, v: %4) {
(&mut *ptr).set_%3(Some(v));
}
)").arg(o.name, base, snakeCase(p.name), p.type.rustType);
}
} else {
r << QString(R"(
#[no_mangle]
@ -507,6 +515,15 @@ pub unsafe extern "C" fn %2_set(ptr: *mut %1, v: %4) {
)").arg(o.name, base, snakeCase(p.name), rustType(p));
}
}
if (p.write && p.optional) {
r << QString(R"(
#[no_mangle]
pub extern "C" fn %2_set_none(ptr: *mut %1) {
let o = unsafe { &mut *ptr };
o.set_%3(None);
}
)").arg(o.name, base, snakeCase(p.name));
}
}
for (const Function& f: o.functions) {
writeFunction(r, f, lcname, o);
@ -828,7 +845,7 @@ void writeRustInterface(const Configuration& conf) {
r << QString(R"(/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;

View File

@ -155,6 +155,11 @@ struct Configuration {
QList<QString> optionalTypes() const {
QList<QString> ops;
for (auto o: objects) {
for (auto ip: o.properties) {
if (ip.optional && !ops.contains(ip.type.name)) {
ops.append(ip.type.name);
}
}
for (auto ip: o.itemProperties) {
if (ip.optional && !ops.contains(ip.type.name)) {
ops.append(ip.type.name);

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;
@ -123,8 +123,8 @@ pub trait PersonsTrait {
fn new(emit: PersonsEmitter, model: PersonsList) -> Self;
fn emit(&self) -> &PersonsEmitter;
fn row_count(&self) -> usize;
fn insert_rows(&mut self, row: usize, count: usize) -> bool { false }
fn remove_rows(&mut self, row: usize, count: usize) -> bool { false }
fn insert_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn remove_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn can_fetch_more(&self) -> bool {
false
}

View File

@ -6,6 +6,7 @@ use interface::*;
#[derive(Default, Clone)]
struct ListItem {
boolean: bool,
optional_boolean: Option<bool>,
i8: i8,
u8: u8,
i16: i16,
@ -49,6 +50,13 @@ impl ListTrait for List {
self.list[item].boolean = v;
true
}
fn optional_boolean(&self, item: usize) -> Option<bool> {
self.list[item].optional_boolean
}
fn set_optional_boolean(&mut self, item: usize, v: Option<bool>) -> bool {
self.list[item].optional_boolean = v;
true
}
fn i8(&self, item: usize) -> i8 {
self.list[item].i8
}

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;
@ -126,8 +126,8 @@ pub trait ListTrait {
fn new(emit: ListEmitter, model: ListList) -> Self;
fn emit(&self) -> &ListEmitter;
fn row_count(&self) -> usize;
fn insert_rows(&mut self, row: usize, count: usize) -> bool { false }
fn remove_rows(&mut self, row: usize, count: usize) -> bool { false }
fn insert_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn remove_rows(&mut self, _row: usize, _count: usize) -> bool { false }
fn can_fetch_more(&self) -> bool {
false
}
@ -149,6 +149,8 @@ pub trait ListTrait {
fn set_i64(&mut self, item: usize, i64) -> bool;
fn i8(&self, item: usize) -> i8;
fn set_i8(&mut self, item: usize, i8) -> bool;
fn optional_boolean(&self, item: usize) -> Option<bool>;
fn set_optional_boolean(&mut self, item: usize, Option<bool>) -> bool;
fn optional_bytearray(&self, item: usize) -> Option<&[u8]>;
fn set_optional_bytearray(&mut self, item: usize, Option<Vec<u8>>) -> bool;
fn optional_string(&self, item: usize) -> Option<&str>;
@ -351,6 +353,25 @@ pub unsafe extern "C" fn list_set_data_i8(
(&mut *ptr).set_i8(row as usize, v)
}
#[no_mangle]
pub extern "C" fn list_data_optional_boolean(ptr: *const List, row: c_int) -> COption<bool> {
let o = unsafe { &*ptr };
o.optional_boolean(row as usize).into()
}
#[no_mangle]
pub unsafe extern "C" fn list_set_data_optional_boolean(
ptr: *mut List, row: c_int,
v: bool,
) -> bool {
(&mut *ptr).set_optional_boolean(row as usize, Some(v))
}
#[no_mangle]
pub unsafe extern "C" fn list_set_data_optional_boolean_none(ptr: *mut List, row: c_int) -> bool {
(&mut *ptr).set_optional_boolean(row as usize, None)
}
#[no_mangle]
pub extern "C" fn list_data_optional_bytearray(
ptr: *const List, row: c_int,

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;

View File

@ -6,6 +6,7 @@ use interface::*;
pub struct Object {
emit: ObjectEmitter,
boolean: bool,
optional_boolean: Option<bool>,
i8: i8,
u8: u8,
i16: i16,
@ -14,6 +15,7 @@ pub struct Object {
u32: u32,
i64: i64,
u64: u64,
optional_u64: Option<u64>,
f32: f32,
f64: f64,
bytearray: Vec<u8>,
@ -27,6 +29,7 @@ impl ObjectTrait for Object {
Object {
emit,
boolean: false,
optional_boolean: None,
i8: 0,
u8: 0,
i16: 0,
@ -35,6 +38,7 @@ impl ObjectTrait for Object {
u32: 0,
i64: 0,
u64: 0,
optional_u64: None,
f32: 0.,
f64: 0.,
bytearray: Vec::new(),
@ -53,6 +57,13 @@ impl ObjectTrait for Object {
self.boolean = value;
self.emit.boolean_changed();
}
fn optional_boolean(&self) -> Option<bool> {
self.optional_boolean
}
fn set_optional_boolean(&mut self, b: Option<bool>) {
self.optional_boolean = b;
self.emit.optional_boolean_changed();
}
fn i8(&self) -> i8 {
self.i8
}
@ -109,6 +120,13 @@ impl ObjectTrait for Object {
self.u64 = value;
self.emit.u64_changed();
}
fn optional_u64(&self) -> Option<u64> {
self.optional_u64
}
fn set_optional_u64(&mut self, v: Option<u64>) {
self.optional_u64 = v;
self.emit.optional_u64_changed();
}
fn f32(&self) -> f32 {
self.f32
}
@ -123,14 +141,6 @@ impl ObjectTrait for Object {
self.f64 = value;
self.emit.f64_changed();
}
/*
fn optional_boolean(&self) -> Option<bool> {
self.optional_boolean
}
fn set_optional_boolean(&mut self, b: Option<bool>) {
self.optional_boolean = b;
}
*/
fn bytearray(&self) -> &[u8] {
&self.bytearray
}

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;
@ -65,8 +65,10 @@ pub struct ObjectEmitter {
i32_changed: fn(*const ObjectQObject),
i64_changed: fn(*const ObjectQObject),
i8_changed: fn(*const ObjectQObject),
optional_boolean_changed: fn(*const ObjectQObject),
optional_bytearray_changed: fn(*const ObjectQObject),
optional_string_changed: fn(*const ObjectQObject),
optional_u64_changed: fn(*const ObjectQObject),
string_changed: fn(*const ObjectQObject),
u16_changed: fn(*const ObjectQObject),
u32_changed: fn(*const ObjectQObject),
@ -128,6 +130,12 @@ impl ObjectEmitter {
(self.i8_changed)(ptr);
}
}
pub fn optional_boolean_changed(&self) {
let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() {
(self.optional_boolean_changed)(ptr);
}
}
pub fn optional_bytearray_changed(&self) {
let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() {
@ -140,6 +148,12 @@ impl ObjectEmitter {
(self.optional_string_changed)(ptr);
}
}
pub fn optional_u64_changed(&self) {
let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() {
(self.optional_u64_changed)(ptr);
}
}
pub fn string_changed(&self) {
let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() {
@ -191,10 +205,14 @@ pub trait ObjectTrait {
fn set_i64(&mut self, value: i64);
fn i8(&self) -> i8;
fn set_i8(&mut self, value: i8);
fn optional_boolean(&self) -> Option<bool>;
fn set_optional_boolean(&mut self, value: Option<bool>);
fn optional_bytearray(&self) -> Option<&[u8]>;
fn set_optional_bytearray(&mut self, value: Option<Vec<u8>>);
fn optional_string(&self) -> Option<&str>;
fn set_optional_string(&mut self, value: Option<String>);
fn optional_u64(&self) -> Option<u64>;
fn set_optional_u64(&mut self, value: Option<u64>);
fn string(&self) -> &str;
fn set_string(&mut self, value: String);
fn u16(&self) -> u16;
@ -218,8 +236,10 @@ pub extern "C" fn object_new(
i32_changed: fn(*const ObjectQObject),
i64_changed: fn(*const ObjectQObject),
i8_changed: fn(*const ObjectQObject),
optional_boolean_changed: fn(*const ObjectQObject),
optional_bytearray_changed: fn(*const ObjectQObject),
optional_string_changed: fn(*const ObjectQObject),
optional_u64_changed: fn(*const ObjectQObject),
string_changed: fn(*const ObjectQObject),
u16_changed: fn(*const ObjectQObject),
u32_changed: fn(*const ObjectQObject),
@ -236,8 +256,10 @@ pub extern "C" fn object_new(
i32_changed: i32_changed,
i64_changed: i64_changed,
i8_changed: i8_changed,
optional_boolean_changed: optional_boolean_changed,
optional_bytearray_changed: optional_bytearray_changed,
optional_string_changed: optional_string_changed,
optional_u64_changed: optional_u64_changed,
string_changed: string_changed,
u16_changed: u16_changed,
u32_changed: u32_changed,
@ -342,6 +364,25 @@ pub unsafe extern "C" fn object_i8_set(ptr: *mut Object, v: i8) {
(&mut *ptr).set_i8(v);
}
#[no_mangle]
pub unsafe extern "C" fn object_optional_boolean_get(ptr: *const Object) -> COption<bool> {
match (&*ptr).optional_boolean() {
Some(value) => COption { data: value, some: true },
None => COption { data: bool::default(), some: false}
}
}
#[no_mangle]
pub unsafe extern "C" fn object_optional_boolean_set(ptr: *mut Object, v: bool) {
(&mut *ptr).set_optional_boolean(Some(v));
}
#[no_mangle]
pub extern "C" fn object_optional_boolean_set_none(ptr: *mut Object) {
let o = unsafe { &mut *ptr };
o.set_optional_boolean(None);
}
#[no_mangle]
pub extern "C" fn object_optional_bytearray_get(
ptr: *const Object,
@ -362,6 +403,7 @@ pub extern "C" fn object_optional_bytearray_set(ptr: *mut Object, v: *const c_ch
let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) };
o.set_optional_bytearray(Some(v.into()));
}
#[no_mangle]
pub extern "C" fn object_optional_bytearray_set_none(ptr: *mut Object) {
let o = unsafe { &mut *ptr };
@ -389,12 +431,32 @@ pub extern "C" fn object_optional_string_set(ptr: *mut Object, v: *const c_ushor
set_string_from_utf16(&mut s, v, len);
o.set_optional_string(Some(s));
}
#[no_mangle]
pub extern "C" fn object_optional_string_set_none(ptr: *mut Object) {
let o = unsafe { &mut *ptr };
o.set_optional_string(None);
}
#[no_mangle]
pub unsafe extern "C" fn object_optional_u64_get(ptr: *const Object) -> COption<u64> {
match (&*ptr).optional_u64() {
Some(value) => COption { data: value, some: true },
None => COption { data: u64::default(), some: false}
}
}
#[no_mangle]
pub unsafe extern "C" fn object_optional_u64_set(ptr: *mut Object, v: u64) {
(&mut *ptr).set_optional_u64(Some(v));
}
#[no_mangle]
pub extern "C" fn object_optional_u64_set_none(ptr: *mut Object) {
let o = unsafe { &mut *ptr };
o.set_optional_u64(None);
}
#[no_mangle]
pub extern "C" fn object_string_get(
ptr: *const Object,

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;

View File

@ -1,7 +1,7 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t};
use libc::{c_char, c_ushort, c_int, c_void};
use std::slice;
use std::char::decode_utf16;

View File

@ -30,6 +30,7 @@ private slots:
void testStringGetter();
void testStringSetter();
void testBool();
void testOptionalBool();
void testInt8();
void testUint8();
void testInt16();
@ -53,6 +54,26 @@ void testSetter(const V v, Set set, Get get)
List list;
QSignalSpy spy(&list, &List::dataChanged);
// WHEN
const QVariant vv = QVariant::fromValue(v);
QVERIFY(!vv.isNull());
bool ok = (list.*set)(0, vv);
QVERIFY(ok);
// THEN
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QCOMPARE((list.*get)(0), vv);
}
template <typename V, typename Set, typename Get>
void testOptionalSetter(const V v, Set set, Get get)
{
// GIVEN
List list;
QSignalSpy spy(&list, &List::dataChanged);
QVERIFY((list.*get)(0).isNull());
// WHEN
QVariant vv = QVariant::fromValue(v);
if (vv.isNull()) {
@ -90,6 +111,28 @@ void testDataSetter(const char* roleName, const V v)
// WHEN
int role = getRoleFromName(list, roleName);
auto index = list.index(1, 0);
const QVariant vv = QVariant::fromValue(v);
QVERIFY(!vv.isNull());
bool ok = list.setData(index, vv, role);
QVERIFY(ok);
// THEN
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QCOMPARE(list.data(index, role), vv);
}
template <typename V>
void testOptionalDataSetter(const char* roleName, const V v)
{
// GIVEN
List list;
QSignalSpy spy(&list, &List::dataChanged);
int role = getRoleFromName(list, roleName);
auto index = list.index(1, 0);
QVERIFY(list.data(index, role).isNull());
// WHEN
QVariant vv = QVariant::fromValue(v);
if (vv.isNull()) {
vv = QVariant();
@ -107,7 +150,14 @@ template <typename V, typename Set, typename Get>
void test(const V v, Set set, Get get, const char* roleName)
{
testSetter(v, set, get);
//testDataSetter(roleName, v);
testDataSetter(roleName, v);
}
template <typename V, typename Set, typename Get>
void testOptional(const V v, Set set, Get get, const char* roleName)
{
testOptionalSetter(v, set, get);
testOptionalDataSetter(roleName, v);
}
void TestRustListTypes::testConstructor()
@ -121,6 +171,14 @@ void TestRustListTypes::testBool()
test(false, &List::setBoolean, &List::boolean, "boolean");
}
void TestRustListTypes::testOptionalBool()
{
testOptional(true, &List::setOptionalBoolean, &List::optionalBoolean,
"optionalBoolean");
testOptional(false, &List::setOptionalBoolean, &List::optionalBoolean,
"optionalBoolean");
}
void TestRustListTypes::testInt8()
{
test(0, &List::setI8, &List::i8, "i8");
@ -210,14 +268,14 @@ void TestRustListTypes::testString()
void TestRustListTypes::testOptionalString()
{
test(QString(), &List::setOptionalString, &List::optionalString,
testOptional(QString(), &List::setOptionalString, &List::optionalString,
"optionalString");
test(QString(""), &List::setOptionalString, &List::optionalString,
"optionalString");
test(QString("Konqi"), &List::setOptionalString, &List::optionalString,
"optionalString");
test(QString("$𐐷𤭢"), &List::setOptionalString, &List::optionalString,
testOptional(QString(""), &List::setOptionalString, &List::optionalString,
"optionalString");
testOptional(QString("Konqi"), &List::setOptionalString,
&List::optionalString, "optionalString");
testOptional(QString("$𐐷𤭢"), &List::setOptionalString,
&List::optionalString, "optionalString");
}
void TestRustListTypes::testByteArray()
@ -231,16 +289,15 @@ void TestRustListTypes::testByteArray()
void TestRustListTypes::testOptionalByteArray()
{
test(QByteArray(), &List::setOptionalBytearray, &List::optionalBytearray,
"optionalBytearray");
testOptional(QByteArray(), &List::setOptionalBytearray,
&List::optionalBytearray, "optionalBytearray");
const char data[10] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9};
test(QByteArray(data, 0), &List::setOptionalBytearray,
testOptional(QByteArray(data, 0), &List::setOptionalBytearray,
&List::optionalBytearray, "optionalBytearray");
test(QByteArray(data, 10), &List::setOptionalBytearray,
testOptional(QByteArray(data, 10), &List::setOptionalBytearray,
&List::optionalBytearray, "optionalBytearray");
}
void TestRustListTypes::testStringGetter()
{
List list;

View File

@ -13,6 +13,11 @@
"type": "bool",
"write": true
},
"optionalBoolean": {
"optional": true,
"type": "bool",
"write": true
},
"i8": {
"type": "qint8",
"write": true

View File

@ -3,6 +3,19 @@
namespace {
struct option_bool {
public:
bool value;
bool some;
operator QVariant() const {
if (some) {
return QVariant::fromValue(value);
}
return QVariant();
}
};
static_assert(std::is_pod<option_bool>::value, "option_bool must be a POD type.");
struct option_quintptr {
public:
quintptr value;
@ -53,6 +66,9 @@ extern "C" {
bool list_set_data_i64(List::Private*, int, qint64);
qint8 list_data_i8(const List::Private*, int);
bool list_set_data_i8(List::Private*, int, qint8);
option_bool list_data_optional_boolean(const List::Private*, int);
bool list_set_data_optional_boolean(List::Private*, int, bool);
bool list_set_data_optional_boolean_none(List::Private*, int);
void list_data_optional_bytearray(const List::Private*, int, QByteArray*, qbytearray_set);
bool list_set_data_optional_bytearray(List::Private*, int, const char* s, int len);
bool list_set_data_optional_bytearray_none(List::Private*, int);
@ -311,6 +327,31 @@ bool List::setI8(int row, const QVariant& value)
return set;
}
QVariant List::optionalBoolean(int row) const
{
QVariant v;
v = list_data_optional_boolean(m_d, row);
return v;
}
bool List::setOptionalBoolean(int row, const QVariant& value)
{
bool set = false;
if (!value.isValid()) {
set = list_set_data_optional_boolean_none(m_d, row);
} else {
if (!value.canConvert(qMetaTypeId<bool>())) {
return false;
}
set = list_set_data_optional_boolean(m_d, row, value.value<bool>());
}
if (set) {
QModelIndex index = createIndex(row, 0, row);
emit dataChanged(index, index);
}
return set;
}
QVariant List::optionalBytearray(int row) const
{
QVariant v;
@ -498,20 +539,22 @@ QVariant List::data(const QModelIndex &index, int role) const
case Qt::UserRole + 7:
return i8(index.row());
case Qt::UserRole + 8:
return optionalBytearray(index.row());
return optionalBoolean(index.row());
case Qt::UserRole + 9:
return optionalBytearray(index.row());
case Qt::UserRole + 10:
return optionalString(index.row());
case Qt::DisplayRole:
case Qt::EditRole:
case Qt::UserRole + 10:
return string(index.row());
case Qt::UserRole + 11:
return u16(index.row());
return string(index.row());
case Qt::UserRole + 12:
return u32(index.row());
return u16(index.row());
case Qt::UserRole + 13:
return u64(index.row());
return u32(index.row());
case Qt::UserRole + 14:
return u64(index.row());
case Qt::UserRole + 15:
return u8(index.row());
}
}
@ -528,13 +571,14 @@ QHash<int, QByteArray> List::roleNames() const {
names.insert(Qt::UserRole + 5, "i32");
names.insert(Qt::UserRole + 6, "i64");
names.insert(Qt::UserRole + 7, "i8");
names.insert(Qt::UserRole + 8, "optionalBytearray");
names.insert(Qt::UserRole + 9, "optionalString");
names.insert(Qt::UserRole + 10, "string");
names.insert(Qt::UserRole + 11, "u16");
names.insert(Qt::UserRole + 12, "u32");
names.insert(Qt::UserRole + 13, "u64");
names.insert(Qt::UserRole + 14, "u8");
names.insert(Qt::UserRole + 8, "optionalBoolean");
names.insert(Qt::UserRole + 9, "optionalBytearray");
names.insert(Qt::UserRole + 10, "optionalString");
names.insert(Qt::UserRole + 11, "string");
names.insert(Qt::UserRole + 12, "u16");
names.insert(Qt::UserRole + 13, "u32");
names.insert(Qt::UserRole + 14, "u64");
names.insert(Qt::UserRole + 15, "u8");
return names;
}
QVariant List::headerData(int section, Qt::Orientation orientation, int role) const
@ -582,24 +626,27 @@ bool List::setData(const QModelIndex &index, const QVariant &value, int role)
return setI8(index.row(), value);
}
if (role == Qt::UserRole + 8) {
return setOptionalBytearray(index.row(), value);
return setOptionalBoolean(index.row(), value);
}
if (role == Qt::UserRole + 9) {
return setOptionalBytearray(index.row(), value);
}
if (role == Qt::UserRole + 10) {
return setOptionalString(index.row(), value);
}
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 10) {
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 11) {
return setString(index.row(), value);
}
if (role == Qt::UserRole + 11) {
if (role == Qt::UserRole + 12) {
return setU16(index.row(), value);
}
if (role == Qt::UserRole + 12) {
if (role == Qt::UserRole + 13) {
return setU32(index.row(), value);
}
if (role == Qt::UserRole + 13) {
if (role == Qt::UserRole + 14) {
return setU64(index.row(), value);
}
if (role == Qt::UserRole + 14) {
if (role == Qt::UserRole + 15) {
return setU8(index.row(), value);
}
}

View File

@ -52,6 +52,8 @@ public:
Q_INVOKABLE bool setI64(int row, const QVariant& value);
Q_INVOKABLE QVariant i8(int row) const;
Q_INVOKABLE bool setI8(int row, const QVariant& value);
Q_INVOKABLE QVariant optionalBoolean(int row) const;
Q_INVOKABLE bool setOptionalBoolean(int row, const QVariant& value);
Q_INVOKABLE QVariant optionalBytearray(int row) const;
Q_INVOKABLE bool setOptionalBytearray(int row, const QVariant& value);
Q_INVOKABLE QVariant optionalString(int row) const;

View File

@ -8,6 +8,7 @@ class TestRustObjectTypes : public QObject
Q_OBJECT
private slots:
void testBool();
void testOptionalBool();
void testInt8();
void testUint8();
void testInt16();
@ -16,6 +17,7 @@ private slots:
void testUint32();
void testInt64();
void testUint64();
void testOptionalUint64();
void testFloat();
void testDouble();
void testString();
@ -48,6 +50,16 @@ void TestRustObjectTypes::testBool()
&Object::boolean, &Object::booleanChanged);
}
void TestRustObjectTypes::testOptionalBool()
{
testSetter(QVariant(), &Object::setOptionalBoolean,
&Object::optionalBoolean, &Object::optionalBooleanChanged);
testSetter(QVariant::fromValue(true), &Object::setOptionalBoolean,
&Object::optionalBoolean, &Object::optionalBooleanChanged);
testSetter(QVariant::fromValue(false), &Object::setOptionalBoolean,
&Object::optionalBoolean, &Object::optionalBooleanChanged);
}
void TestRustObjectTypes::testInt8()
{
testSetter(0, &Object::setI8,
@ -144,6 +156,22 @@ void TestRustObjectTypes::testUint64()
&Object::u64, &Object::u64Changed);
}
void TestRustObjectTypes::testOptionalUint64()
{
testSetter(QVariant(), &Object::setOptionalU64,
&Object::optionalU64, &Object::optionalU64Changed);
testSetter(QVariant::fromValue(0), &Object::setOptionalU64,
&Object::optionalU64, &Object::optionalU64Changed);
testSetter(QVariant::fromValue(1), &Object::setOptionalU64,
&Object::optionalU64, &Object::optionalU64Changed);
testSetter(QVariant::fromValue(std::numeric_limits<uint64_t>::min()),
&Object::setOptionalU64, &Object::optionalU64,
&Object::optionalU64Changed);
testSetter(QVariant::fromValue(std::numeric_limits<uint64_t>::max()),
&Object::setOptionalU64, &Object::optionalU64,
&Object::optionalU64Changed);
}
void TestRustObjectTypes::testFloat()
{
testSetter(0, &Object::setF32,

View File

@ -13,6 +13,11 @@
"type": "bool",
"write": true
},
"optionalBoolean": {
"optional": true,
"type": "bool",
"write": true
},
"i8": {
"type": "qint8",
"write": true
@ -45,6 +50,11 @@
"type": "quint64",
"write": true
},
"optionalU64": {
"optional": true,
"type": "quint64",
"write": true
},
"f32": {
"type": "float",
"write": true

View File

@ -3,6 +3,32 @@
namespace {
struct option_bool {
public:
bool value;
bool some;
operator QVariant() const {
if (some) {
return QVariant::fromValue(value);
}
return QVariant();
}
};
static_assert(std::is_pod<option_bool>::value, "option_bool must be a POD type.");
struct option_quint64 {
public:
quint64 value;
bool some;
operator QVariant() const {
if (some) {
return QVariant::fromValue(value);
}
return QVariant();
}
};
static_assert(std::is_pod<option_quint64>::value, "option_quint64 must be a POD type.");
typedef void (*qstring_set)(QString* val, const char* utf8, int nbytes);
void set_qstring(QString* val, const char* utf8, int nbytes) {
*val = QString::fromUtf8(utf8, nbytes);
@ -49,6 +75,10 @@ namespace {
{
emit o->i8Changed();
}
inline void objectOptionalBooleanChanged(Object* o)
{
emit o->optionalBooleanChanged();
}
inline void objectOptionalBytearrayChanged(Object* o)
{
emit o->optionalBytearrayChanged();
@ -57,6 +87,10 @@ namespace {
{
emit o->optionalStringChanged();
}
inline void objectOptionalU64Changed(Object* o)
{
emit o->optionalU64Changed();
}
inline void objectStringChanged(Object* o)
{
emit o->stringChanged();
@ -79,7 +113,7 @@ namespace {
}
}
extern "C" {
Object::Private* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*));
Object::Private* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*));
void object_free(Object::Private*);
bool object_boolean_get(const Object::Private*);
void object_boolean_set(Object::Private*, bool);
@ -97,12 +131,18 @@ extern "C" {
void object_i64_set(Object::Private*, qint64);
qint8 object_i8_get(const Object::Private*);
void object_i8_set(Object::Private*, qint8);
option_bool object_optional_boolean_get(const Object::Private*);
void object_optional_boolean_set(Object::Private*, bool);
void object_optional_boolean_set_none(Object::Private*);
void object_optional_bytearray_get(const Object::Private*, QByteArray*, qbytearray_set);
void object_optional_bytearray_set(Object::Private*, const char* bytes, int len);
void object_optional_bytearray_set_none(Object::Private*);
void object_optional_string_get(const Object::Private*, QString*, qstring_set);
void object_optional_string_set(Object::Private*, const ushort *str, int len);
void object_optional_string_set_none(Object::Private*);
option_quint64 object_optional_u64_get(const Object::Private*);
void object_optional_u64_set(Object::Private*, quint64);
void object_optional_u64_set_none(Object::Private*);
void object_string_get(const Object::Private*, QString*, qstring_set);
void object_string_set(Object::Private*, const ushort *str, int len);
quint16 object_u16_get(const Object::Private*);
@ -133,8 +173,10 @@ Object::Object(QObject *parent):
objectI32Changed,
objectI64Changed,
objectI8Changed,
objectOptionalBooleanChanged,
objectOptionalBytearrayChanged,
objectOptionalStringChanged,
objectOptionalU64Changed,
objectStringChanged,
objectU16Changed,
objectU32Changed,
@ -207,6 +249,22 @@ qint8 Object::i8() const
void Object::setI8(qint8 v) {
object_i8_set(m_d, v);
}
QVariant Object::optionalBoolean() const
{
QVariant v;
auto r = object_optional_boolean_get(m_d);
if (r.some) {
v.setValue(r.value);
}
return r;
}
void Object::setOptionalBoolean(const QVariant& v) {
if (v.isNull() || !v.canConvert<bool>()) {
object_optional_boolean_set_none(m_d);
} else {
object_optional_boolean_set(m_d, v.value<bool>());
}
}
QByteArray Object::optionalBytearray() const
{
QByteArray v;
@ -233,6 +291,22 @@ void Object::setOptionalString(const QString& v) {
object_optional_string_set(m_d, reinterpret_cast<const ushort*>(v.data()), v.size());
}
}
QVariant Object::optionalU64() const
{
QVariant v;
auto r = object_optional_u64_get(m_d);
if (r.some) {
v.setValue(r.value);
}
return r;
}
void Object::setOptionalU64(const QVariant& v) {
if (v.isNull() || !v.canConvert<quint64>()) {
object_optional_u64_set_none(m_d);
} else {
object_optional_u64_set(m_d, v.value<quint64>());
}
}
QString Object::string() const
{
QString v;

View File

@ -23,8 +23,10 @@ private:
Q_PROPERTY(qint32 i32 READ i32 WRITE setI32 NOTIFY i32Changed FINAL)
Q_PROPERTY(qint64 i64 READ i64 WRITE setI64 NOTIFY i64Changed FINAL)
Q_PROPERTY(qint8 i8 READ i8 WRITE setI8 NOTIFY i8Changed FINAL)
Q_PROPERTY(QVariant optionalBoolean READ optionalBoolean WRITE setOptionalBoolean NOTIFY optionalBooleanChanged FINAL)
Q_PROPERTY(QByteArray optionalBytearray READ optionalBytearray WRITE setOptionalBytearray NOTIFY optionalBytearrayChanged FINAL)
Q_PROPERTY(QString optionalString READ optionalString WRITE setOptionalString NOTIFY optionalStringChanged FINAL)
Q_PROPERTY(QVariant optionalU64 READ optionalU64 WRITE setOptionalU64 NOTIFY optionalU64Changed FINAL)
Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged FINAL)
Q_PROPERTY(quint16 u16 READ u16 WRITE setU16 NOTIFY u16Changed FINAL)
Q_PROPERTY(quint32 u32 READ u32 WRITE setU32 NOTIFY u32Changed FINAL)
@ -50,10 +52,14 @@ public:
void setI64(qint64 v);
qint8 i8() const;
void setI8(qint8 v);
QVariant optionalBoolean() const;
void setOptionalBoolean(const QVariant& v);
QByteArray optionalBytearray() const;
void setOptionalBytearray(const QByteArray& v);
QString optionalString() const;
void setOptionalString(const QString& v);
QVariant optionalU64() const;
void setOptionalU64(const QVariant& v);
QString string() const;
void setString(const QString& v);
quint16 u16() const;
@ -73,8 +79,10 @@ signals:
void i32Changed();
void i64Changed();
void i8Changed();
void optionalBooleanChanged();
void optionalBytearrayChanged();
void optionalStringChanged();
void optionalU64Changed();
void stringChanged();
void u16Changed();
void u32Changed();