A few fixes for deeply nested objects

This is still broken according to the test test_objects.
master
Jos van den Oever 2017-08-28 09:28:48 +02:00
parent 64bcac54f0
commit c516409326
30 changed files with 342 additions and 61 deletions

View File

@ -4,7 +4,7 @@ version = "0.1.0"
[dependencies] [dependencies]
libc = "*" libc = "*"
sysinfo = "0.3" sysinfo = "0.3.16"
[lib] [lib]
name = "rust" name = "rust"

View File

@ -69,6 +69,7 @@ extern "C" {
void fibonacci_input_set(Fibonacci::Private*, uint); void fibonacci_input_set(Fibonacci::Private*, uint);
quint64 fibonacci_result_get(const Fibonacci::Private*); quint64 fibonacci_result_get(const Fibonacci::Private*);
}; };
extern "C" { extern "C" {
quint64 fibonacci_list_data_result(const FibonacciList::Private*, int); quint64 fibonacci_list_data_result(const FibonacciList::Private*, int);
void fibonacci_list_sort(FibonacciList::Private*, unsigned char column, Qt::SortOrder order = Qt::AscendingOrder); void fibonacci_list_sort(FibonacciList::Private*, unsigned char column, Qt::SortOrder order = Qt::AscendingOrder);
@ -168,16 +169,21 @@ extern "C" {
void (*)(FibonacciList*)); void (*)(FibonacciList*));
void fibonacci_list_free(FibonacciList::Private*); void fibonacci_list_free(FibonacciList::Private*);
}; };
Fibonacci::Fibonacci(bool /*owned*/, QObject *parent): Fibonacci::Fibonacci(bool /*owned*/, QObject *parent):
QObject(parent), QObject(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Fibonacci::Fibonacci(QObject *parent): Fibonacci::Fibonacci(QObject *parent):
QObject(parent), QObject(parent),
m_d(fibonacci_new(this, m_d(fibonacci_new(this,
fibonacciInputChanged, fibonacciInputChanged,
fibonacciResultChanged)), fibonacciResultChanged)),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
} }
Fibonacci::~Fibonacci() { Fibonacci::~Fibonacci() {
@ -199,7 +205,10 @@ quint64 Fibonacci::result() const
FibonacciList::FibonacciList(bool /*owned*/, QObject *parent): FibonacciList::FibonacciList(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
FibonacciList::FibonacciList(QObject *parent): FibonacciList::FibonacciList(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(fibonacci_list_new(this, m_d(fibonacci_list_new(this,
@ -225,7 +234,8 @@ FibonacciList::FibonacciList(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &FibonacciList::newDataReady, this, [this](const QModelIndex& i) { connect(this, &FibonacciList::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,9 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Fibonacci;
class FibonacciList;
class Fibonacci : public QObject class Fibonacci : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@ -220,10 +220,14 @@ extern "C" {
void (*)(Processes*)); void (*)(Processes*));
void processes_free(Processes::Private*); void processes_free(Processes::Private*);
}; };
Processes::Processes(bool /*owned*/, QObject *parent): Processes::Processes(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Processes::Processes(QObject *parent): Processes::Processes(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(processes_new(this, m_d(processes_new(this,
@ -264,7 +268,8 @@ Processes::Processes(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &Processes::newDataReady, this, [this](const QModelIndex& i) { connect(this, &Processes::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Processes;
class Processes : public QAbstractItemModel class Processes : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT

View File

@ -189,10 +189,14 @@ extern "C" {
void (*)(TimeSeries*)); void (*)(TimeSeries*));
void time_series_free(TimeSeries::Private*); void time_series_free(TimeSeries::Private*);
}; };
TimeSeries::TimeSeries(bool /*owned*/, QObject *parent): TimeSeries::TimeSeries(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
TimeSeries::TimeSeries(QObject *parent): TimeSeries::TimeSeries(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(time_series_new(this, m_d(time_series_new(this,
@ -218,7 +222,8 @@ TimeSeries::TimeSeries(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &TimeSeries::newDataReady, this, [this](const QModelIndex& i) { connect(this, &TimeSeries::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class TimeSeries;
class TimeSeries : public QAbstractItemModel class TimeSeries : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT

View File

@ -240,10 +240,14 @@ extern "C" {
void tree_path_set(Tree::Private*, qstring_t); void tree_path_set(Tree::Private*, qstring_t);
void tree_path_set_none(Tree::Private*); void tree_path_set_none(Tree::Private*);
}; };
Tree::Tree(bool /*owned*/, QObject *parent): Tree::Tree(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Tree::Tree(QObject *parent): Tree::Tree(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(tree_new(this, m_d(tree_new(this,
@ -285,7 +289,8 @@ Tree::Tree(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &Tree::newDataReady, this, [this](const QModelIndex& i) { connect(this, &Tree::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Tree;
class Tree : public QAbstractItemModel class Tree : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT

View File

@ -325,7 +325,7 @@ class %1 : public %3
Q_OBJEC%2 Q_OBJEC%2
)").arg(o.name, "T", baseType(o)); )").arg(o.name, "T", baseType(o));
for (auto object: conf.objects) { for (auto object: conf.objects) {
if (object.containsObject()) { if (object.containsObject() && o.name != object.name) {
h << " friend class " << object.name << ";\n"; h << " friend class " << object.name << ";\n";
} }
} }
@ -414,12 +414,13 @@ QString changedF(const Object& o, const Property& p) {
return lowerInitial(o.name) + upperInitial(p.name) + "Changed"; return lowerInitial(o.name) + upperInitial(p.name) + "Changed";
} }
void constructorArgs(QTextStream& cpp, const Object& o, const Configuration& conf) { void constructorArgs(QTextStream& cpp, const QString& prefix, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name)); const QString lcname(snakeCase(o.name));
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) { if (p.type.type == BindingType::Object) {
cpp << ", m_" << p.name; cpp << ", " << prefix << "m_" << p.name;
constructorArgs(cpp, conf.findObject(p.type.name), conf); constructorArgs(cpp, "m_" + p.name + "->",
conf.findObject(p.type.name), conf);
} else { } else {
cpp << ",\n " << changedF(o, p); cpp << ",\n " << changedF(o, p);
} }
@ -521,6 +522,40 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& co
} }
} }
void initializeMembersEmpty(QTextStream& cpp, const Object& o, const Configuration& conf)
{
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
initializeMembersEmpty(cpp, conf.findObject(p.type.name), conf);
cpp << QString(" %1m_%2(new %3(false, this)),\n")
.arg(p.name, p.type.name);
}
}
}
void initializeMembersZero(QTextStream& cpp, const Object& o, const Configuration& conf)
{
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
cpp << QString(" m_%1(new %2(false, this)),\n")
.arg(p.name, p.type.name);
}
}
}
void initializeMembers(QTextStream& cpp, const QString& prefix, const Object& o, const Configuration& conf)
{
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
initializeMembers(cpp, "m_" + p.name + "->",
conf.findObject(p.type.name), conf);
cpp << QString(" %1m_%2->m_d = %3_%2_get(%1m_d);\n")
.arg(prefix, p.name, snakeCase(o.name));
}
}
}
void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf) { void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name)); const QString lcname(snakeCase(o.name));
cpp << QString("%1::%1(bool /*owned*/, QObject *parent):\n %2(parent),") cpp << QString("%1::%1(bool /*owned*/, QObject *parent):\n %2(parent),")
@ -531,24 +566,14 @@ void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf
.arg(p.name, p.type.name); .arg(p.name, p.type.name);
} }
} }
cpp << " m_d(0),\n m_ownsPrivate(false) {}\n"; cpp << " m_d(0),\n m_ownsPrivate(false)\n{\n}\n\n";
cpp << QString("%1::%1(QObject *parent):\n %2(parent),") cpp << QString("%1::%1(QObject *parent):\n %2(parent),")
.arg(o.name, baseType(o)) << endl; .arg(o.name, baseType(o)) << endl;
for (const Property& p: o.properties) { initializeMembersZero(cpp, o, conf);
if (p.type.type == BindingType::Object) {
cpp << QString(" m_%1(new %2(false, this)),\n")
.arg(p.name, p.type.name);
}
}
cpp << QString(" m_d(%1_new(this").arg(lcname); cpp << QString(" m_d(%1_new(this").arg(lcname);
constructorArgs(cpp, o, conf); constructorArgs(cpp, "", o, conf);
cpp << ")),\n m_ownsPrivate(true) {\n"; cpp << ")),\n m_ownsPrivate(true)\n{\n";
for (const Property& p: o.properties) { initializeMembers(cpp, "", o, conf);
if (p.type.type == BindingType::Object) {
cpp << QString(" m_%1->m_d = %2_%1_get(this->m_d);\n")
.arg(p.name, snakeCase(o.name));
}
}
if (o.type != ObjectType::Object) { if (o.type != ObjectType::Object) {
cpp << QString(R"( connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) { cpp << QString(R"( connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
@ -612,12 +637,11 @@ void writeHeader(const Configuration& conf) {
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
)").arg(guard); )").arg(guard);
for (auto object: conf.objects) { for (auto object: conf.objects) {
if (object.containsObject()) { h << "class " << object.name << ";\n";
h << "class " << object.name << ";\n";
}
} }
for (auto object: conf.objects) { for (auto object: conf.objects) {
writeHeaderObject(h, object, conf); writeHeaderObject(h, object, conf);
@ -706,7 +730,7 @@ void set_qbytearray(QByteArray* v, qbytearray_t* val) {
cpp << "extern \"C\" {\n"; cpp << "extern \"C\" {\n";
writeObjectCDecl(cpp, object, conf); writeObjectCDecl(cpp, object, conf);
cpp << "};" << endl; cpp << "};\n" << endl;
} }
for (auto object: conf.objects) { for (auto object: conf.objects) {

View File

@ -204,17 +204,19 @@ parseConfiguration(const QString& path) {
c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h"); c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h");
const QJsonObject& object = o.value("objects").toObject(); const QJsonObject& object = o.value("objects").toObject();
for (const QString& key: object.keys()) { for (const QString& key: object.keys()) {
Object o = parseObject(key, object[key].toObject());
c.objects.append(o);
bindingTypeProperties().append({ bindingTypeProperties().append({
.type = BindingType::Object, .type = BindingType::Object,
.name = o.name, .name = key,
.cppSetType = o.name, .cppSetType = key,
.cSetType = o.name, .cSetType = key,
.rustType = o.name, .rustType = key,
.rustTypeInit = "", .rustTypeInit = "",
}); });
} }
for (const QString& key: object.keys()) {
Object o = parseObject(key, object[key].toObject());
c.objects.append(o);
}
const QJsonObject rust = o.value("rust").toObject(); const QJsonObject rust = o.value("rust").toObject();
c.rustdir = QDir(base.filePath(rust.value("dir").toString())); c.rustdir = QDir(base.filePath(rust.value("dir").toString()));
c.interfaceModule = rust.value("interfaceModule").toString(); c.interfaceModule = rust.value("interfaceModule").toString();

View File

@ -767,7 +767,7 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
} }
} }
} }
r << "}\n"; r << "}\n\n";
} }
void writeRustImplementation(const Configuration& conf) { void writeRustImplementation(const Configuration& conf) {

View File

@ -36,3 +36,4 @@ impl PersonsTrait for Persons {
true true
} }
} }

View File

@ -26,3 +26,4 @@ impl PersonTrait for Person {
self.emit.user_name_changed(); self.emit.user_name_changed();
} }
} }

View File

@ -89,3 +89,4 @@ impl ObjectTrait for Object {
self.emit.uinteger_changed(); self.emit.uinteger_changed();
} }
} }

View File

@ -3,6 +3,29 @@
#![allow(dead_code)] #![allow(dead_code)]
use interface::*; use interface::*;
pub struct Group {
emit: GroupEmitter,
person: Person,
}
impl GroupTrait for Group {
fn create(emit: GroupEmitter, person: Person) -> Group {
Group {
emit: emit,
person: person,
}
}
fn emit(&self) -> &GroupEmitter {
&self.emit
}
fn get_person(&self) -> &Person {
&self.person
}
fn get_mut_person(&mut self) -> &mut Person {
&mut self.person
}
}
pub struct InnerObject { pub struct InnerObject {
emit: InnerObjectEmitter, emit: InnerObjectEmitter,
description: String, description: String,
@ -26,6 +49,7 @@ impl InnerObjectTrait for InnerObject {
self.emit.description_changed(); self.emit.description_changed();
} }
} }
pub struct Person { pub struct Person {
emit: PersonEmitter, emit: PersonEmitter,
object: InnerObject, object: InnerObject,
@ -48,3 +72,4 @@ impl PersonTrait for Person {
&mut self.object &mut self.object
} }
} }

View File

@ -38,6 +38,61 @@ impl<'a> From<&'a String> for QString {
} }
} }
pub struct GroupQObject {}
#[derive (Clone)]
pub struct GroupEmitter {
qobject: Arc<Mutex<*const GroupQObject>>,
}
unsafe impl Send for GroupEmitter {}
impl GroupEmitter {
fn clear(&self) {
*self.qobject.lock().unwrap() = null();
}
}
pub trait GroupTrait {
fn create(emit: GroupEmitter,
person: Person) -> Self;
fn emit(&self) -> &GroupEmitter;
fn get_person(&self) -> &Person;
fn get_mut_person(&mut self) -> &mut Person;
}
#[no_mangle]
pub extern "C" fn group_new(group: *mut GroupQObject, person: *mut PersonQObject, object: *mut InnerObjectQObject,
description_changed: fn(*const InnerObjectQObject))
-> *mut Group {
let object_emit = InnerObjectEmitter {
qobject: Arc::new(Mutex::new(object)),
description_changed: description_changed,
};
let d_object = InnerObject::create(object_emit);
let person_emit = PersonEmitter {
qobject: Arc::new(Mutex::new(person)),
};
let d_person = Person::create(person_emit,
d_object);
let group_emit = GroupEmitter {
qobject: Arc::new(Mutex::new(group)),
};
let d_group = Group::create(group_emit,
d_person);
Box::into_raw(Box::new(d_group))
}
#[no_mangle]
pub unsafe extern "C" fn group_free(ptr: *mut Group) {
Box::from_raw(ptr).emit().clear();
}
#[no_mangle]
pub unsafe extern "C" fn group_person_get(ptr: *mut Group) -> *mut Person {
(&mut *ptr).get_mut_person()
}
pub struct InnerObjectQObject {} pub struct InnerObjectQObject {}
#[derive (Clone)] #[derive (Clone)]

View File

@ -45,3 +45,4 @@ impl PersonsTrait for Persons {
true true
} }
} }

View File

@ -164,10 +164,14 @@ extern "C" {
void (*)(Persons*)); void (*)(Persons*));
void persons_free(Persons::Private*); void persons_free(Persons::Private*);
}; };
Persons::Persons(bool /*owned*/, QObject *parent): Persons::Persons(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Persons::Persons(QObject *parent): Persons::Persons(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(persons_new(this, m_d(persons_new(this,
@ -193,7 +197,8 @@ Persons::Persons(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) { connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Persons;
class Persons : public QAbstractItemModel class Persons : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT

View File

@ -64,15 +64,20 @@ extern "C" {
void person_user_name_get(const Person::Private*, QString*, qstring_set); void person_user_name_get(const Person::Private*, QString*, qstring_set);
void person_user_name_set(Person::Private*, qstring_t); void person_user_name_set(Person::Private*, qstring_t);
}; };
Person::Person(bool /*owned*/, QObject *parent): Person::Person(bool /*owned*/, QObject *parent):
QObject(parent), QObject(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Person::Person(QObject *parent): Person::Person(QObject *parent):
QObject(parent), QObject(parent),
m_d(person_new(this, m_d(person_new(this,
personUserNameChanged)), personUserNameChanged)),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
} }
Person::~Person() { Person::~Person() {

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Person;
class Person : public QObject class Person : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@ -108,10 +108,14 @@ extern "C" {
quint32 object_uinteger_get(const Object::Private*); quint32 object_uinteger_get(const Object::Private*);
void object_uinteger_set(Object::Private*, uint); void object_uinteger_set(Object::Private*, uint);
}; };
Object::Object(bool /*owned*/, QObject *parent): Object::Object(bool /*owned*/, QObject *parent):
QObject(parent), QObject(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Object::Object(QObject *parent): Object::Object(QObject *parent):
QObject(parent), QObject(parent),
m_d(object_new(this, m_d(object_new(this,
@ -123,7 +127,8 @@ Object::Object(QObject *parent):
objectStringChanged, objectStringChanged,
objectU64Changed, objectU64Changed,
objectUintegerChanged)), objectUintegerChanged)),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
} }
Object::~Object() { Object::~Object() {

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Object;
class Object : public QObject class Object : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@ -6,23 +6,26 @@ class TestRustObjects : public QObject
{ {
Q_OBJECT Q_OBJECT
private slots: private slots:
void testConstructor(); void testOneLevelConstructor();
void testStringGetter(); void testOneLevelStringGetter();
void testStringSetter(); void testOneLevelStringSetter();
void testTwoLevelsConstructor();
void testTwoLevelsStringGetter();
void testTwoLevelsStringSetter();
}; };
void TestRustObjects::testConstructor() void TestRustObjects::testOneLevelConstructor()
{ {
Person person; Person person;
} }
void TestRustObjects::testStringGetter() void TestRustObjects::testOneLevelStringGetter()
{ {
Person person; Person person;
person.object()->setDescription("Konqi"); person.object()->setDescription("Konqi");
} }
void TestRustObjects::testStringSetter() void TestRustObjects::testOneLevelStringSetter()
{ {
// GIVEN // GIVEN
Person person; Person person;
@ -37,5 +40,31 @@ void TestRustObjects::testStringSetter()
QCOMPARE(person.object()->description(), QString("Konqi")); QCOMPARE(person.object()->description(), QString("Konqi"));
} }
void TestRustObjects::testTwoLevelsConstructor()
{
Group group;
}
void TestRustObjects::testTwoLevelsStringGetter()
{
Group group;
group.person()->object()->setDescription("Konqi");
}
void TestRustObjects::testTwoLevelsStringSetter()
{
// GIVEN
Group group;
QSignalSpy spy(group.person()->object(), &InnerObject::descriptionChanged);
// WHEN
group.person()->object()->setDescription("Konqi");
// THEN
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QCOMPARE(group.person()->object()->description(), QString("Konqi"));
}
QTEST_MAIN(TestRustObjects) QTEST_MAIN(TestRustObjects)
#include "test_objects.moc" #include "test_objects.moc"

View File

@ -23,6 +23,14 @@
"type": "InnerObject" "type": "InnerObject"
} }
} }
},
"Group": {
"type": "Object",
"properties": {
"person": {
"type": "Person"
}
}
} }
} }
} }

View File

@ -58,26 +58,70 @@ typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) { void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val; *v = *val;
} }
extern "C" {
Group::Private* group_new(Group*, Person*, InnerObject*, void (*)(InnerObject*));
void group_free(Group::Private*);
Person::Private* group_person_get(const Group::Private*);
};
extern "C" { extern "C" {
InnerObject::Private* inner_object_new(InnerObject*, void (*)(InnerObject*)); InnerObject::Private* inner_object_new(InnerObject*, void (*)(InnerObject*));
void inner_object_free(InnerObject::Private*); void inner_object_free(InnerObject::Private*);
void inner_object_description_get(const InnerObject::Private*, QString*, qstring_set); void inner_object_description_get(const InnerObject::Private*, QString*, qstring_set);
void inner_object_description_set(InnerObject::Private*, qstring_t); void inner_object_description_set(InnerObject::Private*, qstring_t);
}; };
extern "C" { extern "C" {
Person::Private* person_new(Person*, InnerObject*, void (*)(InnerObject*)); Person::Private* person_new(Person*, InnerObject*, void (*)(InnerObject*));
void person_free(Person::Private*); void person_free(Person::Private*);
InnerObject::Private* person_object_get(const Person::Private*); InnerObject::Private* person_object_get(const Person::Private*);
}; };
Group::Group(bool /*owned*/, QObject *parent):
QObject(parent),
m_person(new Person(false, this)),
m_d(0),
m_ownsPrivate(false)
{
}
Group::Group(QObject *parent):
QObject(parent),
m_person(new Person(false, this)),
m_d(group_new(this, m_person, m_person->m_object,
innerObjectDescriptionChanged)),
m_ownsPrivate(true)
{
m_person->m_object->m_d = person_object_get(m_person->m_d);
m_person->m_d = group_person_get(m_d);
}
Group::~Group() {
if (m_ownsPrivate) {
group_free(m_d);
}
}
const Person* Group::person() const
{
return m_person;
}
Person* Group::person()
{
return m_person;
}
InnerObject::InnerObject(bool /*owned*/, QObject *parent): InnerObject::InnerObject(bool /*owned*/, QObject *parent):
QObject(parent), QObject(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
InnerObject::InnerObject(QObject *parent): InnerObject::InnerObject(QObject *parent):
QObject(parent), QObject(parent),
m_d(inner_object_new(this, m_d(inner_object_new(this,
innerObjectDescriptionChanged)), innerObjectDescriptionChanged)),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
} }
InnerObject::~InnerObject() { InnerObject::~InnerObject() {
@ -98,14 +142,18 @@ Person::Person(bool /*owned*/, QObject *parent):
QObject(parent), QObject(parent),
m_object(new InnerObject(false, this)), m_object(new InnerObject(false, this)),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Person::Person(QObject *parent): Person::Person(QObject *parent):
QObject(parent), QObject(parent),
m_object(new InnerObject(false, this)), m_object(new InnerObject(false, this)),
m_d(person_new(this, m_object, m_d(person_new(this, m_object,
innerObjectDescriptionChanged)), innerObjectDescriptionChanged)),
m_ownsPrivate(true) { m_ownsPrivate(true)
m_object->m_d = person_object_get(this->m_d); {
m_object->m_d = person_object_get(m_d);
} }
Person::~Person() { Person::~Person() {

View File

@ -4,11 +4,35 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Group;
class InnerObject;
class Person; class Person;
class Group : public QObject
{
Q_OBJECT
friend class Person;
public:
class Private;
private:
Person* const m_person;
Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(Person* person READ person FINAL)
explicit Group(bool owned, QObject *parent);
public:
explicit Group(QObject *parent = nullptr);
~Group();
const Person* person() const;
Person* person();
signals:
};
class InnerObject : public QObject class InnerObject : public QObject
{ {
Q_OBJECT Q_OBJECT
friend class Group;
friend class Person; friend class Person;
public: public:
class Private; class Private;
@ -29,7 +53,7 @@ signals:
class Person : public QObject class Person : public QObject
{ {
Q_OBJECT Q_OBJECT
friend class Person; friend class Group;
public: public:
class Private; class Private;
private: private:

View File

@ -182,10 +182,14 @@ extern "C" {
void (*)(Persons*)); void (*)(Persons*));
void persons_free(Persons::Private*); void persons_free(Persons::Private*);
}; };
Persons::Persons(bool /*owned*/, QObject *parent): Persons::Persons(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(0), m_d(0),
m_ownsPrivate(false) {} m_ownsPrivate(false)
{
}
Persons::Persons(QObject *parent): Persons::Persons(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
m_d(persons_new(this, m_d(persons_new(this,
@ -226,7 +230,8 @@ Persons::Persons(QObject *parent):
o->endRemoveRows(); o->endRemoveRows();
} }
)), )),
m_ownsPrivate(true) { m_ownsPrivate(true)
{
connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) { connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i); fetchMore(i);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);

View File

@ -5,6 +5,8 @@
#include <QObject> #include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class Persons;
class Persons : public QAbstractItemModel class Persons : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT