Allow nesting of binding types.

master
Jos van den Oever 2017-08-26 19:10:18 +02:00
parent 31f2e0078d
commit 64bcac54f0
40 changed files with 1234 additions and 470 deletions

View File

@ -14,6 +14,10 @@ ApplicationWindow {
id: selectionModel id: selectionModel
model: sortedFileSystem model: sortedFileSystem
} }
ItemSelectionModel {
id: processSelection
model: processes
}
TabView { TabView {
id: tabView id: tabView
anchors.fill: parent anchors.fill: parent
@ -116,11 +120,17 @@ ApplicationWindow {
} }
} }
TreeView { TreeView {
onClicked: {
processSelection.select(index, ItemSelectionModel.ToggleCurrent);
}
width: parent.width width: parent.width
anchors.top: processFilterInput.bottom anchors.top: processFilterInput.bottom
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
id: processView id: processView
model: processes model: processes
selection: processSelection
selectionMode: SelectionMode.ExtendedSelection
// selectionMode: SelectionMode.SingleSelection
sortIndicatorVisible: true sortIndicatorVisible: true
alternatingRowColors: true alternatingRowColors: true
TableViewColumn { TableViewColumn {

View File

@ -83,17 +83,17 @@ pub trait FibonacciTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn fibonacci_new(qobject: *const FibonacciQObject, pub extern "C" fn fibonacci_new(fibonacci: *mut FibonacciQObject,
input_changed: fn(*const FibonacciQObject), input_changed: fn(*const FibonacciQObject),
result_changed: fn(*const FibonacciQObject)) result_changed: fn(*const FibonacciQObject))
-> *mut Fibonacci { -> *mut Fibonacci {
let emit = FibonacciEmitter { let fibonacci_emit = FibonacciEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(fibonacci)),
input_changed: input_changed, input_changed: input_changed,
result_changed: result_changed, result_changed: result_changed,
}; };
let d = Fibonacci::create(emit); let d_fibonacci = Fibonacci::create(fibonacci_emit);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_fibonacci))
} }
#[no_mangle] #[no_mangle]
@ -180,7 +180,7 @@ pub trait FibonacciListTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn fibonacci_list_new(qobject: *const FibonacciListQObject, pub extern "C" fn fibonacci_list_new(fibonacci_list: *mut FibonacciListQObject,
new_data_ready: fn(*const FibonacciListQObject), new_data_ready: fn(*const FibonacciListQObject),
begin_reset_model: fn(*const FibonacciListQObject), begin_reset_model: fn(*const FibonacciListQObject),
end_reset_model: fn(*const FibonacciListQObject), end_reset_model: fn(*const FibonacciListQObject),
@ -193,12 +193,12 @@ pub extern "C" fn fibonacci_list_new(qobject: *const FibonacciListQObject,
usize), usize),
end_remove_rows: fn(*const FibonacciListQObject)) end_remove_rows: fn(*const FibonacciListQObject))
-> *mut FibonacciList { -> *mut FibonacciList {
let emit = FibonacciListEmitter { let fibonacci_list_emit = FibonacciListEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(fibonacci_list)),
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = FibonacciListList { let model = FibonacciListList {
qobject: qobject, qobject: fibonacci_list,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -206,8 +206,8 @@ pub extern "C" fn fibonacci_list_new(qobject: *const FibonacciListQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = FibonacciList::create(emit, model); let d_fibonacci_list = FibonacciList::create(fibonacci_list_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_fibonacci_list))
} }
#[no_mangle] #[no_mangle]

View File

@ -178,7 +178,7 @@ pub trait TreeTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn tree_new(qobject: *const TreeQObject, pub extern "C" fn tree_new(tree: *mut TreeQObject,
path_changed: fn(*const TreeQObject), path_changed: fn(*const TreeQObject),
new_data_ready: fn(*const TreeQObject, item: usize, valid: bool), new_data_ready: fn(*const TreeQObject, item: usize, valid: bool),
begin_reset_model: fn(*const TreeQObject), begin_reset_model: fn(*const TreeQObject),
@ -192,13 +192,13 @@ pub extern "C" fn tree_new(qobject: *const TreeQObject,
usize), usize),
end_remove_rows: fn(*const TreeQObject)) end_remove_rows: fn(*const TreeQObject))
-> *mut Tree { -> *mut Tree {
let emit = TreeEmitter { let tree_emit = TreeEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(tree)),
path_changed: path_changed, path_changed: path_changed,
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = TreeUniformTree { let model = TreeUniformTree {
qobject: qobject, qobject: tree,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -206,8 +206,8 @@ pub extern "C" fn tree_new(qobject: *const TreeQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = Tree::create(emit, model); let d_tree = Tree::create(tree_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_tree))
} }
#[no_mangle] #[no_mangle]

View File

@ -147,7 +147,7 @@ pub trait ProcessesTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn processes_new(qobject: *const ProcessesQObject, pub extern "C" fn processes_new(processes: *mut ProcessesQObject,
new_data_ready: fn(*const ProcessesQObject, item: usize, valid: bool), new_data_ready: fn(*const ProcessesQObject, item: usize, valid: bool),
begin_reset_model: fn(*const ProcessesQObject), begin_reset_model: fn(*const ProcessesQObject),
end_reset_model: fn(*const ProcessesQObject), end_reset_model: fn(*const ProcessesQObject),
@ -160,12 +160,12 @@ pub extern "C" fn processes_new(qobject: *const ProcessesQObject,
usize), usize),
end_remove_rows: fn(*const ProcessesQObject)) end_remove_rows: fn(*const ProcessesQObject))
-> *mut Processes { -> *mut Processes {
let emit = ProcessesEmitter { let processes_emit = ProcessesEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(processes)),
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = ProcessesUniformTree { let model = ProcessesUniformTree {
qobject: qobject, qobject: processes,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -173,8 +173,8 @@ pub extern "C" fn processes_new(qobject: *const ProcessesQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = Processes::create(emit, model); let d_processes = Processes::create(processes_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_processes))
} }
#[no_mangle] #[no_mangle]

View File

@ -112,7 +112,7 @@ pub trait TimeSeriesTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn time_series_new(qobject: *const TimeSeriesQObject, pub extern "C" fn time_series_new(time_series: *mut TimeSeriesQObject,
new_data_ready: fn(*const TimeSeriesQObject), new_data_ready: fn(*const TimeSeriesQObject),
begin_reset_model: fn(*const TimeSeriesQObject), begin_reset_model: fn(*const TimeSeriesQObject),
end_reset_model: fn(*const TimeSeriesQObject), end_reset_model: fn(*const TimeSeriesQObject),
@ -125,12 +125,12 @@ pub extern "C" fn time_series_new(qobject: *const TimeSeriesQObject,
usize), usize),
end_remove_rows: fn(*const TimeSeriesQObject)) end_remove_rows: fn(*const TimeSeriesQObject))
-> *mut TimeSeries { -> *mut TimeSeries {
let emit = TimeSeriesEmitter { let time_series_emit = TimeSeriesEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(time_series)),
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = TimeSeriesList { let model = TimeSeriesList {
qobject: qobject, qobject: time_series,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -138,8 +138,8 @@ pub extern "C" fn time_series_new(qobject: *const TimeSeriesQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = TimeSeries::create(emit, model); let d_time_series = TimeSeries::create(time_series_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_time_series))
} }
#[no_mangle] #[no_mangle]

View File

@ -44,6 +44,15 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
inline void fibonacciInputChanged(Fibonacci* o)
{
emit o->inputChanged();
}
inline void fibonacciResultChanged(Fibonacci* o)
{
emit o->resultChanged();
}
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +62,6 @@ 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" { extern "C" {
Fibonacci::Private* fibonacci_new(Fibonacci*, void (*)(Fibonacci*), void (*)(Fibonacci*)); Fibonacci::Private* fibonacci_new(Fibonacci*, void (*)(Fibonacci*), void (*)(Fibonacci*));
void fibonacci_free(Fibonacci::Private*); void fibonacci_free(Fibonacci::Private*);
@ -81,7 +89,7 @@ bool FibonacciList::hasChildren(const QModelIndex &parent) const
int FibonacciList::rowCount(const QModelIndex &parent) const int FibonacciList::rowCount(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : fibonacci_list_row_count(d); return (parent.isValid()) ? 0 : fibonacci_list_row_count(m_d);
} }
QModelIndex FibonacciList::index(int row, int column, const QModelIndex &parent) const QModelIndex FibonacciList::index(int row, int column, const QModelIndex &parent) const
@ -99,19 +107,19 @@ QModelIndex FibonacciList::parent(const QModelIndex &) const
bool FibonacciList::canFetchMore(const QModelIndex &parent) const bool FibonacciList::canFetchMore(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : fibonacci_list_can_fetch_more(d); return (parent.isValid()) ? 0 : fibonacci_list_can_fetch_more(m_d);
} }
void FibonacciList::fetchMore(const QModelIndex &parent) void FibonacciList::fetchMore(const QModelIndex &parent)
{ {
if (!parent.isValid()) { if (!parent.isValid()) {
fibonacci_list_fetch_more(d); fibonacci_list_fetch_more(m_d);
} }
} }
void FibonacciList::sort(int column, Qt::SortOrder order) void FibonacciList::sort(int column, Qt::SortOrder order)
{ {
fibonacci_list_sort(d, column, order); fibonacci_list_sort(m_d, column, order);
} }
Qt::ItemFlags FibonacciList::flags(const QModelIndex &i) const Qt::ItemFlags FibonacciList::flags(const QModelIndex &i) const
{ {
@ -129,7 +137,7 @@ QVariant FibonacciList::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 0: case Qt::UserRole + 0:
v = fibonacci_list_data_result(d, index.row()); v = fibonacci_list_data_result(m_d, index.row());
break; break;
} }
break; break;
@ -160,29 +168,41 @@ extern "C" {
void (*)(FibonacciList*)); void (*)(FibonacciList*));
void fibonacci_list_free(FibonacciList::Private*); void fibonacci_list_free(FibonacciList::Private*);
}; };
Fibonacci::Fibonacci(bool /*owned*/, QObject *parent):
QObject(parent),
m_d(0),
m_ownsPrivate(false) {}
Fibonacci::Fibonacci(QObject *parent): Fibonacci::Fibonacci(QObject *parent):
QObject(parent), QObject(parent),
d(fibonacci_new(this, m_d(fibonacci_new(this,
[](Fibonacci* o) { emit o->inputChanged(); }, fibonacciInputChanged,
[](Fibonacci* o) { emit o->resultChanged(); })) {} fibonacciResultChanged)),
m_ownsPrivate(true) {
}
Fibonacci::~Fibonacci() { Fibonacci::~Fibonacci() {
fibonacci_free(d); if (m_ownsPrivate) {
fibonacci_free(m_d);
}
} }
quint32 Fibonacci::input() const quint32 Fibonacci::input() const
{ {
return fibonacci_input_get(d); return fibonacci_input_get(m_d);
} }
void Fibonacci::setInput(uint v) { void Fibonacci::setInput(uint v) {
fibonacci_input_set(d, v); fibonacci_input_set(m_d, v);
} }
quint64 Fibonacci::result() const quint64 Fibonacci::result() const
{ {
return fibonacci_result_get(d); return fibonacci_result_get(m_d);
} }
FibonacciList::FibonacciList(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
FibonacciList::FibonacciList(QObject *parent): FibonacciList::FibonacciList(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(fibonacci_list_new(this, m_d(fibonacci_list_new(this,
[](const FibonacciList* o) { [](const FibonacciList* o) {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
}, },
@ -204,13 +224,15 @@ FibonacciList::FibonacciList(QObject *parent):
[](FibonacciList* o) { [](FibonacciList* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
FibonacciList::~FibonacciList() { FibonacciList::~FibonacciList() {
fibonacci_list_free(d); if (m_ownsPrivate) {
fibonacci_list_free(m_d);
}
} }

View File

@ -11,9 +11,11 @@ class Fibonacci : public QObject
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(quint32 input READ input WRITE setInput NOTIFY inputChanged FINAL) Q_PROPERTY(quint32 input READ input WRITE setInput NOTIFY inputChanged FINAL)
Q_PROPERTY(quint64 result READ result NOTIFY resultChanged FINAL) Q_PROPERTY(quint64 result READ result NOTIFY resultChanged FINAL)
explicit Fibonacci(bool owned, QObject *parent);
public: public:
explicit Fibonacci(QObject *parent = nullptr); explicit Fibonacci(QObject *parent = nullptr);
~Fibonacci(); ~Fibonacci();
@ -23,9 +25,6 @@ public:
signals: signals:
void inputChanged(); void inputChanged();
void resultChanged(); void resultChanged();
private:
quint32 m_input;
quint64 m_result;
}; };
class FibonacciList : public QAbstractItemModel class FibonacciList : public QAbstractItemModel
@ -34,7 +33,9 @@ class FibonacciList : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
explicit FibonacciList(bool owned, QObject *parent);
public: public:
explicit FibonacciList(QObject *parent = nullptr); explicit FibonacciList(QObject *parent = nullptr);
~FibonacciList(); ~FibonacciList();
@ -55,6 +56,5 @@ signals:
// new data is ready to be made available to the model with fetchMore() // new data is ready to be made available to the model with fetchMore()
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
private:
}; };
#endif // FIBONACCI_H #endif // FIBONACCI_H

View File

@ -44,6 +44,7 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +54,6 @@ 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" { extern "C" {
void processes_data_cmd(const Processes::Private*, quintptr, QString*, qstring_set); void processes_data_cmd(const Processes::Private*, quintptr, QString*, qstring_set);
quint8 processes_data_cpu_percentage(const Processes::Private*, quintptr); quint8 processes_data_cpu_percentage(const Processes::Private*, quintptr);
@ -86,7 +86,7 @@ int Processes::rowCount(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return 0; return 0;
} }
return processes_row_count(d, parent.internalId(), parent.isValid()); return processes_row_count(m_d, parent.internalId(), parent.isValid());
} }
QModelIndex Processes::index(int row, int column, const QModelIndex &parent) const QModelIndex Processes::index(int row, int column, const QModelIndex &parent) const
@ -100,7 +100,7 @@ QModelIndex Processes::index(int row, int column, const QModelIndex &parent) con
if (row >= rowCount(parent)) { if (row >= rowCount(parent)) {
return QModelIndex(); return QModelIndex();
} }
const quintptr id = processes_index(d, parent.internalId(), parent.isValid(), row); const quintptr id = processes_index(m_d, parent.internalId(), parent.isValid(), row);
return createIndex(row, column, id); return createIndex(row, column, id);
} }
@ -109,7 +109,7 @@ QModelIndex Processes::parent(const QModelIndex &index) const
if (!index.isValid()) { if (!index.isValid()) {
return QModelIndex(); return QModelIndex();
} }
const qmodelindex_t parent = processes_parent(d, index.internalId()); const qmodelindex_t parent = processes_parent(m_d, index.internalId());
return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex(); return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex();
} }
@ -118,17 +118,17 @@ bool Processes::canFetchMore(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return false; return false;
} }
return processes_can_fetch_more(d, parent.internalId(), parent.isValid()); return processes_can_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Processes::fetchMore(const QModelIndex &parent) void Processes::fetchMore(const QModelIndex &parent)
{ {
processes_fetch_more(d, parent.internalId(), parent.isValid()); processes_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Processes::sort(int column, Qt::SortOrder order) void Processes::sort(int column, Qt::SortOrder order)
{ {
processes_sort(d, column, order); processes_sort(m_d, column, order);
} }
Qt::ItemFlags Processes::flags(const QModelIndex &i) const Qt::ItemFlags Processes::flags(const QModelIndex &i) const
{ {
@ -145,29 +145,29 @@ QVariant Processes::data(const QModelIndex &index, int role) const
case 0: case 0:
switch (role) { switch (role) {
case Qt::UserRole + 0: case Qt::UserRole + 0:
processes_data_cmd(d, index.internalId(), &s, set_qstring); processes_data_cmd(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
case Qt::UserRole + 1: case Qt::UserRole + 1:
v = processes_data_cpu_percentage(d, index.internalId()); v = processes_data_cpu_percentage(m_d, index.internalId());
break; break;
case Qt::UserRole + 2: case Qt::UserRole + 2:
v = processes_data_cpu_usage(d, index.internalId()); v = processes_data_cpu_usage(m_d, index.internalId());
break; break;
case Qt::UserRole + 3: case Qt::UserRole + 3:
v = processes_data_memory(d, index.internalId()); v = processes_data_memory(m_d, index.internalId());
break; break;
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 4: case Qt::UserRole + 4:
processes_data_name(d, index.internalId(), &s, set_qstring); processes_data_name(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
case Qt::ToolTipRole: case Qt::ToolTipRole:
case Qt::UserRole + 5: case Qt::UserRole + 5:
v = processes_data_pid(d, index.internalId()); v = processes_data_pid(m_d, index.internalId());
break; break;
case Qt::UserRole + 6: case Qt::UserRole + 6:
v = processes_data_uid(d, index.internalId()); v = processes_data_uid(m_d, index.internalId());
break; break;
} }
break; break;
@ -175,7 +175,7 @@ QVariant Processes::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 2: case Qt::UserRole + 2:
v = processes_data_cpu_usage(d, index.internalId()); v = processes_data_cpu_usage(m_d, index.internalId());
break; break;
} }
break; break;
@ -183,7 +183,7 @@ QVariant Processes::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 3: case Qt::UserRole + 3:
v = processes_data_memory(d, index.internalId()); v = processes_data_memory(m_d, index.internalId());
break; break;
} }
break; break;
@ -220,12 +220,16 @@ extern "C" {
void (*)(Processes*)); void (*)(Processes*));
void processes_free(Processes::Private*); void processes_free(Processes::Private*);
}; };
Processes::Processes(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
Processes::Processes(QObject *parent): Processes::Processes(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(processes_new(this, m_d(processes_new(this,
[](const Processes* o, quintptr id, bool valid) { [](const Processes* o, quintptr id, bool valid) {
if (valid) { if (valid) {
int row = processes_row(o->d, id); int row = processes_row(o->m_d, id);
emit o->newDataReady(o->createIndex(row, 0, id)); emit o->newDataReady(o->createIndex(row, 0, id));
} else { } else {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
@ -239,7 +243,7 @@ Processes::Processes(QObject *parent):
}, },
[](Processes* o, option<quintptr> id, int first, int last) { [](Processes* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = processes_row(o->d, id.value); int row = processes_row(o->m_d, id.value);
o->beginInsertRows(o->createIndex(row, 0, id.value), first, last); o->beginInsertRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginInsertRows(QModelIndex(), first, last); o->beginInsertRows(QModelIndex(), first, last);
@ -250,7 +254,7 @@ Processes::Processes(QObject *parent):
}, },
[](Processes* o, option<quintptr> id, int first, int last) { [](Processes* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = processes_row(o->d, id.value); int row = processes_row(o->m_d, id.value);
o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last); o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginRemoveRows(QModelIndex(), first, last); o->beginRemoveRows(QModelIndex(), first, last);
@ -259,13 +263,15 @@ Processes::Processes(QObject *parent):
[](Processes* o) { [](Processes* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
Processes::~Processes() { Processes::~Processes() {
processes_free(d); if (m_ownsPrivate) {
processes_free(m_d);
}
} }

View File

@ -11,7 +11,9 @@ class Processes : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
explicit Processes(bool owned, QObject *parent);
public: public:
explicit Processes(QObject *parent = nullptr); explicit Processes(QObject *parent = nullptr);
~Processes(); ~Processes();
@ -32,6 +34,5 @@ signals:
// new data is ready to be made available to the model with fetchMore() // new data is ready to be made available to the model with fetchMore()
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
private:
}; };
#endif // PROCESSES_H #endif // PROCESSES_H

View File

@ -44,6 +44,7 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +54,6 @@ 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" { extern "C" {
uint time_series_data_input(const TimeSeries::Private*, int); uint time_series_data_input(const TimeSeries::Private*, int);
bool time_series_set_data_input(TimeSeries::Private*, int, uint); bool time_series_set_data_input(TimeSeries::Private*, int, uint);
@ -77,7 +77,7 @@ bool TimeSeries::hasChildren(const QModelIndex &parent) const
int TimeSeries::rowCount(const QModelIndex &parent) const int TimeSeries::rowCount(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : time_series_row_count(d); return (parent.isValid()) ? 0 : time_series_row_count(m_d);
} }
QModelIndex TimeSeries::index(int row, int column, const QModelIndex &parent) const QModelIndex TimeSeries::index(int row, int column, const QModelIndex &parent) const
@ -95,19 +95,19 @@ QModelIndex TimeSeries::parent(const QModelIndex &) const
bool TimeSeries::canFetchMore(const QModelIndex &parent) const bool TimeSeries::canFetchMore(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : time_series_can_fetch_more(d); return (parent.isValid()) ? 0 : time_series_can_fetch_more(m_d);
} }
void TimeSeries::fetchMore(const QModelIndex &parent) void TimeSeries::fetchMore(const QModelIndex &parent)
{ {
if (!parent.isValid()) { if (!parent.isValid()) {
time_series_fetch_more(d); time_series_fetch_more(m_d);
} }
} }
void TimeSeries::sort(int column, Qt::SortOrder order) void TimeSeries::sort(int column, Qt::SortOrder order)
{ {
time_series_sort(d, column, order); time_series_sort(m_d, column, order);
} }
Qt::ItemFlags TimeSeries::flags(const QModelIndex &i) const Qt::ItemFlags TimeSeries::flags(const QModelIndex &i) const
{ {
@ -132,10 +132,10 @@ QVariant TimeSeries::data(const QModelIndex &index, int role) const
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
case Qt::UserRole + 0: case Qt::UserRole + 0:
v = time_series_data_input(d, index.row()); v = time_series_data_input(m_d, index.row());
break; break;
case Qt::UserRole + 1: case Qt::UserRole + 1:
v = time_series_data_result(d, index.row()); v = time_series_data_result(m_d, index.row());
break; break;
} }
break; break;
@ -144,7 +144,7 @@ QVariant TimeSeries::data(const QModelIndex &index, int role) const
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
case Qt::UserRole + 1: case Qt::UserRole + 1:
v = time_series_data_result(d, index.row()); v = time_series_data_result(m_d, index.row());
break; break;
} }
break; break;
@ -162,15 +162,15 @@ bool TimeSeries::setData(const QModelIndex &index, const QVariant &value, int ro
bool set = false; bool set = false;
if (index.column() == 0) { if (index.column() == 0) {
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) { if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) {
set = time_series_set_data_input(d, index.row(), value.value<quint32>()); set = time_series_set_data_input(m_d, index.row(), value.value<quint32>());
} }
if (role == Qt::UserRole + 1) { if (role == Qt::UserRole + 1) {
set = time_series_set_data_result(d, index.row(), value.value<quint32>()); set = time_series_set_data_result(m_d, index.row(), value.value<quint32>());
} }
} }
if (index.column() == 1) { if (index.column() == 1) {
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 1) { if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 1) {
set = time_series_set_data_result(d, index.row(), value.value<quint32>()); set = time_series_set_data_result(m_d, index.row(), value.value<quint32>());
} }
} }
if (set) { if (set) {
@ -189,9 +189,13 @@ extern "C" {
void (*)(TimeSeries*)); void (*)(TimeSeries*));
void time_series_free(TimeSeries::Private*); void time_series_free(TimeSeries::Private*);
}; };
TimeSeries::TimeSeries(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
TimeSeries::TimeSeries(QObject *parent): TimeSeries::TimeSeries(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(time_series_new(this, m_d(time_series_new(this,
[](const TimeSeries* o) { [](const TimeSeries* o) {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
}, },
@ -213,13 +217,15 @@ TimeSeries::TimeSeries(QObject *parent):
[](TimeSeries* o) { [](TimeSeries* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
TimeSeries::~TimeSeries() { TimeSeries::~TimeSeries() {
time_series_free(d); if (m_ownsPrivate) {
time_series_free(m_d);
}
} }

View File

@ -11,7 +11,9 @@ class TimeSeries : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
explicit TimeSeries(bool owned, QObject *parent);
public: public:
explicit TimeSeries(QObject *parent = nullptr); explicit TimeSeries(QObject *parent = nullptr);
~TimeSeries(); ~TimeSeries();
@ -32,6 +34,5 @@ signals:
// new data is ready to be made available to the model with fetchMore() // new data is ready to be made available to the model with fetchMore()
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
private:
}; };
#endif // TIMESERIES_H #endif // TIMESERIES_H

View File

@ -44,6 +44,11 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
inline void treePathChanged(Tree* o)
{
emit o->pathChanged();
}
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +58,6 @@ 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" { extern "C" {
void tree_data_file_icon(const Tree::Private*, quintptr, QByteArray*, qbytearray_set); void tree_data_file_icon(const Tree::Private*, quintptr, QByteArray*, qbytearray_set);
void tree_data_file_name(const Tree::Private*, quintptr, QString*, qstring_set); void tree_data_file_name(const Tree::Private*, quintptr, QString*, qstring_set);
@ -85,7 +89,7 @@ int Tree::rowCount(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return 0; return 0;
} }
return tree_row_count(d, parent.internalId(), parent.isValid()); return tree_row_count(m_d, parent.internalId(), parent.isValid());
} }
QModelIndex Tree::index(int row, int column, const QModelIndex &parent) const QModelIndex Tree::index(int row, int column, const QModelIndex &parent) const
@ -99,7 +103,7 @@ QModelIndex Tree::index(int row, int column, const QModelIndex &parent) const
if (row >= rowCount(parent)) { if (row >= rowCount(parent)) {
return QModelIndex(); return QModelIndex();
} }
const quintptr id = tree_index(d, parent.internalId(), parent.isValid(), row); const quintptr id = tree_index(m_d, parent.internalId(), parent.isValid(), row);
return createIndex(row, column, id); return createIndex(row, column, id);
} }
@ -108,7 +112,7 @@ QModelIndex Tree::parent(const QModelIndex &index) const
if (!index.isValid()) { if (!index.isValid()) {
return QModelIndex(); return QModelIndex();
} }
const qmodelindex_t parent = tree_parent(d, index.internalId()); const qmodelindex_t parent = tree_parent(m_d, index.internalId());
return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex(); return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex();
} }
@ -117,17 +121,17 @@ bool Tree::canFetchMore(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return false; return false;
} }
return tree_can_fetch_more(d, parent.internalId(), parent.isValid()); return tree_can_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Tree::fetchMore(const QModelIndex &parent) void Tree::fetchMore(const QModelIndex &parent)
{ {
tree_fetch_more(d, parent.internalId(), parent.isValid()); tree_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Tree::sort(int column, Qt::SortOrder order) void Tree::sort(int column, Qt::SortOrder order)
{ {
tree_sort(d, column, order); tree_sort(m_d, column, order);
} }
Qt::ItemFlags Tree::flags(const QModelIndex &i) const Qt::ItemFlags Tree::flags(const QModelIndex &i) const
{ {
@ -145,26 +149,26 @@ QVariant Tree::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DecorationRole: case Qt::DecorationRole:
case Qt::UserRole + 0: case Qt::UserRole + 0:
tree_data_file_icon(d, index.internalId(), &b, set_qbytearray); tree_data_file_icon(m_d, index.internalId(), &b, set_qbytearray);
if (!b.isNull()) v.setValue<QByteArray>(b); if (!b.isNull()) v.setValue<QByteArray>(b);
break; break;
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 1: case Qt::UserRole + 1:
tree_data_file_name(d, index.internalId(), &s, set_qstring); tree_data_file_name(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
case Qt::UserRole + 2: case Qt::UserRole + 2:
tree_data_file_path(d, index.internalId(), &s, set_qstring); tree_data_file_path(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
case Qt::UserRole + 3: case Qt::UserRole + 3:
v = tree_data_file_permissions(d, index.internalId()); v = tree_data_file_permissions(m_d, index.internalId());
break; break;
case Qt::UserRole + 4: case Qt::UserRole + 4:
v = tree_data_file_size(d, index.internalId()); v = tree_data_file_size(m_d, index.internalId());
break; break;
case Qt::UserRole + 5: case Qt::UserRole + 5:
v = tree_data_file_type(d, index.internalId()); v = tree_data_file_type(m_d, index.internalId());
break; break;
} }
break; break;
@ -172,7 +176,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 4: case Qt::UserRole + 4:
v = tree_data_file_size(d, index.internalId()); v = tree_data_file_size(m_d, index.internalId());
break; break;
} }
break; break;
@ -180,7 +184,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 2: case Qt::UserRole + 2:
tree_data_file_path(d, index.internalId(), &s, set_qstring); tree_data_file_path(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
} }
@ -189,7 +193,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 3: case Qt::UserRole + 3:
v = tree_data_file_permissions(d, index.internalId()); v = tree_data_file_permissions(m_d, index.internalId());
break; break;
} }
break; break;
@ -197,7 +201,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::UserRole + 5: case Qt::UserRole + 5:
v = tree_data_file_type(d, index.internalId()); v = tree_data_file_type(m_d, index.internalId());
break; break;
} }
break; break;
@ -236,13 +240,17 @@ 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):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
Tree::Tree(QObject *parent): Tree::Tree(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(tree_new(this, m_d(tree_new(this,
[](Tree* o) { emit o->pathChanged(); }, treePathChanged,
[](const Tree* o, quintptr id, bool valid) { [](const Tree* o, quintptr id, bool valid) {
if (valid) { if (valid) {
int row = tree_row(o->d, id); int row = tree_row(o->m_d, id);
emit o->newDataReady(o->createIndex(row, 0, id)); emit o->newDataReady(o->createIndex(row, 0, id));
} else { } else {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
@ -256,7 +264,7 @@ Tree::Tree(QObject *parent):
}, },
[](Tree* o, option<quintptr> id, int first, int last) { [](Tree* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = tree_row(o->d, id.value); int row = tree_row(o->m_d, id.value);
o->beginInsertRows(o->createIndex(row, 0, id.value), first, last); o->beginInsertRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginInsertRows(QModelIndex(), first, last); o->beginInsertRows(QModelIndex(), first, last);
@ -267,7 +275,7 @@ Tree::Tree(QObject *parent):
}, },
[](Tree* o, option<quintptr> id, int first, int last) { [](Tree* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = tree_row(o->d, id.value); int row = tree_row(o->m_d, id.value);
o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last); o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginRemoveRows(QModelIndex(), first, last); o->beginRemoveRows(QModelIndex(), first, last);
@ -276,26 +284,28 @@ Tree::Tree(QObject *parent):
[](Tree* o) { [](Tree* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
Tree::~Tree() { Tree::~Tree() {
tree_free(d); if (m_ownsPrivate) {
tree_free(m_d);
}
} }
QString Tree::path() const QString Tree::path() const
{ {
QString v; QString v;
tree_path_get(d, &v, set_qstring); tree_path_get(m_d, &v, set_qstring);
return v; return v;
} }
void Tree::setPath(const QString& v) { void Tree::setPath(const QString& v) {
if (v.isNull()) { if (v.isNull()) {
tree_path_set_none(d); tree_path_set_none(m_d);
} else { } else {
tree_path_set(d, v); tree_path_set(m_d, v);
} }
} }

View File

@ -11,8 +11,10 @@ class Tree : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL) Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL)
explicit Tree(bool owned, QObject *parent);
public: public:
explicit Tree(QObject *parent = nullptr); explicit Tree(QObject *parent = nullptr);
~Tree(); ~Tree();
@ -36,7 +38,5 @@ signals:
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
void pathChanged(); void pathChanged();
private:
QString m_path;
}; };
#endif // TREE_H #endif // TREE_H

View File

@ -16,6 +16,10 @@ QString upperInitial(const QString& name) {
return name.left(1).toUpper() + name.mid(1); return name.left(1).toUpper() + name.mid(1);
} }
QString lowerInitial(const QString& name) {
return name.left(1).toLower() + name.mid(1);
}
QString writeProperty(const QString& name) { QString writeProperty(const QString& name) {
return "WRITE set" + upperInitial(name) + " "; return "WRITE set" + upperInitial(name) + " ";
} }
@ -106,7 +110,7 @@ bool %1::hasChildren(const QModelIndex &parent) const
int %1::rowCount(const QModelIndex &parent) const int %1::rowCount(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : %2_row_count(d); return (parent.isValid()) ? 0 : %2_row_count(m_d);
} }
QModelIndex %1::index(int row, int column, const QModelIndex &parent) const QModelIndex %1::index(int row, int column, const QModelIndex &parent) const
@ -124,13 +128,13 @@ QModelIndex %1::parent(const QModelIndex &) const
bool %1::canFetchMore(const QModelIndex &parent) const bool %1::canFetchMore(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : %2_can_fetch_more(d); return (parent.isValid()) ? 0 : %2_can_fetch_more(m_d);
} }
void %1::fetchMore(const QModelIndex &parent) void %1::fetchMore(const QModelIndex &parent)
{ {
if (!parent.isValid()) { if (!parent.isValid()) {
%2_fetch_more(d); %2_fetch_more(m_d);
} }
} }
)").arg(o.name, lcname, QString::number(o.columnCount)); )").arg(o.name, lcname, QString::number(o.columnCount));
@ -158,7 +162,7 @@ int %1::rowCount(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return 0; return 0;
} }
return %2_row_count(d, parent.internalId(), parent.isValid()); return %2_row_count(m_d, parent.internalId(), parent.isValid());
} }
QModelIndex %1::index(int row, int column, const QModelIndex &parent) const QModelIndex %1::index(int row, int column, const QModelIndex &parent) const
@ -172,7 +176,7 @@ QModelIndex %1::index(int row, int column, const QModelIndex &parent) const
if (row >= rowCount(parent)) { if (row >= rowCount(parent)) {
return QModelIndex(); return QModelIndex();
} }
const quintptr id = %2_index(d, parent.internalId(), parent.isValid(), row); const quintptr id = %2_index(m_d, parent.internalId(), parent.isValid(), row);
return createIndex(row, column, id); return createIndex(row, column, id);
} }
@ -181,7 +185,7 @@ QModelIndex %1::parent(const QModelIndex &index) const
if (!index.isValid()) { if (!index.isValid()) {
return QModelIndex(); return QModelIndex();
} }
const qmodelindex_t parent = %2_parent(d, index.internalId()); const qmodelindex_t parent = %2_parent(m_d, index.internalId());
return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex(); return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex();
} }
@ -190,12 +194,12 @@ bool %1::canFetchMore(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return false; return false;
} }
return %2_can_fetch_more(d, parent.internalId(), parent.isValid()); return %2_can_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void %1::fetchMore(const QModelIndex &parent) void %1::fetchMore(const QModelIndex &parent)
{ {
%2_fetch_more(d, parent.internalId(), parent.isValid()); %2_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
)").arg(o.name, lcname, QString::number(o.columnCount)); )").arg(o.name, lcname, QString::number(o.columnCount));
} }
@ -203,7 +207,7 @@ void %1::fetchMore(const QModelIndex &parent)
cpp << QString(R"( cpp << QString(R"(
void %1::sort(int column, Qt::SortOrder order) void %1::sort(int column, Qt::SortOrder order)
{ {
%2_sort(d, column, order); %2_sort(m_d, column, order);
} }
Qt::ItemFlags %1::flags(const QModelIndex &i) const Qt::ItemFlags %1::flags(const QModelIndex &i) const
{ {
@ -241,15 +245,15 @@ QVariant %1::data(const QModelIndex &index, int role) const
} }
cpp << QString(" case Qt::UserRole + %1:\n").arg(i); cpp << QString(" case Qt::UserRole + %1:\n").arg(i);
if (ip.type.name == "QString") { if (ip.type.name == "QString") {
cpp << QString(" %1_data_%2(d%4, &s, set_%3);\n") cpp << QString(" %1_data_%2(m_d%4, &s, set_%3);\n")
.arg(lcname, snakeCase(ip.name), ip.type.name.toLower(), index); .arg(lcname, snakeCase(ip.name), ip.type.name.toLower(), index);
cpp << " if (!s.isNull()) v.setValue<QString>(s);\n"; cpp << " if (!s.isNull()) v.setValue<QString>(s);\n";
} else if (ip.type.name == "QByteArray") { } else if (ip.type.name == "QByteArray") {
cpp << QString(" %1_data_%2(d%4, &b, set_%3);\n") cpp << QString(" %1_data_%2(m_d%4, &b, set_%3);\n")
.arg(lcname, snakeCase(ip.name), ip.type.name.toLower(), index); .arg(lcname, snakeCase(ip.name), ip.type.name.toLower(), index);
cpp << " if (!b.isNull()) v.setValue<QByteArray>(b);\n"; cpp << " if (!b.isNull()) v.setValue<QByteArray>(b);\n";
} else { } else {
cpp << QString(" v = %1_data_%2(d%3);\n") cpp << QString(" v = %1_data_%2(m_d%3);\n")
.arg(lcname, snakeCase(ip.name), index); .arg(lcname, snakeCase(ip.name), index);
} }
cpp << " break;\n"; cpp << " break;\n";
@ -295,12 +299,12 @@ bool %1::setData(const QModelIndex &index, const QVariant &value, int role)
test += " || value.isNull()"; test += " || value.isNull()";
} }
cpp << " if (" << test << ") {\n"; cpp << " if (" << test << ") {\n";
cpp << QString(" set = %1_set_data_%2_none(d%3);") cpp << QString(" set = %1_set_data_%2_none(m_d%3);")
.arg(lcname, snakeCase(ip.name), index) << endl; .arg(lcname, snakeCase(ip.name), index) << endl;
cpp << " } else\n"; cpp << " } else\n";
} }
QString val = QString("value.value<%1>()").arg(ip.type.name); QString val = QString("value.value<%1>()").arg(ip.type.name);
cpp << QString(" set = %1_set_data_%2(d%3, %4);") cpp << QString(" set = %1_set_data_%2(m_d%3, %4);")
.arg(lcname, snakeCase(ip.name), index, val) << endl; .arg(lcname, snakeCase(ip.name), index, val) << endl;
cpp << " }\n"; cpp << " }\n";
} }
@ -314,29 +318,52 @@ bool %1::setData(const QModelIndex &index, const QVariant &value, int role)
)"; )";
} }
void writeHeaderObject(QTextStream& h, const Object& o) { void writeHeaderObject(QTextStream& h, const Object& o, const Configuration& conf) {
h << QString(R"( h << QString(R"(
class %1 : public %3 class %1 : public %3
{ {
Q_OBJEC%2 Q_OBJEC%2
public: )").arg(o.name, "T", baseType(o));
for (auto object: conf.objects) {
if (object.containsObject()) {
h << " friend class " << object.name << ";\n";
}
}
h << R"(public:
class Private; class Private;
private: private:
Private * const d; )";
)").arg(o.name, "T", baseType(o));
for (auto p: o.properties) { for (auto p: o.properties) {
h << QString(" Q_PROPERTY(%1 %2 READ %2 %3NOTIFY %2Changed FINAL)") if (p.type.type == BindingType::Object) {
.arg(p.type.name, p.name, h << " " << p.type.name << "* const m_" << p.name << ";\n";
p.write ? writeProperty(p.name) :"") << endl; }
} }
h << QString(R"(public: h << R"( Private * m_d;
bool m_ownsPrivate;
)";
for (auto p: o.properties) {
bool obj = p.type.type == BindingType::Object;
h << QString(" Q_PROPERTY(%1 %2 READ %2 %3%4FINAL)")
.arg(p.type.name + (obj ?"*" :""),
p.name,
p.write ? writeProperty(p.name) :"",
obj ?"" :("NOTIFY " +p.name + "Changed "))
<< endl;
}
h << QString(R"( explicit %1(bool owned, QObject *parent);
public:
explicit %1(QObject *parent = nullptr); explicit %1(QObject *parent = nullptr);
~%1(); ~%1();
)").arg(o.name); )").arg(o.name);
for (auto p: o.properties) { for (auto p: o.properties) {
h << " " << p.type.name << " " << p.name << "() const;" << endl; if (p.type.type == BindingType::Object) {
if (p.write) { h << " const " << p.type.name << "* " << p.name << "() const;" << endl;
h << " void set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v);" << endl; h << " " << p.type.name << "* " << p.name << "();" << endl;
} else {
h << " " << p.type.name << " " << p.name << "() const;" << endl;
if (p.write) {
h << " void set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v);" << endl;
}
} }
} }
if (baseType(o) == "QAbstractItemModel") { if (baseType(o) == "QAbstractItemModel") {
@ -344,20 +371,22 @@ private:
} }
h << "signals:" << endl; h << "signals:" << endl;
for (auto p: o.properties) { for (auto p: o.properties) {
h << " void " << p.name << "Changed();" << endl; if (p.type.type != BindingType::Object) {
} h << " void " << p.name << "Changed();" << endl;
h << "private:" << endl; }
for (auto p: o.properties) {
h << " " << p.type.name << " m_" << p.name << ";" << endl;
} }
h << "};" << endl; h << "};" << endl;
} }
void writeObjectCDecl(QTextStream& cpp, const Object& o) { void constructorArgsDecl(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name)); cpp << o.name << "*";
cpp << QString(" %1::Private* %2_new(%1*").arg(o.name, lcname); for (auto p: o.properties) {
for (int i = 0; i < o.properties.size(); ++i) { if (p.type.type == BindingType::Object) {
cpp << QString(", void (*)(%1*)").arg(o.name); cpp << QString(", ");
constructorArgsDecl(cpp, conf.findObject(p.type.name), conf);
} else {
cpp << QString(", void (*)(%1*)").arg(o.name);
}
} }
if (o.type == ObjectType::List) { if (o.type == ObjectType::List) {
cpp << QString(R"(, cpp << QString(R"(,
@ -379,37 +408,21 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o) {
void (*)(%1*, option<quintptr>, int, int), void (*)(%1*, option<quintptr>, int, int),
void (*)(%1*))").arg(o.name); void (*)(%1*))").arg(o.name);
} }
cpp << ");" << endl;
cpp << QString(" void %2_free(%1::Private*);").arg(o.name, lcname)
<< endl;
for (const Property& p: o.properties) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
if (p.type.isComplex()) {
cpp << QString(" void %2_get(const %1::Private*, %3);")
.arg(o.name, base, cGetType(p.type)) << endl;
} else {
cpp << QString(" %3 %2_get(const %1::Private*);")
.arg(o.name, base, p.type.name) << endl;
}
if (p.write) {
cpp << QString(" void %2_set(%1::Private*, %3);")
.arg(o.name, base, p.type.cSetType) << endl;
if (p.optional) {
cpp << QString(" void %2_set_none(%1::Private*);")
.arg(o.name, base) << endl;
}
}
}
} }
void writeCppObject(QTextStream& cpp, const Object& o) { QString changedF(const Object& o, const Property& p) {
return lowerInitial(o.name) + upperInitial(p.name) + "Changed";
}
void constructorArgs(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name)); const QString lcname(snakeCase(o.name));
cpp << QString("%1::%1(QObject *parent):\n %2(parent),")
.arg(o.name, baseType(o)) << endl;
cpp << QString(" d(%1_new(this").arg(lcname);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
cpp << QString(",\n [](%1* o) { emit o->%2Changed(); }") if (p.type.type == BindingType::Object) {
.arg(o.name, p.name); cpp << ", m_" << p.name;
constructorArgs(cpp, conf.findObject(p.type.name), conf);
} else {
cpp << ",\n " << changedF(o, p);
}
} }
if (o.type == ObjectType::List) { if (o.type == ObjectType::List) {
cpp << QString(R"(, cpp << QString(R"(,
@ -434,18 +447,13 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
[](%1* o) { [](%1* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) {
connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i);
}, Qt::QueuedConnection);
}
)").arg(o.name); )").arg(o.name);
} }
if (o.type == ObjectType::UniformTree) { if (o.type == ObjectType::UniformTree) {
cpp << QString(R"(, cpp << QString(R"(,
[](const %1* o, quintptr id, bool valid) { [](const %1* o, quintptr id, bool valid) {
if (valid) { if (valid) {
int row = %2_row(o->d, id); int row = %2_row(o->m_d, id);
emit o->newDataReady(o->createIndex(row, 0, id)); emit o->newDataReady(o->createIndex(row, 0, id));
} else { } else {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
@ -459,7 +467,7 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
}, },
[](%1* o, option<quintptr> id, int first, int last) { [](%1* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = %2_row(o->d, id.value); int row = %2_row(o->m_d, id.value);
o->beginInsertRows(o->createIndex(row, 0, id.value), first, last); o->beginInsertRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginInsertRows(QModelIndex(), first, last); o->beginInsertRows(QModelIndex(), first, last);
@ -470,7 +478,7 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
}, },
[](%1* o, option<quintptr> id, int first, int last) { [](%1* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = %2_row(o->d, id.value); int row = %2_row(o->m_d, id.value);
o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last); o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginRemoveRows(QModelIndex(), first, last); o->beginRemoveRows(QModelIndex(), first, last);
@ -479,44 +487,115 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
[](%1* o) { [](%1* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) {
connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i);
}, Qt::QueuedConnection);
}
)").arg(o.name, lcname); )").arg(o.name, lcname);
} }
if (o.type == ObjectType::Object) { }
cpp << QString(")) {}");
void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name));
cpp << QString(" %1::Private* %2_new(").arg(o.name, lcname);
constructorArgsDecl(cpp, o, conf);
cpp << ");" << endl;
cpp << QString(" void %2_free(%1::Private*);").arg(o.name, lcname)
<< endl;
for (const Property& p: o.properties) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
if (p.type.type == BindingType::Object) {
cpp << QString(" %3::Private* %2_get(const %1::Private*);")
.arg(o.name, base, p.type.name) << endl;
} else if (p.type.isComplex()) {
cpp << QString(" void %2_get(const %1::Private*, %3);")
.arg(o.name, base, cGetType(p.type)) << endl;
} else {
cpp << QString(" %3 %2_get(const %1::Private*);")
.arg(o.name, base, p.type.name) << endl;
}
if (p.write) {
cpp << QString(" void %2_set(%1::Private*, %3);")
.arg(o.name, base, p.type.cSetType) << endl;
if (p.optional) {
cpp << QString(" void %2_set_none(%1::Private*);")
.arg(o.name, base) << endl;
}
}
} }
cpp << QString(R"( }
void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name));
cpp << QString("%1::%1(bool /*owned*/, QObject *parent):\n %2(parent),")
.arg(o.name, baseType(o)) << endl;
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);
}
}
cpp << " m_d(0),\n m_ownsPrivate(false) {}\n";
cpp << QString("%1::%1(QObject *parent):\n %2(parent),")
.arg(o.name, baseType(o)) << endl;
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);
}
}
cpp << QString(" m_d(%1_new(this").arg(lcname);
constructorArgs(cpp, o, conf);
cpp << ")),\n m_ownsPrivate(true) {\n";
for (const Property& p: o.properties) {
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) {
cpp << QString(R"( connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
fetchMore(i);
}, Qt::QueuedConnection);
)").arg(o.name);
}
cpp << QString(R"(}
%1::~%1() { %1::~%1() {
%2_free(d); if (m_ownsPrivate) {
%2_free(m_d);
}
} }
)").arg(o.name, lcname); )").arg(o.name, lcname);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name)); const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
cpp << QString("%3 %1::%2() const\n{\n").arg(o.name, p.name, p.type.name); if (p.type.type == BindingType::Object) {
if (p.type.isComplex()) { cpp << QString(R"(const %3* %1::%2() const
{
return m_%4;
}
%3* %1::%2()
{
return m_%4;
}
)").arg(o.name, p.name, p.type.name, snakeCase(p.name));
} else if (p.type.isComplex()) {
cpp << QString("%3 %1::%2() const\n{\n").arg(o.name, p.name, p.type.name);
cpp << " " << p.type.name << " v;\n"; cpp << " " << p.type.name << " v;\n";
cpp << " " << base << "_get(d, &v, set_" << p.type.name.toLower() cpp << " " << base << "_get(m_d, &v, set_" << p.type.name.toLower()
<< ");\n"; << ");\n";
cpp << " return v;\n}\n"; cpp << " return v;\n}\n";
} else { } else {
cpp << QString(" return %1_get(d);\n}\n").arg(base); 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) { if (p.write) {
cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v) {" << endl; cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v) {" << endl;
if (p.optional) { if (p.optional) {
cpp << QString(" if (v.isNull()) {") << endl; cpp << QString(" if (v.isNull()) {") << endl;
cpp << QString(" %1_set_none(d);").arg(base) << endl; cpp << QString(" %1_set_none(m_d);").arg(base) << endl;
cpp << QString(" } else {") << endl; cpp << QString(" } else {") << endl;
cpp << QString(" %1_set(d, v);").arg(base) << endl; cpp << QString(" %1_set(m_d, v);").arg(base) << endl;
cpp << QString(" }") << endl; cpp << QString(" }") << endl;
} else { } else {
cpp << QString(" %1_set(d, v);").arg(base) << endl; cpp << QString(" %1_set(m_d, v);").arg(base) << endl;
} }
cpp << "}" << endl; cpp << "}" << endl;
} }
@ -536,7 +615,12 @@ void writeHeader(const Configuration& conf) {
)").arg(guard); )").arg(guard);
for (auto object: conf.objects) { for (auto object: conf.objects) {
writeHeaderObject(h, object); if (object.containsObject()) {
h << "class " << object.name << ";\n";
}
}
for (auto object: conf.objects) {
writeHeaderObject(h, object, conf);
} }
h << QString("#endif // %1\n").arg(guard); h << QString("#endif // %1\n").arg(guard);
@ -591,6 +675,19 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
)").arg(conf.hFile.fileName());
for (auto o: conf.objects) {
for (auto p: o.properties) {
if (p.type.type == BindingType::Object) {
continue;
}
cpp << " inline void " << changedF(o, p) << "(" << o.name << "* o)\n";
cpp << " {\n emit o->" << p.name << "Changed();\n }\n";
}
}
cpp << R"(
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -600,8 +697,7 @@ 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;
} }
)";
)").arg(conf.hFile.fileName());
for (auto object: conf.objects) { for (auto object: conf.objects) {
if (object.type != ObjectType::Object) { if (object.type != ObjectType::Object) {
@ -609,11 +705,11 @@ void set_qbytearray(QByteArray* v, qbytearray_t* val) {
} }
cpp << "extern \"C\" {\n"; cpp << "extern \"C\" {\n";
writeObjectCDecl(cpp, object); writeObjectCDecl(cpp, object, conf);
cpp << "};" << endl; cpp << "};" << endl;
} }
for (auto object: conf.objects) { for (auto object: conf.objects) {
writeCppObject(cpp, object); writeCppObject(cpp, object, conf);
} }
} }

View File

@ -16,78 +16,76 @@ BindingTypeProperties simpleType(BindingType type, const char* name, const char*
}; };
} }
const QMap<BindingType, BindingTypeProperties>& bindingTypeProperties() { QList<BindingTypeProperties>& bindingTypeProperties() {
static QMap<BindingType, BindingTypeProperties> p; static QList<BindingTypeProperties> p;
if (p.empty()) { if (p.empty()) {
QMap<BindingType, BindingTypeProperties> f; QList<BindingTypeProperties> f;
f.insert(BindingType::Bool, simpleType(BindingType::Bool, "bool", "true")); f.append(simpleType(BindingType::Bool, "bool", "true"));
f.insert(BindingType::UChar, { f.append({
.type = BindingType::UChar, .type = BindingType::UChar,
.name = "quint8", .name = "quint8",
.cppSetType = "quint8", .cppSetType = "quint8",
.cSetType = "quint8", .cSetType = "quint8",
.rustType = "u8", .rustType = "u8",
.rustTypeInit = "0", .rustTypeInit = "0",
}); });
f.insert(BindingType::Int, { f.append({
.type = BindingType::Int, .type = BindingType::Int,
.name = "qint32", .name = "qint32",
.cppSetType = "qint32", .cppSetType = "qint32",
.cSetType = "qint32", .cSetType = "qint32",
.rustType = "i32", .rustType = "i32",
.rustTypeInit = "0", .rustTypeInit = "0",
}); });
f.insert(BindingType::UInt, { f.append({
.type = BindingType::UInt, .type = BindingType::UInt,
.name = "quint32", .name = "quint32",
.cppSetType = "uint", .cppSetType = "uint",
.cSetType = "uint", .cSetType = "uint",
.rustType = "u32", .rustType = "u32",
.rustTypeInit = "0" .rustTypeInit = "0"
}); });
f.insert(BindingType::ULongLong, { f.append({
.type = BindingType::ULongLong, .type = BindingType::ULongLong,
.name = "quint64", .name = "quint64",
.cppSetType = "quint64", .cppSetType = "quint64",
.cSetType = "quint64", .cSetType = "quint64",
.rustType = "u64", .rustType = "u64",
.rustTypeInit = "0" .rustTypeInit = "0"
}); });
f.insert(BindingType::Float, { f.append({
.type = BindingType::Float, .type = BindingType::Float,
.name = "float", .name = "float",
.cppSetType = "float", .cppSetType = "float",
.cSetType = "float", .cSetType = "float",
.rustType = "f32", .rustType = "f32",
.rustTypeInit = "0.0" .rustTypeInit = "0.0"
}); });
f.insert(BindingType::QString, { f.append({
.type = BindingType::QString, .type = BindingType::QString,
.name = "QString", .name = "QString",
.cppSetType = "const QString&", .cppSetType = "const QString&",
.cSetType = "qstring_t", .cSetType = "qstring_t",
.rustType = "String", .rustType = "String",
.rustTypeInit = "String::new()" .rustTypeInit = "String::new()"
}); });
f.insert(BindingType::QByteArray, { f.append({
.type = BindingType::QByteArray, .type = BindingType::QByteArray,
.name = "QByteArray", .name = "QByteArray",
.cppSetType = "const QByteArray&", .cppSetType = "const QByteArray&",
.cSetType = "qbytearray_t", .cSetType = "qbytearray_t",
.rustType = "Vec<u8>", .rustType = "Vec<u8>",
.rustTypeInit = "Vec::new()" .rustTypeInit = "Vec::new()"
}); });
p = f; p = f;
} }
return p; return p;
} }
BindingTypeProperties parseBindingType(const QString& value) { BindingTypeProperties parseBindingType(const QString& value) {
QMapIterator<BindingType, BindingTypeProperties> i(bindingTypeProperties()); for (auto type: bindingTypeProperties()) {
while (i.hasNext()) { if (value == type.name) {
i.next(); return type;
if (value == i.value().name) {
return i.value();
} }
} }
QTextStream err(stderr); QTextStream err(stderr);
@ -206,7 +204,16 @@ 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()) {
c.objects.append(parseObject(key, object[key].toObject())); Object o = parseObject(key, object[key].toObject());
c.objects.append(o);
bindingTypeProperties().append({
.type = BindingType::Object,
.name = o.name,
.cppSetType = o.name,
.cSetType = o.name,
.rustType = o.name,
.rustTypeInit = "",
});
} }
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()));

View File

@ -28,7 +28,86 @@ QString rustTypeInit(const T& p)
return p.type.rustTypeInit; return p.type.rustTypeInit;
} }
void writeRustInterfaceObject(QTextStream& r, const Object& o) { void rConstructorArgsDecl(QTextStream& r, const QString& name, const Object& o, const Configuration& conf) {
r << QString("%2: *mut %1QObject").arg(o.name, name);
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
r << QString(", ");
rConstructorArgsDecl(r, p.name, conf.findObject(p.type.name), conf);
} else {
r << QString(",\n %2_changed: fn(*const %1QObject)")
.arg(o.name, snakeCase(p.name));
}
}
if (o.type == ObjectType::List) {
r << QString(",\n new_data_ready: fn(*const %1QObject)")
.arg(o.name);
} else if (o.type == ObjectType::UniformTree) {
r << QString(",\n new_data_ready: fn(*const %1QObject, item: usize, valid: bool)")
.arg(o.name);
}
if (o.type != ObjectType::Object) {
QString indexDecl;
if (o.type == ObjectType::UniformTree) {
indexDecl = " item: usize, valid: bool,";
}
r << QString(R"(,
begin_reset_model: fn(*const %1QObject),
end_reset_model: fn(*const %1QObject),
begin_insert_rows: fn(*const %1QObject,%2
usize,
usize),
end_insert_rows: fn(*const %1QObject),
begin_remove_rows: fn(*const %1QObject,%2
usize,
usize),
end_remove_rows: fn(*const %1QObject))").arg(o.name, indexDecl);
}
}
void rConstructorArgs(QTextStream& r, const QString& name, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name));
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
rConstructorArgs(r, p.name, conf.findObject(p.type.name), conf);
}
}
r << QString(R"( let %2_emit = %1Emitter {
qobject: Arc::new(Mutex::new(%2)),
)").arg(o.name, name);
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) continue;
r << QString(" %1_changed: %1_changed,\n").arg(snakeCase(p.name));
}
if (o.type != ObjectType::Object) {
r << QString(" new_data_ready: new_data_ready,\n");
}
QString model = "";
if (o.type != ObjectType::Object) {
const QString type = o.type == ObjectType::List ? "List" : "UniformTree";
model = ", model";
r << QString(R"( };
let model = %1%2 {
qobject: %3,
begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows,
end_insert_rows: end_insert_rows,
begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows,
)").arg(o.name, type, name);
}
r << QString(" };\n let d_%3 = %1::create(%3_emit%2")
.arg(o.name, model, name);
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
r << ",\n d_" << p.name;
}
}
r << ");\n";
}
void writeRustInterfaceObject(QTextStream& r, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name)); const QString lcname(snakeCase(o.name));
r << QString(R"( r << QString(R"(
pub struct %1QObject {} pub struct %1QObject {}
@ -38,6 +117,9 @@ pub struct %1Emitter {
qobject: Arc<Mutex<*const %1QObject>>, qobject: Arc<Mutex<*const %1QObject>>,
)").arg(o.name); )").arg(o.name);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
continue;
}
r << QString(" %2_changed: fn(*const %1QObject),\n") r << QString(" %2_changed: fn(*const %1QObject),\n")
.arg(o.name, snakeCase(p.name)); .arg(o.name, snakeCase(p.name));
} }
@ -58,6 +140,9 @@ impl %1Emitter {
} }
)").arg(o.name); )").arg(o.name);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
continue;
}
r << QString(R"( pub fn %1_changed(&self) { r << QString(R"( pub fn %1_changed(&self) {
let ptr = *self.qobject.lock().unwrap(); let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() { if !ptr.is_null() {
@ -133,14 +218,25 @@ impl %1%2 {
r << QString(R"(} r << QString(R"(}
pub trait %1Trait { pub trait %1Trait {
fn create(emit: %1Emitter%2) -> Self; fn create(emit: %1Emitter%2)").arg(o.name, modelStruct);
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
r << ",\n " << snakeCase(p.name) << ": " << p.type.name;
}
}
r << QString(R"() -> Self;
fn emit(&self) -> &%1Emitter; fn emit(&self) -> &%1Emitter;
)").arg(o.name, modelStruct); )").arg(o.name);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
const QString lc(snakeCase(p.name)); const QString lc(snakeCase(p.name));
r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustType(p)); if (p.type.type == BindingType::Object) {
if (p.write) { r << QString(" fn get_%1(&self) -> &%2;\n").arg(lc, rustType(p));
r << QString(" fn set_%1(&mut self, value: %2);\n").arg(lc, rustType(p)); r << QString(" fn get_mut_%1(&mut self) -> &mut %2;\n").arg(lc, rustType(p));
} else {
r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustType(p));
if (p.write) {
r << QString(" fn set_%1(&mut self, value: %2);\n").arg(lc, rustType(p));
}
} }
} }
if (o.type == ObjectType::List) { if (o.type == ObjectType::List) {
@ -173,75 +269,30 @@ pub trait %1Trait {
r << QString(R"(} r << QString(R"(}
#[no_mangle] #[no_mangle]
pub extern "C" fn %2_new(qobject: *const %1QObject)").arg(o.name, lcname); pub extern "C" fn %1_new()").arg(lcname);
for (const Property& p: o.properties) { rConstructorArgsDecl(r, lcname, o, conf);
r << QString(",\n %2_changed: fn(*const %1QObject)") r << QString(")\n -> *mut %1 {\n").arg(o.name);
.arg(o.name, snakeCase(p.name)); rConstructorArgs(r, lcname, o, conf);
} r << QString(R"( Box::into_raw(Box::new(d_%2))
if (o.type == ObjectType::List) {
r << QString(",\n new_data_ready: fn(*const %1QObject)")
.arg(o.name);
} else if (o.type == ObjectType::UniformTree) {
r << QString(",\n new_data_ready: fn(*const %1QObject, item: usize, valid: bool)")
.arg(o.name);
}
if (o.type != ObjectType::Object) {
QString indexDecl;
if (o.type == ObjectType::UniformTree) {
indexDecl = " item: usize, valid: bool,";
}
r << QString(R"(,
begin_reset_model: fn(*const %1QObject),
end_reset_model: fn(*const %1QObject),
begin_insert_rows: fn(*const %1QObject,%2
usize,
usize),
end_insert_rows: fn(*const %1QObject),
begin_remove_rows: fn(*const %1QObject,%2
usize,
usize),
end_remove_rows: fn(*const %1QObject))").arg(o.name, indexDecl);
}
r << QString(R"()
-> *mut %1 {
let emit = %1Emitter {
qobject: Arc::new(Mutex::new(qobject)),
)").arg(o.name);
for (const Property& p: o.properties) {
r << QString(" %1_changed: %1_changed,\n").arg(snakeCase(p.name));
}
if (o.type != ObjectType::Object) {
r << QString(" new_data_ready: new_data_ready,\n");
}
QString model = "";
if (o.type != ObjectType::Object) {
const QString type = o.type == ObjectType::List ? "List" : "UniformTree";
model = ", model";
r << QString(R"( };
let model = %1%2 {
qobject: qobject,
begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows,
end_insert_rows: end_insert_rows,
begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows,
)").arg(o.name, type);
}
r << QString(R"( };
let d = %1::create(emit%3);
Box::into_raw(Box::new(d))
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn %2_free(ptr: *mut %1) { pub unsafe extern "C" fn %2_free(ptr: *mut %1) {
Box::from_raw(ptr).emit().clear(); Box::from_raw(ptr).emit().clear();
} }
)").arg(o.name, lcname, model); )").arg(o.name, lcname);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name)); const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
QString ret = ") -> " + rustType(p); QString ret = ") -> " + rustType(p);
if (p.type.isComplex() && !p.optional) { if (p.type.type == BindingType::Object) {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_get(ptr: *mut %1) -> *mut %4 {
(&mut *ptr).get_mut_%3()
}
)").arg(o.name, base, snakeCase(p.name), rustType(p));
} else if (p.type.isComplex() && !p.optional) {
r << QString(R"( r << QString(R"(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn %2_get(ptr: *const %1, pub unsafe extern "C" fn %2_get(ptr: *const %1,
@ -589,7 +640,7 @@ use %1::*;
writeRustTypes(conf, r); writeRustTypes(conf, r);
for (auto object: conf.objects) { for (auto object: conf.objects) {
writeRustInterfaceObject(r, object); writeRustInterfaceObject(r, object, conf);
} }
} }
@ -621,6 +672,11 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
r << QString(" list: Vec<%1Item>,\n").arg(o.name); r << QString(" list: Vec<%1Item>,\n").arg(o.name);
} }
r << "}\n\n"; r << "}\n\n";
for (const Property& p: o.properties) {
if (p.type.type == BindingType::Object) {
modelStruct += ", " + p.name + ": " + p.type.name;
}
}
r << QString(R"(impl %1Trait for %1 { r << QString(R"(impl %1Trait for %1 {
fn create(emit: %1Emitter%2) -> %1 { fn create(emit: %1Emitter%2) -> %1 {
%1 { %1 {
@ -631,7 +687,11 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
} }
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
const QString lc(snakeCase(p.name)); const QString lc(snakeCase(p.name));
r << QString(" %1: %2,\n").arg(lc, rustTypeInit(p)); if (p.type.type == BindingType::Object) {
r << QString(" %1: %1,\n").arg(lc);
} else {
r << QString(" %1: %2,\n").arg(lc, rustTypeInit(p));
}
} }
if (o.type != ObjectType::Object) { if (o.type != ObjectType::Object) {
r << QString(" list: vec![%1Item::default(); 10],\n") r << QString(" list: vec![%1Item::default(); 10],\n")
@ -645,19 +705,29 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
)").arg(o.name); )").arg(o.name);
for (const Property& p: o.properties) { for (const Property& p: o.properties) {
const QString lc(snakeCase(p.name)); const QString lc(snakeCase(p.name));
r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustType(p)); if (p.type.type == BindingType::Object) {
if (p.type.isComplex()) { r << QString(R"( fn get_%1(&self) -> &%2 {
r << QString(" self.%1.clone()\n").arg(lc); &self.%1
}
fn get_mut_%1(&mut self) -> &mut %2 {
&mut self.%1
}
)").arg(lc, rustType(p));
} else { } else {
r << QString(" self.%1\n").arg(lc); r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustType(p));
} if (p.type.isComplex()) {
r << " }\n"; r << QString(" self.%1.clone()\n").arg(lc);
if (p.write) { } else {
r << QString(R"( fn set_%1(&mut self, value: %2) { r << QString(" self.%1\n").arg(lc);
}
r << " }\n";
if (p.write) {
r << QString(R"( fn set_%1(&mut self, value: %2) {
self.%1 = value; self.%1 = value;
self.emit.%1_changed(); self.emit.%1_changed();
} }
)").arg(lc, rustType(p)); )").arg(lc, rustType(p));
}
} }
} }
if (o.type == ObjectType::List) { if (o.type == ObjectType::List) {

View File

@ -3,6 +3,8 @@
#include <QList> #include <QList>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QTextStream>
#include <QCoreApplication>
enum class ObjectType { enum class ObjectType {
Object, Object,
@ -18,7 +20,8 @@ enum class BindingType {
ULongLong, ULongLong,
Float, Float,
QString, QString,
QByteArray QByteArray,
Object,
}; };
struct BindingTypeProperties { struct BindingTypeProperties {
@ -54,6 +57,14 @@ struct Object {
QList<Property> properties; QList<Property> properties;
QList<ItemProperty> itemProperties; QList<ItemProperty> itemProperties;
int columnCount; int columnCount;
bool containsObject() {
for (auto p: properties) {
if (p.type.type == BindingType::Object) {
return true;
}
}
return false;
}
}; };
struct Configuration { struct Configuration {
@ -64,5 +75,17 @@ struct Configuration {
QString implementationModule; QString implementationModule;
QList<Object> objects; QList<Object> objects;
bool overwriteImplementation; bool overwriteImplementation;
const Object& findObject(const QString& name) const {
for (auto& o: objects) {
if (o.name == name) {
return o;
}
}
QTextStream err(stderr);
err << QCoreApplication::translate("main",
"Cannot find type %1.\n").arg(name);
err.flush();
exit(1);
}
}; };

View File

@ -65,3 +65,4 @@ rust_test(test_object rust_object)
rust_test(test_object_types rust_object_types) rust_test(test_object_types rust_object_types)
rust_test(test_list rust_list) rust_test(test_list rust_list)
rust_test(test_tree rust_tree) rust_test(test_tree rust_tree)
rust_test(test_objects rust_objects)

View File

@ -139,7 +139,7 @@ pub trait PersonsTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn persons_new(qobject: *const PersonsQObject, pub extern "C" fn persons_new(persons: *mut PersonsQObject,
new_data_ready: fn(*const PersonsQObject), new_data_ready: fn(*const PersonsQObject),
begin_reset_model: fn(*const PersonsQObject), begin_reset_model: fn(*const PersonsQObject),
end_reset_model: fn(*const PersonsQObject), end_reset_model: fn(*const PersonsQObject),
@ -152,12 +152,12 @@ pub extern "C" fn persons_new(qobject: *const PersonsQObject,
usize), usize),
end_remove_rows: fn(*const PersonsQObject)) end_remove_rows: fn(*const PersonsQObject))
-> *mut Persons { -> *mut Persons {
let emit = PersonsEmitter { let persons_emit = PersonsEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(persons)),
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = PersonsList { let model = PersonsList {
qobject: qobject, qobject: persons,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -165,8 +165,8 @@ pub extern "C" fn persons_new(qobject: *const PersonsQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = Persons::create(emit, model); let d_persons = Persons::create(persons_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_persons))
} }
#[no_mangle] #[no_mangle]

View File

@ -25,4 +25,4 @@ impl PersonTrait for Person {
self.user_name = value; self.user_name = value;
self.emit.user_name_changed(); self.emit.user_name_changed();
} }
} }

View File

@ -68,15 +68,15 @@ pub trait PersonTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn person_new(qobject: *const PersonQObject, pub extern "C" fn person_new(person: *mut PersonQObject,
user_name_changed: fn(*const PersonQObject)) user_name_changed: fn(*const PersonQObject))
-> *mut Person { -> *mut Person {
let emit = PersonEmitter { let person_emit = PersonEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(person)),
user_name_changed: user_name_changed, user_name_changed: user_name_changed,
}; };
let d = Person::create(emit); let d_person = Person::create(person_emit);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_person))
} }
#[no_mangle] #[no_mangle]

View File

@ -39,53 +39,53 @@ impl ObjectTrait for Object {
self.boolean = value; self.boolean = value;
self.emit.boolean_changed(); self.emit.boolean_changed();
} }
fn get_bytearray(&self) -> Vec<u8> { fn get_bytearray(&self) -> Vec<u8> {
self.bytearray.clone() self.bytearray.clone()
} }
fn set_bytearray(&mut self, value: Vec<u8>) { fn set_bytearray(&mut self, value: Vec<u8>) {
self.bytearray = value; self.bytearray = value;
self.emit.bytearray_changed(); self.emit.bytearray_changed();
} }
fn get_integer(&self) -> i32 { fn get_integer(&self) -> i32 {
self.integer self.integer
} }
fn set_integer(&mut self, value: i32) { fn set_integer(&mut self, value: i32) {
self.integer = value; self.integer = value;
self.emit.integer_changed(); self.emit.integer_changed();
} }
fn get_optional_bytearray(&self) -> Option<Vec<u8>> { fn get_optional_bytearray(&self) -> Option<Vec<u8>> {
self.optional_bytearray.clone() self.optional_bytearray.clone()
} }
fn set_optional_bytearray(&mut self, value: Option<Vec<u8>>) { fn set_optional_bytearray(&mut self, value: Option<Vec<u8>>) {
self.optional_bytearray = value; self.optional_bytearray = value;
self.emit.optional_bytearray_changed(); self.emit.optional_bytearray_changed();
} }
fn get_optional_string(&self) -> Option<String> { fn get_optional_string(&self) -> Option<String> {
self.optional_string.clone() self.optional_string.clone()
} }
fn set_optional_string(&mut self, value: Option<String>) { fn set_optional_string(&mut self, value: Option<String>) {
self.optional_string = value; self.optional_string = value;
self.emit.optional_string_changed(); self.emit.optional_string_changed();
} }
fn get_string(&self) -> String { fn get_string(&self) -> String {
self.string.clone() self.string.clone()
} }
fn set_string(&mut self, value: String) { fn set_string(&mut self, value: String) {
self.string = value; self.string = value;
self.emit.string_changed(); self.emit.string_changed();
} }
fn get_u64(&self) -> u64 { fn get_u64(&self) -> u64 {
self.u64 self.u64
} }
fn set_u64(&mut self, value: u64) { fn set_u64(&mut self, value: u64) {
self.u64 = value; self.u64 = value;
self.emit.u64_changed(); self.emit.u64_changed();
} }
fn get_uinteger(&self) -> u32 { fn get_uinteger(&self) -> u32 {
self.uinteger self.uinteger
} }
fn set_uinteger(&mut self, value: u32) { fn set_uinteger(&mut self, value: u32) {
self.uinteger = value; self.uinteger = value;
self.emit.uinteger_changed(); self.emit.uinteger_changed();
} }
} }

View File

@ -177,7 +177,7 @@ pub trait ObjectTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn object_new(qobject: *const ObjectQObject, pub extern "C" fn object_new(object: *mut ObjectQObject,
boolean_changed: fn(*const ObjectQObject), boolean_changed: fn(*const ObjectQObject),
bytearray_changed: fn(*const ObjectQObject), bytearray_changed: fn(*const ObjectQObject),
integer_changed: fn(*const ObjectQObject), integer_changed: fn(*const ObjectQObject),
@ -187,8 +187,8 @@ pub extern "C" fn object_new(qobject: *const ObjectQObject,
u64_changed: fn(*const ObjectQObject), u64_changed: fn(*const ObjectQObject),
uinteger_changed: fn(*const ObjectQObject)) uinteger_changed: fn(*const ObjectQObject))
-> *mut Object { -> *mut Object {
let emit = ObjectEmitter { let object_emit = ObjectEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(object)),
boolean_changed: boolean_changed, boolean_changed: boolean_changed,
bytearray_changed: bytearray_changed, bytearray_changed: bytearray_changed,
integer_changed: integer_changed, integer_changed: integer_changed,
@ -198,8 +198,8 @@ pub extern "C" fn object_new(qobject: *const ObjectQObject,
u64_changed: u64_changed, u64_changed: u64_changed,
uinteger_changed: uinteger_changed, uinteger_changed: uinteger_changed,
}; };
let d = Object::create(emit); let d_object = Object::create(object_emit);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_object))
} }
#[no_mangle] #[no_mangle]

View File

@ -0,0 +1,10 @@
[package]
name = "rust_objects"
version = "1.0.0"
[dependencies]
libc = "*"
[lib]
name = "rust"
crate-type = ["staticlib"]

View File

@ -0,0 +1,50 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]
use interface::*;
pub struct InnerObject {
emit: InnerObjectEmitter,
description: String,
}
impl InnerObjectTrait for InnerObject {
fn create(emit: InnerObjectEmitter) -> InnerObject {
InnerObject {
emit: emit,
description: String::new(),
}
}
fn emit(&self) -> &InnerObjectEmitter {
&self.emit
}
fn get_description(&self) -> String {
self.description.clone()
}
fn set_description(&mut self, value: String) {
self.description = value;
self.emit.description_changed();
}
}
pub struct Person {
emit: PersonEmitter,
object: InnerObject,
}
impl PersonTrait for Person {
fn create(emit: PersonEmitter, object: InnerObject) -> Person {
Person {
emit: emit,
object: object,
}
}
fn emit(&self) -> &PersonEmitter {
&self.emit
}
fn get_object(&self) -> &InnerObject {
&self.object
}
fn get_mut_object(&mut self) -> &mut InnerObject {
&mut self.object
}
}

View File

@ -0,0 +1,148 @@
/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_int, c_void, uint8_t, uint16_t};
use std::slice;
use std::sync::{Arc, Mutex};
use std::ptr::null;
use implementation::*;
#[repr(C)]
pub struct QString {
data: *const uint8_t,
len: c_int,
}
#[repr(C)]
pub struct QStringIn {
data: *const uint16_t,
len: c_int,
}
impl QStringIn {
fn convert(&self) -> String {
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
String::from_utf16_lossy(data)
}
}
impl<'a> From<&'a String> for QString {
fn from(string: &'a String) -> QString {
QString {
len: string.len() as c_int,
data: string.as_ptr(),
}
}
}
pub struct InnerObjectQObject {}
#[derive (Clone)]
pub struct InnerObjectEmitter {
qobject: Arc<Mutex<*const InnerObjectQObject>>,
description_changed: fn(*const InnerObjectQObject),
}
unsafe impl Send for InnerObjectEmitter {}
impl InnerObjectEmitter {
fn clear(&self) {
*self.qobject.lock().unwrap() = null();
}
pub fn description_changed(&self) {
let ptr = *self.qobject.lock().unwrap();
if !ptr.is_null() {
(self.description_changed)(ptr);
}
}
}
pub trait InnerObjectTrait {
fn create(emit: InnerObjectEmitter) -> Self;
fn emit(&self) -> &InnerObjectEmitter;
fn get_description(&self) -> String;
fn set_description(&mut self, value: String);
}
#[no_mangle]
pub extern "C" fn inner_object_new(inner_object: *mut InnerObjectQObject,
description_changed: fn(*const InnerObjectQObject))
-> *mut InnerObject {
let inner_object_emit = InnerObjectEmitter {
qobject: Arc::new(Mutex::new(inner_object)),
description_changed: description_changed,
};
let d_inner_object = InnerObject::create(inner_object_emit);
Box::into_raw(Box::new(d_inner_object))
}
#[no_mangle]
pub unsafe extern "C" fn inner_object_free(ptr: *mut InnerObject) {
Box::from_raw(ptr).emit().clear();
}
#[no_mangle]
pub unsafe extern "C" fn inner_object_description_get(ptr: *const InnerObject,
p: *mut c_void,
set: fn(*mut c_void, QString)) {
let data = (&*ptr).get_description();
set(p, QString::from(&data));
}
#[no_mangle]
pub unsafe extern "C" fn inner_object_description_set(ptr: *mut InnerObject, v: QStringIn) {
(&mut *ptr).set_description(v.convert());
}
pub struct PersonQObject {}
#[derive (Clone)]
pub struct PersonEmitter {
qobject: Arc<Mutex<*const PersonQObject>>,
}
unsafe impl Send for PersonEmitter {}
impl PersonEmitter {
fn clear(&self) {
*self.qobject.lock().unwrap() = null();
}
}
pub trait PersonTrait {
fn create(emit: PersonEmitter,
object: InnerObject) -> Self;
fn emit(&self) -> &PersonEmitter;
fn get_object(&self) -> &InnerObject;
fn get_mut_object(&mut self) -> &mut InnerObject;
}
#[no_mangle]
pub extern "C" fn person_new(person: *mut PersonQObject, object: *mut InnerObjectQObject,
description_changed: fn(*const InnerObjectQObject))
-> *mut Person {
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);
Box::into_raw(Box::new(d_person))
}
#[no_mangle]
pub unsafe extern "C" fn person_free(ptr: *mut Person) {
Box::from_raw(ptr).emit().clear();
}
#[no_mangle]
pub unsafe extern "C" fn person_object_get(ptr: *mut Person) -> *mut InnerObject {
(&mut *ptr).get_mut_object()
}

View File

@ -0,0 +1,4 @@
extern crate libc;
pub mod interface;
mod implementation;

View File

@ -142,7 +142,7 @@ pub trait PersonsTrait {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn persons_new(qobject: *const PersonsQObject, pub extern "C" fn persons_new(persons: *mut PersonsQObject,
new_data_ready: fn(*const PersonsQObject, item: usize, valid: bool), new_data_ready: fn(*const PersonsQObject, item: usize, valid: bool),
begin_reset_model: fn(*const PersonsQObject), begin_reset_model: fn(*const PersonsQObject),
end_reset_model: fn(*const PersonsQObject), end_reset_model: fn(*const PersonsQObject),
@ -155,12 +155,12 @@ pub extern "C" fn persons_new(qobject: *const PersonsQObject,
usize), usize),
end_remove_rows: fn(*const PersonsQObject)) end_remove_rows: fn(*const PersonsQObject))
-> *mut Persons { -> *mut Persons {
let emit = PersonsEmitter { let persons_emit = PersonsEmitter {
qobject: Arc::new(Mutex::new(qobject)), qobject: Arc::new(Mutex::new(persons)),
new_data_ready: new_data_ready, new_data_ready: new_data_ready,
}; };
let model = PersonsUniformTree { let model = PersonsUniformTree {
qobject: qobject, qobject: persons,
begin_reset_model: begin_reset_model, begin_reset_model: begin_reset_model,
end_reset_model: end_reset_model, end_reset_model: end_reset_model,
begin_insert_rows: begin_insert_rows, begin_insert_rows: begin_insert_rows,
@ -168,8 +168,8 @@ pub extern "C" fn persons_new(qobject: *const PersonsQObject,
begin_remove_rows: begin_remove_rows, begin_remove_rows: begin_remove_rows,
end_remove_rows: end_remove_rows, end_remove_rows: end_remove_rows,
}; };
let d = Persons::create(emit, model); let d_persons = Persons::create(persons_emit, model);
Box::into_raw(Box::new(d)) Box::into_raw(Box::new(d_persons))
} }
#[no_mangle] #[no_mangle]

View File

@ -44,6 +44,7 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +54,6 @@ 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" { extern "C" {
void persons_data_user_name(const Persons::Private*, int, QString*, qstring_set); void persons_data_user_name(const Persons::Private*, int, QString*, qstring_set);
bool persons_set_data_user_name(Persons::Private*, int, qstring_t); bool persons_set_data_user_name(Persons::Private*, int, qstring_t);
@ -75,7 +75,7 @@ bool Persons::hasChildren(const QModelIndex &parent) const
int Persons::rowCount(const QModelIndex &parent) const int Persons::rowCount(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : persons_row_count(d); return (parent.isValid()) ? 0 : persons_row_count(m_d);
} }
QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const
@ -93,19 +93,19 @@ QModelIndex Persons::parent(const QModelIndex &) const
bool Persons::canFetchMore(const QModelIndex &parent) const bool Persons::canFetchMore(const QModelIndex &parent) const
{ {
return (parent.isValid()) ? 0 : persons_can_fetch_more(d); return (parent.isValid()) ? 0 : persons_can_fetch_more(m_d);
} }
void Persons::fetchMore(const QModelIndex &parent) void Persons::fetchMore(const QModelIndex &parent)
{ {
if (!parent.isValid()) { if (!parent.isValid()) {
persons_fetch_more(d); persons_fetch_more(m_d);
} }
} }
void Persons::sort(int column, Qt::SortOrder order) void Persons::sort(int column, Qt::SortOrder order)
{ {
persons_sort(d, column, order); persons_sort(m_d, column, order);
} }
Qt::ItemFlags Persons::flags(const QModelIndex &i) const Qt::ItemFlags Persons::flags(const QModelIndex &i) const
{ {
@ -127,7 +127,7 @@ QVariant Persons::data(const QModelIndex &index, int role) const
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
case Qt::UserRole + 0: case Qt::UserRole + 0:
persons_data_user_name(d, index.row(), &s, set_qstring); persons_data_user_name(m_d, index.row(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
} }
@ -145,7 +145,7 @@ bool Persons::setData(const QModelIndex &index, const QVariant &value, int role)
bool set = false; bool set = false;
if (index.column() == 0) { if (index.column() == 0) {
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) { if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) {
set = persons_set_data_user_name(d, index.row(), value.value<QString>()); set = persons_set_data_user_name(m_d, index.row(), value.value<QString>());
} }
} }
if (set) { if (set) {
@ -164,9 +164,13 @@ extern "C" {
void (*)(Persons*)); void (*)(Persons*));
void persons_free(Persons::Private*); void persons_free(Persons::Private*);
}; };
Persons::Persons(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
Persons::Persons(QObject *parent): Persons::Persons(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(persons_new(this, m_d(persons_new(this,
[](const Persons* o) { [](const Persons* o) {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
}, },
@ -188,13 +192,15 @@ Persons::Persons(QObject *parent):
[](Persons* o) { [](Persons* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
Persons::~Persons() { Persons::~Persons() {
persons_free(d); if (m_ownsPrivate) {
persons_free(m_d);
}
} }

View File

@ -11,7 +11,9 @@ class Persons : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
explicit Persons(bool owned, QObject *parent);
public: public:
explicit Persons(QObject *parent = nullptr); explicit Persons(QObject *parent = nullptr);
~Persons(); ~Persons();
@ -32,6 +34,5 @@ signals:
// new data is ready to be made available to the model with fetchMore() // new data is ready to be made available to the model with fetchMore()
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
private:
}; };
#endif // TEST_LIST_RUST_H #endif // TEST_LIST_RUST_H

View File

@ -44,6 +44,11 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
inline void personUserNameChanged(Person* o)
{
emit o->userNameChanged();
}
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,27 +58,34 @@ 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" { extern "C" {
Person::Private* person_new(Person*, void (*)(Person*)); Person::Private* person_new(Person*, void (*)(Person*));
void person_free(Person::Private*); void person_free(Person::Private*);
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):
QObject(parent),
m_d(0),
m_ownsPrivate(false) {}
Person::Person(QObject *parent): Person::Person(QObject *parent):
QObject(parent), QObject(parent),
d(person_new(this, m_d(person_new(this,
[](Person* o) { emit o->userNameChanged(); })) {} personUserNameChanged)),
m_ownsPrivate(true) {
}
Person::~Person() { Person::~Person() {
person_free(d); if (m_ownsPrivate) {
person_free(m_d);
}
} }
QString Person::userName() const QString Person::userName() const
{ {
QString v; QString v;
person_user_name_get(d, &v, set_qstring); person_user_name_get(m_d, &v, set_qstring);
return v; return v;
} }
void Person::setUserName(const QString& v) { void Person::setUserName(const QString& v) {
person_user_name_set(d, v); person_user_name_set(m_d, v);
} }

View File

@ -11,8 +11,10 @@ class Person : public QObject
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged FINAL) Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged FINAL)
explicit Person(bool owned, QObject *parent);
public: public:
explicit Person(QObject *parent = nullptr); explicit Person(QObject *parent = nullptr);
~Person(); ~Person();
@ -20,7 +22,5 @@ public:
void setUserName(const QString& v); void setUserName(const QString& v);
signals: signals:
void userNameChanged(); void userNameChanged();
private:
QString m_userName;
}; };
#endif // TEST_OBJECT_RUST_H #endif // TEST_OBJECT_RUST_H

View File

@ -44,6 +44,39 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
inline void objectBooleanChanged(Object* o)
{
emit o->booleanChanged();
}
inline void objectBytearrayChanged(Object* o)
{
emit o->bytearrayChanged();
}
inline void objectIntegerChanged(Object* o)
{
emit o->integerChanged();
}
inline void objectOptionalBytearrayChanged(Object* o)
{
emit o->optionalBytearrayChanged();
}
inline void objectOptionalStringChanged(Object* o)
{
emit o->optionalStringChanged();
}
inline void objectStringChanged(Object* o)
{
emit o->stringChanged();
}
inline void objectU64Changed(Object* o)
{
emit o->u64Changed();
}
inline void objectUintegerChanged(Object* o)
{
emit o->uintegerChanged();
}
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +86,6 @@ 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" { extern "C" {
Object::Private* object_new(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_free(Object::Private*); void object_free(Object::Private*);
@ -76,90 +108,98 @@ 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):
QObject(parent),
m_d(0),
m_ownsPrivate(false) {}
Object::Object(QObject *parent): Object::Object(QObject *parent):
QObject(parent), QObject(parent),
d(object_new(this, m_d(object_new(this,
[](Object* o) { emit o->booleanChanged(); }, objectBooleanChanged,
[](Object* o) { emit o->bytearrayChanged(); }, objectBytearrayChanged,
[](Object* o) { emit o->integerChanged(); }, objectIntegerChanged,
[](Object* o) { emit o->optionalBytearrayChanged(); }, objectOptionalBytearrayChanged,
[](Object* o) { emit o->optionalStringChanged(); }, objectOptionalStringChanged,
[](Object* o) { emit o->stringChanged(); }, objectStringChanged,
[](Object* o) { emit o->u64Changed(); }, objectU64Changed,
[](Object* o) { emit o->uintegerChanged(); })) {} objectUintegerChanged)),
m_ownsPrivate(true) {
}
Object::~Object() { Object::~Object() {
object_free(d); if (m_ownsPrivate) {
object_free(m_d);
}
} }
bool Object::boolean() const bool Object::boolean() const
{ {
return object_boolean_get(d); return object_boolean_get(m_d);
} }
void Object::setBoolean(bool v) { void Object::setBoolean(bool v) {
object_boolean_set(d, v); object_boolean_set(m_d, v);
} }
QByteArray Object::bytearray() const QByteArray Object::bytearray() const
{ {
QByteArray v; QByteArray v;
object_bytearray_get(d, &v, set_qbytearray); object_bytearray_get(m_d, &v, set_qbytearray);
return v; return v;
} }
void Object::setBytearray(const QByteArray& v) { void Object::setBytearray(const QByteArray& v) {
object_bytearray_set(d, v); object_bytearray_set(m_d, v);
} }
qint32 Object::integer() const qint32 Object::integer() const
{ {
return object_integer_get(d); return object_integer_get(m_d);
} }
void Object::setInteger(qint32 v) { void Object::setInteger(qint32 v) {
object_integer_set(d, v); object_integer_set(m_d, v);
} }
QByteArray Object::optionalBytearray() const QByteArray Object::optionalBytearray() const
{ {
QByteArray v; QByteArray v;
object_optional_bytearray_get(d, &v, set_qbytearray); object_optional_bytearray_get(m_d, &v, set_qbytearray);
return v; return v;
} }
void Object::setOptionalBytearray(const QByteArray& v) { void Object::setOptionalBytearray(const QByteArray& v) {
if (v.isNull()) { if (v.isNull()) {
object_optional_bytearray_set_none(d); object_optional_bytearray_set_none(m_d);
} else { } else {
object_optional_bytearray_set(d, v); object_optional_bytearray_set(m_d, v);
} }
} }
QString Object::optionalString() const QString Object::optionalString() const
{ {
QString v; QString v;
object_optional_string_get(d, &v, set_qstring); object_optional_string_get(m_d, &v, set_qstring);
return v; return v;
} }
void Object::setOptionalString(const QString& v) { void Object::setOptionalString(const QString& v) {
if (v.isNull()) { if (v.isNull()) {
object_optional_string_set_none(d); object_optional_string_set_none(m_d);
} else { } else {
object_optional_string_set(d, v); object_optional_string_set(m_d, v);
} }
} }
QString Object::string() const QString Object::string() const
{ {
QString v; QString v;
object_string_get(d, &v, set_qstring); object_string_get(m_d, &v, set_qstring);
return v; return v;
} }
void Object::setString(const QString& v) { void Object::setString(const QString& v) {
object_string_set(d, v); object_string_set(m_d, v);
} }
quint64 Object::u64() const quint64 Object::u64() const
{ {
return object_u64_get(d); return object_u64_get(m_d);
} }
void Object::setU64(quint64 v) { void Object::setU64(quint64 v) {
object_u64_set(d, v); object_u64_set(m_d, v);
} }
quint32 Object::uinteger() const quint32 Object::uinteger() const
{ {
return object_uinteger_get(d); return object_uinteger_get(m_d);
} }
void Object::setUinteger(uint v) { void Object::setUinteger(uint v) {
object_uinteger_set(d, v); object_uinteger_set(m_d, v);
} }

View File

@ -11,7 +11,8 @@ class Object : public QObject
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(bool boolean READ boolean WRITE setBoolean NOTIFY booleanChanged FINAL) Q_PROPERTY(bool boolean READ boolean WRITE setBoolean NOTIFY booleanChanged FINAL)
Q_PROPERTY(QByteArray bytearray READ bytearray WRITE setBytearray NOTIFY bytearrayChanged FINAL) Q_PROPERTY(QByteArray bytearray READ bytearray WRITE setBytearray NOTIFY bytearrayChanged FINAL)
Q_PROPERTY(qint32 integer READ integer WRITE setInteger NOTIFY integerChanged FINAL) Q_PROPERTY(qint32 integer READ integer WRITE setInteger NOTIFY integerChanged FINAL)
@ -20,6 +21,7 @@ private:
Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged FINAL) Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged FINAL)
Q_PROPERTY(quint64 u64 READ u64 WRITE setU64 NOTIFY u64Changed FINAL) Q_PROPERTY(quint64 u64 READ u64 WRITE setU64 NOTIFY u64Changed FINAL)
Q_PROPERTY(quint32 uinteger READ uinteger WRITE setUinteger NOTIFY uintegerChanged FINAL) Q_PROPERTY(quint32 uinteger READ uinteger WRITE setUinteger NOTIFY uintegerChanged FINAL)
explicit Object(bool owned, QObject *parent);
public: public:
explicit Object(QObject *parent = nullptr); explicit Object(QObject *parent = nullptr);
~Object(); ~Object();
@ -48,14 +50,5 @@ signals:
void stringChanged(); void stringChanged();
void u64Changed(); void u64Changed();
void uintegerChanged(); void uintegerChanged();
private:
bool m_boolean;
QByteArray m_bytearray;
qint32 m_integer;
QByteArray m_optionalBytearray;
QString m_optionalString;
QString m_string;
quint64 m_u64;
quint32 m_uinteger;
}; };
#endif // TEST_OBJECT_TYPES_RUST_H #endif // TEST_OBJECT_TYPES_RUST_H

41
tests/test_objects.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "test_objects_rust.h"
#include <QTest>
#include <QSignalSpy>
class TestRustObjects : public QObject
{
Q_OBJECT
private slots:
void testConstructor();
void testStringGetter();
void testStringSetter();
};
void TestRustObjects::testConstructor()
{
Person person;
}
void TestRustObjects::testStringGetter()
{
Person person;
person.object()->setDescription("Konqi");
}
void TestRustObjects::testStringSetter()
{
// GIVEN
Person person;
QSignalSpy spy(person.object(), &InnerObject::descriptionChanged);
// WHEN
person.object()->setDescription("Konqi");
// THEN
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QCOMPARE(person.object()->description(), QString("Konqi"));
}
QTEST_MAIN(TestRustObjects)
#include "test_objects.moc"

28
tests/test_objects.json Normal file
View File

@ -0,0 +1,28 @@
{
"cppFile": "test_objects_rust.cpp",
"rust": {
"dir": "rust_objects",
"interfaceModule": "interface",
"implementationModule": "implementation",
"typesModule": "types"
},
"objects": {
"InnerObject": {
"type": "Object",
"properties": {
"description": {
"type": "QString",
"write": true
}
}
},
"Person": {
"type": "Object",
"properties": {
"object": {
"type": "InnerObject"
}
}
}
}
}

123
tests/test_objects_rust.cpp Normal file
View File

@ -0,0 +1,123 @@
/* generated by rust_qt_binding_generator */
#include "test_objects_rust.h"
namespace {
template <typename T>
struct option {
public:
T value;
bool some;
operator QVariant() const {
if (some) {
return QVariant(value);
}
return QVariant();
}
};
struct qbytearray_t {
private:
const char* data;
int len;
public:
qbytearray_t(const QByteArray& v):
data(v.data()),
len(v.size()) {
}
operator QByteArray() const {
return QByteArray(data, len);
}
};
struct qstring_t {
private:
const void* data;
int len;
public:
qstring_t(const QString& v):
data(static_cast<const void*>(v.utf16())),
len(v.size()) {
}
operator QString() const {
return QString::fromUtf8(static_cast<const char*>(data), len);
}
};
struct qmodelindex_t {
int row;
quintptr id;
};
inline void innerObjectDescriptionChanged(InnerObject* o)
{
emit o->descriptionChanged();
}
}
typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) {
*v = *val;
}
typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val;
}
extern "C" {
InnerObject::Private* inner_object_new(InnerObject*, void (*)(InnerObject*));
void inner_object_free(InnerObject::Private*);
void inner_object_description_get(const InnerObject::Private*, QString*, qstring_set);
void inner_object_description_set(InnerObject::Private*, qstring_t);
};
extern "C" {
Person::Private* person_new(Person*, InnerObject*, void (*)(InnerObject*));
void person_free(Person::Private*);
InnerObject::Private* person_object_get(const Person::Private*);
};
InnerObject::InnerObject(bool /*owned*/, QObject *parent):
QObject(parent),
m_d(0),
m_ownsPrivate(false) {}
InnerObject::InnerObject(QObject *parent):
QObject(parent),
m_d(inner_object_new(this,
innerObjectDescriptionChanged)),
m_ownsPrivate(true) {
}
InnerObject::~InnerObject() {
if (m_ownsPrivate) {
inner_object_free(m_d);
}
}
QString InnerObject::description() const
{
QString v;
inner_object_description_get(m_d, &v, set_qstring);
return v;
}
void InnerObject::setDescription(const QString& v) {
inner_object_description_set(m_d, v);
}
Person::Person(bool /*owned*/, QObject *parent):
QObject(parent),
m_object(new InnerObject(false, this)),
m_d(0),
m_ownsPrivate(false) {}
Person::Person(QObject *parent):
QObject(parent),
m_object(new InnerObject(false, this)),
m_d(person_new(this, m_object,
innerObjectDescriptionChanged)),
m_ownsPrivate(true) {
m_object->m_d = person_object_get(this->m_d);
}
Person::~Person() {
if (m_ownsPrivate) {
person_free(m_d);
}
}
const InnerObject* Person::object() const
{
return m_object;
}
InnerObject* Person::object()
{
return m_object;
}

48
tests/test_objects_rust.h Normal file
View File

@ -0,0 +1,48 @@
/* generated by rust_qt_binding_generator */
#ifndef TEST_OBJECTS_RUST_H
#define TEST_OBJECTS_RUST_H
#include <QObject>
#include <QAbstractItemModel>
class Person;
class InnerObject : public QObject
{
Q_OBJECT
friend class Person;
public:
class Private;
private:
Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged FINAL)
explicit InnerObject(bool owned, QObject *parent);
public:
explicit InnerObject(QObject *parent = nullptr);
~InnerObject();
QString description() const;
void setDescription(const QString& v);
signals:
void descriptionChanged();
};
class Person : public QObject
{
Q_OBJECT
friend class Person;
public:
class Private;
private:
InnerObject* const m_object;
Private * m_d;
bool m_ownsPrivate;
Q_PROPERTY(InnerObject* object READ object FINAL)
explicit Person(bool owned, QObject *parent);
public:
explicit Person(QObject *parent = nullptr);
~Person();
const InnerObject* object() const;
InnerObject* object();
signals:
};
#endif // TEST_OBJECTS_RUST_H

View File

@ -44,6 +44,7 @@ namespace {
int row; int row;
quintptr id; quintptr id;
}; };
} }
typedef void (*qstring_set)(QString*, qstring_t*); typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) { void set_qstring(QString* v, qstring_t* val) {
@ -53,7 +54,6 @@ 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" { extern "C" {
void persons_data_user_name(const Persons::Private*, quintptr, QString*, qstring_set); void persons_data_user_name(const Persons::Private*, quintptr, QString*, qstring_set);
bool persons_set_data_user_name(Persons::Private*, quintptr, qstring_t); bool persons_set_data_user_name(Persons::Private*, quintptr, qstring_t);
@ -81,7 +81,7 @@ int Persons::rowCount(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return 0; return 0;
} }
return persons_row_count(d, parent.internalId(), parent.isValid()); return persons_row_count(m_d, parent.internalId(), parent.isValid());
} }
QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const
@ -95,7 +95,7 @@ QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const
if (row >= rowCount(parent)) { if (row >= rowCount(parent)) {
return QModelIndex(); return QModelIndex();
} }
const quintptr id = persons_index(d, parent.internalId(), parent.isValid(), row); const quintptr id = persons_index(m_d, parent.internalId(), parent.isValid(), row);
return createIndex(row, column, id); return createIndex(row, column, id);
} }
@ -104,7 +104,7 @@ QModelIndex Persons::parent(const QModelIndex &index) const
if (!index.isValid()) { if (!index.isValid()) {
return QModelIndex(); return QModelIndex();
} }
const qmodelindex_t parent = persons_parent(d, index.internalId()); const qmodelindex_t parent = persons_parent(m_d, index.internalId());
return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex(); return parent.row >= 0 ?createIndex(parent.row, 0, parent.id) :QModelIndex();
} }
@ -113,17 +113,17 @@ bool Persons::canFetchMore(const QModelIndex &parent) const
if (parent.isValid() && parent.column() != 0) { if (parent.isValid() && parent.column() != 0) {
return false; return false;
} }
return persons_can_fetch_more(d, parent.internalId(), parent.isValid()); return persons_can_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Persons::fetchMore(const QModelIndex &parent) void Persons::fetchMore(const QModelIndex &parent)
{ {
persons_fetch_more(d, parent.internalId(), parent.isValid()); persons_fetch_more(m_d, parent.internalId(), parent.isValid());
} }
void Persons::sort(int column, Qt::SortOrder order) void Persons::sort(int column, Qt::SortOrder order)
{ {
persons_sort(d, column, order); persons_sort(m_d, column, order);
} }
Qt::ItemFlags Persons::flags(const QModelIndex &i) const Qt::ItemFlags Persons::flags(const QModelIndex &i) const
{ {
@ -145,7 +145,7 @@ QVariant Persons::data(const QModelIndex &index, int role) const
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
case Qt::UserRole + 0: case Qt::UserRole + 0:
persons_data_user_name(d, index.internalId(), &s, set_qstring); persons_data_user_name(m_d, index.internalId(), &s, set_qstring);
if (!s.isNull()) v.setValue<QString>(s); if (!s.isNull()) v.setValue<QString>(s);
break; break;
} }
@ -163,7 +163,7 @@ bool Persons::setData(const QModelIndex &index, const QVariant &value, int role)
bool set = false; bool set = false;
if (index.column() == 0) { if (index.column() == 0) {
if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) { if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole + 0) {
set = persons_set_data_user_name(d, index.internalId(), value.value<QString>()); set = persons_set_data_user_name(m_d, index.internalId(), value.value<QString>());
} }
} }
if (set) { if (set) {
@ -182,12 +182,16 @@ extern "C" {
void (*)(Persons*)); void (*)(Persons*));
void persons_free(Persons::Private*); void persons_free(Persons::Private*);
}; };
Persons::Persons(bool /*owned*/, QObject *parent):
QAbstractItemModel(parent),
m_d(0),
m_ownsPrivate(false) {}
Persons::Persons(QObject *parent): Persons::Persons(QObject *parent):
QAbstractItemModel(parent), QAbstractItemModel(parent),
d(persons_new(this, m_d(persons_new(this,
[](const Persons* o, quintptr id, bool valid) { [](const Persons* o, quintptr id, bool valid) {
if (valid) { if (valid) {
int row = persons_row(o->d, id); int row = persons_row(o->m_d, id);
emit o->newDataReady(o->createIndex(row, 0, id)); emit o->newDataReady(o->createIndex(row, 0, id));
} else { } else {
emit o->newDataReady(QModelIndex()); emit o->newDataReady(QModelIndex());
@ -201,7 +205,7 @@ Persons::Persons(QObject *parent):
}, },
[](Persons* o, option<quintptr> id, int first, int last) { [](Persons* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = persons_row(o->d, id.value); int row = persons_row(o->m_d, id.value);
o->beginInsertRows(o->createIndex(row, 0, id.value), first, last); o->beginInsertRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginInsertRows(QModelIndex(), first, last); o->beginInsertRows(QModelIndex(), first, last);
@ -212,7 +216,7 @@ Persons::Persons(QObject *parent):
}, },
[](Persons* o, option<quintptr> id, int first, int last) { [](Persons* o, option<quintptr> id, int first, int last) {
if (id.some) { if (id.some) {
int row = persons_row(o->d, id.value); int row = persons_row(o->m_d, id.value);
o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last); o->beginRemoveRows(o->createIndex(row, 0, id.value), first, last);
} else { } else {
o->beginRemoveRows(QModelIndex(), first, last); o->beginRemoveRows(QModelIndex(), first, last);
@ -221,13 +225,15 @@ Persons::Persons(QObject *parent):
[](Persons* o) { [](Persons* o) {
o->endRemoveRows(); o->endRemoveRows();
} }
)) { )),
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);
} }
Persons::~Persons() { Persons::~Persons() {
persons_free(d); if (m_ownsPrivate) {
persons_free(m_d);
}
} }

View File

@ -11,7 +11,9 @@ class Persons : public QAbstractItemModel
public: public:
class Private; class Private;
private: private:
Private * const d; Private * m_d;
bool m_ownsPrivate;
explicit Persons(bool owned, QObject *parent);
public: public:
explicit Persons(QObject *parent = nullptr); explicit Persons(QObject *parent = nullptr);
~Persons(); ~Persons();
@ -32,6 +34,5 @@ signals:
// new data is ready to be made available to the model with fetchMore() // new data is ready to be made available to the model with fetchMore()
void newDataReady(const QModelIndex &parent) const; void newDataReady(const QModelIndex &parent) const;
signals: signals:
private:
}; };
#endif // TEST_TREE_RUST_H #endif // TEST_TREE_RUST_H