Allow nesting of binding types.
parent
31f2e0078d
commit
64bcac54f0
|
@ -14,6 +14,10 @@ ApplicationWindow {
|
|||
id: selectionModel
|
||||
model: sortedFileSystem
|
||||
}
|
||||
ItemSelectionModel {
|
||||
id: processSelection
|
||||
model: processes
|
||||
}
|
||||
TabView {
|
||||
id: tabView
|
||||
anchors.fill: parent
|
||||
|
@ -116,11 +120,17 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
TreeView {
|
||||
onClicked: {
|
||||
processSelection.select(index, ItemSelectionModel.ToggleCurrent);
|
||||
}
|
||||
width: parent.width
|
||||
anchors.top: processFilterInput.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
id: processView
|
||||
model: processes
|
||||
selection: processSelection
|
||||
selectionMode: SelectionMode.ExtendedSelection
|
||||
// selectionMode: SelectionMode.SingleSelection
|
||||
sortIndicatorVisible: true
|
||||
alternatingRowColors: true
|
||||
TableViewColumn {
|
||||
|
|
|
@ -83,17 +83,17 @@ pub trait FibonacciTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
result_changed: fn(*const FibonacciQObject))
|
||||
-> *mut Fibonacci {
|
||||
let emit = FibonacciEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let fibonacci_emit = FibonacciEmitter {
|
||||
qobject: Arc::new(Mutex::new(fibonacci)),
|
||||
input_changed: input_changed,
|
||||
result_changed: result_changed,
|
||||
};
|
||||
let d = Fibonacci::create(emit);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_fibonacci = Fibonacci::create(fibonacci_emit);
|
||||
Box::into_raw(Box::new(d_fibonacci))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -180,7 +180,7 @@ pub trait FibonacciListTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
begin_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),
|
||||
end_remove_rows: fn(*const FibonacciListQObject))
|
||||
-> *mut FibonacciList {
|
||||
let emit = FibonacciListEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let fibonacci_list_emit = FibonacciListEmitter {
|
||||
qobject: Arc::new(Mutex::new(fibonacci_list)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = FibonacciListList {
|
||||
qobject: qobject,
|
||||
qobject: fibonacci_list,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = FibonacciList::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_fibonacci_list = FibonacciList::create(fibonacci_list_emit, model);
|
||||
Box::into_raw(Box::new(d_fibonacci_list))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -178,7 +178,7 @@ pub trait TreeTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
new_data_ready: fn(*const TreeQObject, item: usize, valid: bool),
|
||||
begin_reset_model: fn(*const TreeQObject),
|
||||
|
@ -192,13 +192,13 @@ pub extern "C" fn tree_new(qobject: *const TreeQObject,
|
|||
usize),
|
||||
end_remove_rows: fn(*const TreeQObject))
|
||||
-> *mut Tree {
|
||||
let emit = TreeEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let tree_emit = TreeEmitter {
|
||||
qobject: Arc::new(Mutex::new(tree)),
|
||||
path_changed: path_changed,
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = TreeUniformTree {
|
||||
qobject: qobject,
|
||||
qobject: tree,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = Tree::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_tree = Tree::create(tree_emit, model);
|
||||
Box::into_raw(Box::new(d_tree))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -147,7 +147,7 @@ pub trait ProcessesTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
begin_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),
|
||||
end_remove_rows: fn(*const ProcessesQObject))
|
||||
-> *mut Processes {
|
||||
let emit = ProcessesEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let processes_emit = ProcessesEmitter {
|
||||
qobject: Arc::new(Mutex::new(processes)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = ProcessesUniformTree {
|
||||
qobject: qobject,
|
||||
qobject: processes,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = Processes::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_processes = Processes::create(processes_emit, model);
|
||||
Box::into_raw(Box::new(d_processes))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -112,7 +112,7 @@ pub trait TimeSeriesTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
begin_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),
|
||||
end_remove_rows: fn(*const TimeSeriesQObject))
|
||||
-> *mut TimeSeries {
|
||||
let emit = TimeSeriesEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let time_series_emit = TimeSeriesEmitter {
|
||||
qobject: Arc::new(Mutex::new(time_series)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = TimeSeriesList {
|
||||
qobject: qobject,
|
||||
qobject: time_series,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = TimeSeries::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_time_series = TimeSeries::create(time_series_emit, model);
|
||||
Box::into_raw(Box::new(d_time_series))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -44,6 +44,15 @@ namespace {
|
|||
int row;
|
||||
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*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
Fibonacci::Private* fibonacci_new(Fibonacci*, void (*)(Fibonacci*), void (*)(Fibonacci*));
|
||||
void fibonacci_free(Fibonacci::Private*);
|
||||
|
@ -81,7 +89,7 @@ bool FibonacciList::hasChildren(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
|
||||
|
@ -99,19 +107,19 @@ QModelIndex FibonacciList::parent(const QModelIndex &) 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)
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
fibonacci_list_fetch_more(d);
|
||||
fibonacci_list_fetch_more(m_d);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -129,7 +137,7 @@ QVariant FibonacciList::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 0:
|
||||
v = fibonacci_list_data_result(d, index.row());
|
||||
v = fibonacci_list_data_result(m_d, index.row());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -160,29 +168,41 @@ extern "C" {
|
|||
void (*)(FibonacciList*));
|
||||
void fibonacci_list_free(FibonacciList::Private*);
|
||||
};
|
||||
Fibonacci::Fibonacci(bool /*owned*/, QObject *parent):
|
||||
QObject(parent),
|
||||
m_d(0),
|
||||
m_ownsPrivate(false) {}
|
||||
Fibonacci::Fibonacci(QObject *parent):
|
||||
QObject(parent),
|
||||
d(fibonacci_new(this,
|
||||
[](Fibonacci* o) { emit o->inputChanged(); },
|
||||
[](Fibonacci* o) { emit o->resultChanged(); })) {}
|
||||
m_d(fibonacci_new(this,
|
||||
fibonacciInputChanged,
|
||||
fibonacciResultChanged)),
|
||||
m_ownsPrivate(true) {
|
||||
}
|
||||
|
||||
Fibonacci::~Fibonacci() {
|
||||
fibonacci_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
fibonacci_free(m_d);
|
||||
}
|
||||
}
|
||||
quint32 Fibonacci::input() const
|
||||
{
|
||||
return fibonacci_input_get(d);
|
||||
return fibonacci_input_get(m_d);
|
||||
}
|
||||
void Fibonacci::setInput(uint v) {
|
||||
fibonacci_input_set(d, v);
|
||||
fibonacci_input_set(m_d, v);
|
||||
}
|
||||
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):
|
||||
QAbstractItemModel(parent),
|
||||
d(fibonacci_list_new(this,
|
||||
m_d(fibonacci_list_new(this,
|
||||
[](const FibonacciList* o) {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
},
|
||||
|
@ -204,13 +224,15 @@ FibonacciList::FibonacciList(QObject *parent):
|
|||
[](FibonacciList* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &FibonacciList::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
FibonacciList::~FibonacciList() {
|
||||
fibonacci_list_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
fibonacci_list_free(m_d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,11 @@ class Fibonacci : public QObject
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
Q_PROPERTY(quint32 input READ input WRITE setInput NOTIFY inputChanged FINAL)
|
||||
Q_PROPERTY(quint64 result READ result NOTIFY resultChanged FINAL)
|
||||
explicit Fibonacci(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Fibonacci(QObject *parent = nullptr);
|
||||
~Fibonacci();
|
||||
|
@ -23,9 +25,6 @@ public:
|
|||
signals:
|
||||
void inputChanged();
|
||||
void resultChanged();
|
||||
private:
|
||||
quint32 m_input;
|
||||
quint64 m_result;
|
||||
};
|
||||
|
||||
class FibonacciList : public QAbstractItemModel
|
||||
|
@ -34,7 +33,9 @@ class FibonacciList : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
explicit FibonacciList(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit FibonacciList(QObject *parent = nullptr);
|
||||
~FibonacciList();
|
||||
|
@ -55,6 +56,5 @@ signals:
|
|||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // FIBONACCI_H
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void processes_data_cmd(const Processes::Private*, quintptr, QString*, qstring_set);
|
||||
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) {
|
||||
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
|
||||
|
@ -100,7 +100,7 @@ QModelIndex Processes::index(int row, int column, const QModelIndex &parent) con
|
|||
if (row >= rowCount(parent)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ QModelIndex Processes::parent(const QModelIndex &index) const
|
|||
if (!index.isValid()) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -118,17 +118,17 @@ bool Processes::canFetchMore(const QModelIndex &parent) const
|
|||
if (parent.isValid() && parent.column() != 0) {
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
processes_sort(d, column, order);
|
||||
processes_sort(m_d, column, order);
|
||||
}
|
||||
Qt::ItemFlags Processes::flags(const QModelIndex &i) const
|
||||
{
|
||||
|
@ -145,29 +145,29 @@ QVariant Processes::data(const QModelIndex &index, int role) const
|
|||
case 0:
|
||||
switch (role) {
|
||||
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);
|
||||
break;
|
||||
case Qt::UserRole + 1:
|
||||
v = processes_data_cpu_percentage(d, index.internalId());
|
||||
v = processes_data_cpu_percentage(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 2:
|
||||
v = processes_data_cpu_usage(d, index.internalId());
|
||||
v = processes_data_cpu_usage(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 3:
|
||||
v = processes_data_memory(d, index.internalId());
|
||||
v = processes_data_memory(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
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);
|
||||
break;
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::UserRole + 5:
|
||||
v = processes_data_pid(d, index.internalId());
|
||||
v = processes_data_pid(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 6:
|
||||
v = processes_data_uid(d, index.internalId());
|
||||
v = processes_data_uid(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -175,7 +175,7 @@ QVariant Processes::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 2:
|
||||
v = processes_data_cpu_usage(d, index.internalId());
|
||||
v = processes_data_cpu_usage(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -183,7 +183,7 @@ QVariant Processes::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 3:
|
||||
v = processes_data_memory(d, index.internalId());
|
||||
v = processes_data_memory(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -220,12 +220,16 @@ extern "C" {
|
|||
void (*)(Processes*));
|
||||
void processes_free(Processes::Private*);
|
||||
};
|
||||
Processes::Processes(bool /*owned*/, QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
m_d(0),
|
||||
m_ownsPrivate(false) {}
|
||||
Processes::Processes(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(processes_new(this,
|
||||
m_d(processes_new(this,
|
||||
[](const Processes* o, quintptr id, bool 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));
|
||||
} else {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
|
@ -239,7 +243,7 @@ Processes::Processes(QObject *parent):
|
|||
},
|
||||
[](Processes* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginInsertRows(QModelIndex(), first, last);
|
||||
|
@ -250,7 +254,7 @@ Processes::Processes(QObject *parent):
|
|||
},
|
||||
[](Processes* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginRemoveRows(QModelIndex(), first, last);
|
||||
|
@ -259,13 +263,15 @@ Processes::Processes(QObject *parent):
|
|||
[](Processes* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &Processes::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
Processes::~Processes() {
|
||||
processes_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
processes_free(m_d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ class Processes : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
explicit Processes(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Processes(QObject *parent = nullptr);
|
||||
~Processes();
|
||||
|
@ -32,6 +34,5 @@ signals:
|
|||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // PROCESSES_H
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
uint time_series_data_input(const TimeSeries::Private*, int);
|
||||
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
|
||||
{
|
||||
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
|
||||
|
@ -95,19 +95,19 @@ QModelIndex TimeSeries::parent(const QModelIndex &) 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)
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
time_series_fetch_more(d);
|
||||
time_series_fetch_more(m_d);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -132,10 +132,10 @@ QVariant TimeSeries::data(const QModelIndex &index, int role) const
|
|||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
case Qt::UserRole + 0:
|
||||
v = time_series_data_input(d, index.row());
|
||||
v = time_series_data_input(m_d, index.row());
|
||||
break;
|
||||
case Qt::UserRole + 1:
|
||||
v = time_series_data_result(d, index.row());
|
||||
v = time_series_data_result(m_d, index.row());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -144,7 +144,7 @@ QVariant TimeSeries::data(const QModelIndex &index, int role) const
|
|||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
case Qt::UserRole + 1:
|
||||
v = time_series_data_result(d, index.row());
|
||||
v = time_series_data_result(m_d, index.row());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -162,15 +162,15 @@ bool TimeSeries::setData(const QModelIndex &index, const QVariant &value, int ro
|
|||
bool set = false;
|
||||
if (index.column() == 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) {
|
||||
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 (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) {
|
||||
|
@ -189,9 +189,13 @@ extern "C" {
|
|||
void (*)(TimeSeries*));
|
||||
void time_series_free(TimeSeries::Private*);
|
||||
};
|
||||
TimeSeries::TimeSeries(bool /*owned*/, QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
m_d(0),
|
||||
m_ownsPrivate(false) {}
|
||||
TimeSeries::TimeSeries(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(time_series_new(this,
|
||||
m_d(time_series_new(this,
|
||||
[](const TimeSeries* o) {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
},
|
||||
|
@ -213,13 +217,15 @@ TimeSeries::TimeSeries(QObject *parent):
|
|||
[](TimeSeries* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &TimeSeries::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
TimeSeries::~TimeSeries() {
|
||||
time_series_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
time_series_free(m_d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ class TimeSeries : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
explicit TimeSeries(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit TimeSeries(QObject *parent = nullptr);
|
||||
~TimeSeries();
|
||||
|
@ -32,6 +34,5 @@ signals:
|
|||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // TIMESERIES_H
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
inline void treePathChanged(Tree* o)
|
||||
{
|
||||
emit o->pathChanged();
|
||||
}
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void tree_data_file_icon(const Tree::Private*, quintptr, QByteArray*, qbytearray_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) {
|
||||
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
|
||||
|
@ -99,7 +103,7 @@ QModelIndex Tree::index(int row, int column, const QModelIndex &parent) const
|
|||
if (row >= rowCount(parent)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -108,7 +112,7 @@ QModelIndex Tree::parent(const QModelIndex &index) const
|
|||
if (!index.isValid()) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -117,17 +121,17 @@ bool Tree::canFetchMore(const QModelIndex &parent) const
|
|||
if (parent.isValid() && parent.column() != 0) {
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
tree_sort(d, column, order);
|
||||
tree_sort(m_d, column, order);
|
||||
}
|
||||
Qt::ItemFlags Tree::flags(const QModelIndex &i) const
|
||||
{
|
||||
|
@ -145,26 +149,26 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DecorationRole:
|
||||
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);
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
case Qt::UserRole + 3:
|
||||
v = tree_data_file_permissions(d, index.internalId());
|
||||
v = tree_data_file_permissions(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 4:
|
||||
v = tree_data_file_size(d, index.internalId());
|
||||
v = tree_data_file_size(m_d, index.internalId());
|
||||
break;
|
||||
case Qt::UserRole + 5:
|
||||
v = tree_data_file_type(d, index.internalId());
|
||||
v = tree_data_file_type(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -172,7 +176,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 4:
|
||||
v = tree_data_file_size(d, index.internalId());
|
||||
v = tree_data_file_size(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -180,7 +184,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -189,7 +193,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 3:
|
||||
v = tree_data_file_permissions(d, index.internalId());
|
||||
v = tree_data_file_permissions(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -197,7 +201,7 @@ QVariant Tree::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole + 5:
|
||||
v = tree_data_file_type(d, index.internalId());
|
||||
v = tree_data_file_type(m_d, index.internalId());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -236,13 +240,17 @@ extern "C" {
|
|||
void tree_path_set(Tree::Private*, qstring_t);
|
||||
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):
|
||||
QAbstractItemModel(parent),
|
||||
d(tree_new(this,
|
||||
[](Tree* o) { emit o->pathChanged(); },
|
||||
m_d(tree_new(this,
|
||||
treePathChanged,
|
||||
[](const Tree* o, quintptr id, bool 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));
|
||||
} else {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
|
@ -256,7 +264,7 @@ Tree::Tree(QObject *parent):
|
|||
},
|
||||
[](Tree* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginInsertRows(QModelIndex(), first, last);
|
||||
|
@ -267,7 +275,7 @@ Tree::Tree(QObject *parent):
|
|||
},
|
||||
[](Tree* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginRemoveRows(QModelIndex(), first, last);
|
||||
|
@ -276,26 +284,28 @@ Tree::Tree(QObject *parent):
|
|||
[](Tree* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &Tree::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
Tree::~Tree() {
|
||||
tree_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
tree_free(m_d);
|
||||
}
|
||||
}
|
||||
QString Tree::path() const
|
||||
{
|
||||
QString v;
|
||||
tree_path_get(d, &v, set_qstring);
|
||||
tree_path_get(m_d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Tree::setPath(const QString& v) {
|
||||
if (v.isNull()) {
|
||||
tree_path_set_none(d);
|
||||
tree_path_set_none(m_d);
|
||||
} else {
|
||||
tree_path_set(d, v);
|
||||
tree_path_set(m_d, v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ class Tree : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL)
|
||||
explicit Tree(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Tree(QObject *parent = nullptr);
|
||||
~Tree();
|
||||
|
@ -36,7 +38,5 @@ signals:
|
|||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
void pathChanged();
|
||||
private:
|
||||
QString m_path;
|
||||
};
|
||||
#endif // TREE_H
|
||||
|
|
278
src/cpp.cpp
278
src/cpp.cpp
|
@ -16,6 +16,10 @@ QString upperInitial(const QString& name) {
|
|||
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) {
|
||||
return "WRITE set" + upperInitial(name) + " ";
|
||||
}
|
||||
|
@ -106,7 +110,7 @@ bool %1::hasChildren(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
|
||||
|
@ -124,13 +128,13 @@ QModelIndex %1::parent(const QModelIndex &) 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)
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
%2_fetch_more(d);
|
||||
%2_fetch_more(m_d);
|
||||
}
|
||||
}
|
||||
)").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) {
|
||||
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
|
||||
|
@ -172,7 +176,7 @@ QModelIndex %1::index(int row, int column, const QModelIndex &parent) const
|
|||
if (row >= rowCount(parent)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -181,7 +185,7 @@ QModelIndex %1::parent(const QModelIndex &index) const
|
|||
if (!index.isValid()) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -190,12 +194,12 @@ bool %1::canFetchMore(const QModelIndex &parent) const
|
|||
if (parent.isValid() && parent.column() != 0) {
|
||||
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)
|
||||
{
|
||||
%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));
|
||||
}
|
||||
|
@ -203,7 +207,7 @@ void %1::fetchMore(const QModelIndex &parent)
|
|||
cpp << QString(R"(
|
||||
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
|
||||
{
|
||||
|
@ -241,15 +245,15 @@ QVariant %1::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
cpp << QString(" case Qt::UserRole + %1:\n").arg(i);
|
||||
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);
|
||||
cpp << " if (!s.isNull()) v.setValue<QString>(s);\n";
|
||||
} 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);
|
||||
cpp << " if (!b.isNull()) v.setValue<QByteArray>(b);\n";
|
||||
} 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);
|
||||
}
|
||||
cpp << " break;\n";
|
||||
|
@ -295,12 +299,12 @@ bool %1::setData(const QModelIndex &index, const QVariant &value, int role)
|
|||
test += " || value.isNull()";
|
||||
}
|
||||
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;
|
||||
cpp << " } else\n";
|
||||
}
|
||||
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;
|
||||
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"(
|
||||
class %1 : public %3
|
||||
{
|
||||
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;
|
||||
private:
|
||||
Private * const d;
|
||||
)").arg(o.name, "T", baseType(o));
|
||||
)";
|
||||
for (auto p: o.properties) {
|
||||
h << QString(" Q_PROPERTY(%1 %2 READ %2 %3NOTIFY %2Changed FINAL)")
|
||||
.arg(p.type.name, p.name,
|
||||
p.write ? writeProperty(p.name) :"") << endl;
|
||||
if (p.type.type == BindingType::Object) {
|
||||
h << " " << p.type.name << "* const m_" << p.name << ";\n";
|
||||
}
|
||||
}
|
||||
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);
|
||||
~%1();
|
||||
)").arg(o.name);
|
||||
for (auto p: o.properties) {
|
||||
h << " " << p.type.name << " " << p.name << "() const;" << endl;
|
||||
if (p.write) {
|
||||
h << " void set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v);" << endl;
|
||||
if (p.type.type == BindingType::Object) {
|
||||
h << " const " << p.type.name << "* " << p.name << "() const;" << endl;
|
||||
h << " " << p.type.name << "* " << p.name << "();" << endl;
|
||||
} else {
|
||||
h << " " << p.type.name << " " << p.name << "() const;" << endl;
|
||||
if (p.write) {
|
||||
h << " void set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v);" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (baseType(o) == "QAbstractItemModel") {
|
||||
|
@ -344,20 +371,22 @@ private:
|
|||
}
|
||||
h << "signals:" << endl;
|
||||
for (auto p: o.properties) {
|
||||
h << " void " << p.name << "Changed();" << endl;
|
||||
}
|
||||
h << "private:" << endl;
|
||||
for (auto p: o.properties) {
|
||||
h << " " << p.type.name << " m_" << p.name << ";" << endl;
|
||||
if (p.type.type != BindingType::Object) {
|
||||
h << " void " << p.name << "Changed();" << endl;
|
||||
}
|
||||
}
|
||||
h << "};" << endl;
|
||||
}
|
||||
|
||||
void writeObjectCDecl(QTextStream& cpp, const Object& o) {
|
||||
const QString lcname(snakeCase(o.name));
|
||||
cpp << QString(" %1::Private* %2_new(%1*").arg(o.name, lcname);
|
||||
for (int i = 0; i < o.properties.size(); ++i) {
|
||||
cpp << QString(", void (*)(%1*)").arg(o.name);
|
||||
void constructorArgsDecl(QTextStream& cpp, const Object& o, const Configuration& conf) {
|
||||
cpp << o.name << "*";
|
||||
for (auto p: o.properties) {
|
||||
if (p.type.type == BindingType::Object) {
|
||||
cpp << QString(", ");
|
||||
constructorArgsDecl(cpp, conf.findObject(p.type.name), conf);
|
||||
} else {
|
||||
cpp << QString(", void (*)(%1*)").arg(o.name);
|
||||
}
|
||||
}
|
||||
if (o.type == ObjectType::List) {
|
||||
cpp << QString(R"(,
|
||||
|
@ -379,37 +408,21 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o) {
|
|||
void (*)(%1*, option<quintptr>, int, int),
|
||||
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));
|
||||
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) {
|
||||
cpp << QString(",\n [](%1* o) { emit o->%2Changed(); }")
|
||||
.arg(o.name, p.name);
|
||||
if (p.type.type == BindingType::Object) {
|
||||
cpp << ", m_" << p.name;
|
||||
constructorArgs(cpp, conf.findObject(p.type.name), conf);
|
||||
} else {
|
||||
cpp << ",\n " << changedF(o, p);
|
||||
}
|
||||
}
|
||||
if (o.type == ObjectType::List) {
|
||||
cpp << QString(R"(,
|
||||
|
@ -434,18 +447,13 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
|
|||
[](%1* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
)").arg(o.name);
|
||||
}
|
||||
if (o.type == ObjectType::UniformTree) {
|
||||
cpp << QString(R"(,
|
||||
[](const %1* o, quintptr id, bool 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));
|
||||
} else {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
|
@ -459,7 +467,7 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
|
|||
},
|
||||
[](%1* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
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) {
|
||||
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);
|
||||
} else {
|
||||
o->beginRemoveRows(QModelIndex(), first, last);
|
||||
|
@ -479,44 +487,115 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
|
|||
[](%1* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
connect(this, &%1::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
)").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() {
|
||||
%2_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
%2_free(m_d);
|
||||
}
|
||||
}
|
||||
)").arg(o.name, lcname);
|
||||
|
||||
for (const Property& p: o.properties) {
|
||||
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.isComplex()) {
|
||||
if (p.type.type == BindingType::Object) {
|
||||
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 << " " << base << "_get(d, &v, set_" << p.type.name.toLower()
|
||||
cpp << " " << base << "_get(m_d, &v, set_" << p.type.name.toLower()
|
||||
<< ");\n";
|
||||
cpp << " return v;\n}\n";
|
||||
} 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) {
|
||||
cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v) {" << endl;
|
||||
if (p.optional) {
|
||||
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(" %1_set(d, v);").arg(base) << endl;
|
||||
cpp << QString(" %1_set(m_d, v);").arg(base) << endl;
|
||||
cpp << QString(" }") << endl;
|
||||
} else {
|
||||
cpp << QString(" %1_set(d, v);").arg(base) << endl;
|
||||
cpp << QString(" %1_set(m_d, v);").arg(base) << endl;
|
||||
}
|
||||
cpp << "}" << endl;
|
||||
}
|
||||
|
@ -536,7 +615,12 @@ void writeHeader(const Configuration& conf) {
|
|||
)").arg(guard);
|
||||
|
||||
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);
|
||||
|
@ -591,6 +675,19 @@ namespace {
|
|||
int row;
|
||||
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*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
)").arg(conf.hFile.fileName());
|
||||
)";
|
||||
|
||||
for (auto object: conf.objects) {
|
||||
if (object.type != ObjectType::Object) {
|
||||
|
@ -609,11 +705,11 @@ void set_qbytearray(QByteArray* v, qbytearray_t* val) {
|
|||
}
|
||||
|
||||
cpp << "extern \"C\" {\n";
|
||||
writeObjectCDecl(cpp, object);
|
||||
writeObjectCDecl(cpp, object, conf);
|
||||
cpp << "};" << endl;
|
||||
}
|
||||
|
||||
for (auto object: conf.objects) {
|
||||
writeCppObject(cpp, object);
|
||||
writeCppObject(cpp, object, conf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,78 +16,76 @@ BindingTypeProperties simpleType(BindingType type, const char* name, const char*
|
|||
};
|
||||
}
|
||||
|
||||
const QMap<BindingType, BindingTypeProperties>& bindingTypeProperties() {
|
||||
static QMap<BindingType, BindingTypeProperties> p;
|
||||
QList<BindingTypeProperties>& bindingTypeProperties() {
|
||||
static QList<BindingTypeProperties> p;
|
||||
if (p.empty()) {
|
||||
QMap<BindingType, BindingTypeProperties> f;
|
||||
f.insert(BindingType::Bool, simpleType(BindingType::Bool, "bool", "true"));
|
||||
f.insert(BindingType::UChar, {
|
||||
.type = BindingType::UChar,
|
||||
.name = "quint8",
|
||||
.cppSetType = "quint8",
|
||||
.cSetType = "quint8",
|
||||
.rustType = "u8",
|
||||
.rustTypeInit = "0",
|
||||
});
|
||||
f.insert(BindingType::Int, {
|
||||
.type = BindingType::Int,
|
||||
.name = "qint32",
|
||||
.cppSetType = "qint32",
|
||||
.cSetType = "qint32",
|
||||
.rustType = "i32",
|
||||
.rustTypeInit = "0",
|
||||
});
|
||||
f.insert(BindingType::UInt, {
|
||||
.type = BindingType::UInt,
|
||||
.name = "quint32",
|
||||
.cppSetType = "uint",
|
||||
.cSetType = "uint",
|
||||
.rustType = "u32",
|
||||
.rustTypeInit = "0"
|
||||
});
|
||||
f.insert(BindingType::ULongLong, {
|
||||
.type = BindingType::ULongLong,
|
||||
.name = "quint64",
|
||||
.cppSetType = "quint64",
|
||||
.cSetType = "quint64",
|
||||
.rustType = "u64",
|
||||
.rustTypeInit = "0"
|
||||
});
|
||||
f.insert(BindingType::Float, {
|
||||
.type = BindingType::Float,
|
||||
.name = "float",
|
||||
.cppSetType = "float",
|
||||
.cSetType = "float",
|
||||
.rustType = "f32",
|
||||
.rustTypeInit = "0.0"
|
||||
});
|
||||
f.insert(BindingType::QString, {
|
||||
.type = BindingType::QString,
|
||||
.name = "QString",
|
||||
.cppSetType = "const QString&",
|
||||
.cSetType = "qstring_t",
|
||||
.rustType = "String",
|
||||
.rustTypeInit = "String::new()"
|
||||
});
|
||||
f.insert(BindingType::QByteArray, {
|
||||
.type = BindingType::QByteArray,
|
||||
.name = "QByteArray",
|
||||
.cppSetType = "const QByteArray&",
|
||||
.cSetType = "qbytearray_t",
|
||||
.rustType = "Vec<u8>",
|
||||
.rustTypeInit = "Vec::new()"
|
||||
});
|
||||
QList<BindingTypeProperties> f;
|
||||
f.append(simpleType(BindingType::Bool, "bool", "true"));
|
||||
f.append({
|
||||
.type = BindingType::UChar,
|
||||
.name = "quint8",
|
||||
.cppSetType = "quint8",
|
||||
.cSetType = "quint8",
|
||||
.rustType = "u8",
|
||||
.rustTypeInit = "0",
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::Int,
|
||||
.name = "qint32",
|
||||
.cppSetType = "qint32",
|
||||
.cSetType = "qint32",
|
||||
.rustType = "i32",
|
||||
.rustTypeInit = "0",
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::UInt,
|
||||
.name = "quint32",
|
||||
.cppSetType = "uint",
|
||||
.cSetType = "uint",
|
||||
.rustType = "u32",
|
||||
.rustTypeInit = "0"
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::ULongLong,
|
||||
.name = "quint64",
|
||||
.cppSetType = "quint64",
|
||||
.cSetType = "quint64",
|
||||
.rustType = "u64",
|
||||
.rustTypeInit = "0"
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::Float,
|
||||
.name = "float",
|
||||
.cppSetType = "float",
|
||||
.cSetType = "float",
|
||||
.rustType = "f32",
|
||||
.rustTypeInit = "0.0"
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::QString,
|
||||
.name = "QString",
|
||||
.cppSetType = "const QString&",
|
||||
.cSetType = "qstring_t",
|
||||
.rustType = "String",
|
||||
.rustTypeInit = "String::new()"
|
||||
});
|
||||
f.append({
|
||||
.type = BindingType::QByteArray,
|
||||
.name = "QByteArray",
|
||||
.cppSetType = "const QByteArray&",
|
||||
.cSetType = "qbytearray_t",
|
||||
.rustType = "Vec<u8>",
|
||||
.rustTypeInit = "Vec::new()"
|
||||
});
|
||||
p = f;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
BindingTypeProperties parseBindingType(const QString& value) {
|
||||
QMapIterator<BindingType, BindingTypeProperties> i(bindingTypeProperties());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (value == i.value().name) {
|
||||
return i.value();
|
||||
for (auto type: bindingTypeProperties()) {
|
||||
if (value == type.name) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
QTextStream err(stderr);
|
||||
|
@ -206,7 +204,16 @@ parseConfiguration(const QString& path) {
|
|||
c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h");
|
||||
const QJsonObject& object = o.value("objects").toObject();
|
||||
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();
|
||||
c.rustdir = QDir(base.filePath(rust.value("dir").toString()));
|
||||
|
|
224
src/rust.cpp
224
src/rust.cpp
|
@ -28,7 +28,86 @@ QString rustTypeInit(const T& p)
|
|||
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));
|
||||
r << QString(R"(
|
||||
pub struct %1QObject {}
|
||||
|
@ -38,6 +117,9 @@ pub struct %1Emitter {
|
|||
qobject: Arc<Mutex<*const %1QObject>>,
|
||||
)").arg(o.name);
|
||||
for (const Property& p: o.properties) {
|
||||
if (p.type.type == BindingType::Object) {
|
||||
continue;
|
||||
}
|
||||
r << QString(" %2_changed: fn(*const %1QObject),\n")
|
||||
.arg(o.name, snakeCase(p.name));
|
||||
}
|
||||
|
@ -58,6 +140,9 @@ impl %1Emitter {
|
|||
}
|
||||
)").arg(o.name);
|
||||
for (const Property& p: o.properties) {
|
||||
if (p.type.type == BindingType::Object) {
|
||||
continue;
|
||||
}
|
||||
r << QString(R"( pub fn %1_changed(&self) {
|
||||
let ptr = *self.qobject.lock().unwrap();
|
||||
if !ptr.is_null() {
|
||||
|
@ -133,14 +218,25 @@ impl %1%2 {
|
|||
r << QString(R"(}
|
||||
|
||||
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;
|
||||
)").arg(o.name, modelStruct);
|
||||
)").arg(o.name);
|
||||
for (const Property& p: o.properties) {
|
||||
const QString lc(snakeCase(p.name));
|
||||
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 (p.type.type == BindingType::Object) {
|
||||
r << QString(" fn get_%1(&self) -> &%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) {
|
||||
|
@ -173,75 +269,30 @@ pub trait %1Trait {
|
|||
r << QString(R"(}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn %2_new(qobject: *const %1QObject)").arg(o.name, lcname);
|
||||
for (const Property& p: o.properties) {
|
||||
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);
|
||||
}
|
||||
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))
|
||||
pub extern "C" fn %1_new()").arg(lcname);
|
||||
rConstructorArgsDecl(r, lcname, o, conf);
|
||||
r << QString(")\n -> *mut %1 {\n").arg(o.name);
|
||||
rConstructorArgs(r, lcname, o, conf);
|
||||
r << QString(R"( Box::into_raw(Box::new(d_%2))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn %2_free(ptr: *mut %1) {
|
||||
Box::from_raw(ptr).emit().clear();
|
||||
}
|
||||
)").arg(o.name, lcname, model);
|
||||
)").arg(o.name, lcname);
|
||||
for (const Property& p: o.properties) {
|
||||
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
|
||||
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"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn %2_get(ptr: *const %1,
|
||||
|
@ -589,7 +640,7 @@ use %1::*;
|
|||
writeRustTypes(conf, r);
|
||||
|
||||
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 << "}\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 {
|
||||
fn create(emit: %1Emitter%2) -> %1 {
|
||||
%1 {
|
||||
|
@ -631,7 +687,11 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
|
|||
}
|
||||
for (const Property& p: o.properties) {
|
||||
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) {
|
||||
r << QString(" list: vec![%1Item::default(); 10],\n")
|
||||
|
@ -645,19 +705,29 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
|
|||
)").arg(o.name);
|
||||
for (const Property& p: o.properties) {
|
||||
const QString lc(snakeCase(p.name));
|
||||
r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustType(p));
|
||||
if (p.type.isComplex()) {
|
||||
r << QString(" self.%1.clone()\n").arg(lc);
|
||||
if (p.type.type == BindingType::Object) {
|
||||
r << QString(R"( fn get_%1(&self) -> &%2 {
|
||||
&self.%1
|
||||
}
|
||||
fn get_mut_%1(&mut self) -> &mut %2 {
|
||||
&mut self.%1
|
||||
}
|
||||
)").arg(lc, rustType(p));
|
||||
} else {
|
||||
r << QString(" self.%1\n").arg(lc);
|
||||
}
|
||||
r << " }\n";
|
||||
if (p.write) {
|
||||
r << QString(R"( fn set_%1(&mut self, value: %2) {
|
||||
r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustType(p));
|
||||
if (p.type.isComplex()) {
|
||||
r << QString(" self.%1.clone()\n").arg(lc);
|
||||
} else {
|
||||
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.emit.%1_changed();
|
||||
}
|
||||
)").arg(lc, rustType(p));
|
||||
)").arg(lc, rustType(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.type == ObjectType::List) {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <QList>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
#include <QCoreApplication>
|
||||
|
||||
enum class ObjectType {
|
||||
Object,
|
||||
|
@ -18,7 +20,8 @@ enum class BindingType {
|
|||
ULongLong,
|
||||
Float,
|
||||
QString,
|
||||
QByteArray
|
||||
QByteArray,
|
||||
Object,
|
||||
};
|
||||
|
||||
struct BindingTypeProperties {
|
||||
|
@ -54,6 +57,14 @@ struct Object {
|
|||
QList<Property> properties;
|
||||
QList<ItemProperty> itemProperties;
|
||||
int columnCount;
|
||||
bool containsObject() {
|
||||
for (auto p: properties) {
|
||||
if (p.type.type == BindingType::Object) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct Configuration {
|
||||
|
@ -64,5 +75,17 @@ struct Configuration {
|
|||
QString implementationModule;
|
||||
QList<Object> objects;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -65,3 +65,4 @@ rust_test(test_object rust_object)
|
|||
rust_test(test_object_types rust_object_types)
|
||||
rust_test(test_list rust_list)
|
||||
rust_test(test_tree rust_tree)
|
||||
rust_test(test_objects rust_objects)
|
||||
|
|
|
@ -139,7 +139,7 @@ pub trait PersonsTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
begin_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),
|
||||
end_remove_rows: fn(*const PersonsQObject))
|
||||
-> *mut Persons {
|
||||
let emit = PersonsEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let persons_emit = PersonsEmitter {
|
||||
qobject: Arc::new(Mutex::new(persons)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = PersonsList {
|
||||
qobject: qobject,
|
||||
qobject: persons,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = Persons::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_persons = Persons::create(persons_emit, model);
|
||||
Box::into_raw(Box::new(d_persons))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -25,4 +25,4 @@ impl PersonTrait for Person {
|
|||
self.user_name = value;
|
||||
self.emit.user_name_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,15 +68,15 @@ pub trait PersonTrait {
|
|||
}
|
||||
|
||||
#[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))
|
||||
-> *mut Person {
|
||||
let emit = PersonEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let person_emit = PersonEmitter {
|
||||
qobject: Arc::new(Mutex::new(person)),
|
||||
user_name_changed: user_name_changed,
|
||||
};
|
||||
let d = Person::create(emit);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_person = Person::create(person_emit);
|
||||
Box::into_raw(Box::new(d_person))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -39,53 +39,53 @@ impl ObjectTrait for Object {
|
|||
self.boolean = value;
|
||||
self.emit.boolean_changed();
|
||||
}
|
||||
fn get_bytearray(&self) -> Vec<u8> {
|
||||
fn get_bytearray(&self) -> Vec<u8> {
|
||||
self.bytearray.clone()
|
||||
}
|
||||
fn set_bytearray(&mut self, value: Vec<u8>) {
|
||||
self.bytearray = value;
|
||||
self.emit.bytearray_changed();
|
||||
}
|
||||
fn get_integer(&self) -> i32 {
|
||||
fn get_integer(&self) -> i32 {
|
||||
self.integer
|
||||
}
|
||||
fn set_integer(&mut self, value: i32) {
|
||||
self.integer = value;
|
||||
self.emit.integer_changed();
|
||||
}
|
||||
fn get_optional_bytearray(&self) -> Option<Vec<u8>> {
|
||||
fn get_optional_bytearray(&self) -> Option<Vec<u8>> {
|
||||
self.optional_bytearray.clone()
|
||||
}
|
||||
fn set_optional_bytearray(&mut self, value: Option<Vec<u8>>) {
|
||||
self.optional_bytearray = value;
|
||||
self.emit.optional_bytearray_changed();
|
||||
}
|
||||
fn get_optional_string(&self) -> Option<String> {
|
||||
fn get_optional_string(&self) -> Option<String> {
|
||||
self.optional_string.clone()
|
||||
}
|
||||
fn set_optional_string(&mut self, value: Option<String>) {
|
||||
self.optional_string = value;
|
||||
self.emit.optional_string_changed();
|
||||
}
|
||||
fn get_string(&self) -> String {
|
||||
fn get_string(&self) -> String {
|
||||
self.string.clone()
|
||||
}
|
||||
fn set_string(&mut self, value: String) {
|
||||
self.string = value;
|
||||
self.emit.string_changed();
|
||||
}
|
||||
fn get_u64(&self) -> u64 {
|
||||
fn get_u64(&self) -> u64 {
|
||||
self.u64
|
||||
}
|
||||
fn set_u64(&mut self, value: u64) {
|
||||
self.u64 = value;
|
||||
self.emit.u64_changed();
|
||||
}
|
||||
fn get_uinteger(&self) -> u32 {
|
||||
fn get_uinteger(&self) -> u32 {
|
||||
self.uinteger
|
||||
}
|
||||
fn set_uinteger(&mut self, value: u32) {
|
||||
self.uinteger = value;
|
||||
self.emit.uinteger_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ pub trait ObjectTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
bytearray_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),
|
||||
uinteger_changed: fn(*const ObjectQObject))
|
||||
-> *mut Object {
|
||||
let emit = ObjectEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let object_emit = ObjectEmitter {
|
||||
qobject: Arc::new(Mutex::new(object)),
|
||||
boolean_changed: boolean_changed,
|
||||
bytearray_changed: bytearray_changed,
|
||||
integer_changed: integer_changed,
|
||||
|
@ -198,8 +198,8 @@ pub extern "C" fn object_new(qobject: *const ObjectQObject,
|
|||
u64_changed: u64_changed,
|
||||
uinteger_changed: uinteger_changed,
|
||||
};
|
||||
let d = Object::create(emit);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_object = Object::create(object_emit);
|
||||
Box::into_raw(Box::new(d_object))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "rust_objects"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
libc = "*"
|
||||
|
||||
[lib]
|
||||
name = "rust"
|
||||
crate-type = ["staticlib"]
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
extern crate libc;
|
||||
|
||||
pub mod interface;
|
||||
mod implementation;
|
|
@ -142,7 +142,7 @@ pub trait PersonsTrait {
|
|||
}
|
||||
|
||||
#[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),
|
||||
begin_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),
|
||||
end_remove_rows: fn(*const PersonsQObject))
|
||||
-> *mut Persons {
|
||||
let emit = PersonsEmitter {
|
||||
qobject: Arc::new(Mutex::new(qobject)),
|
||||
let persons_emit = PersonsEmitter {
|
||||
qobject: Arc::new(Mutex::new(persons)),
|
||||
new_data_ready: new_data_ready,
|
||||
};
|
||||
let model = PersonsUniformTree {
|
||||
qobject: qobject,
|
||||
qobject: persons,
|
||||
begin_reset_model: begin_reset_model,
|
||||
end_reset_model: end_reset_model,
|
||||
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,
|
||||
end_remove_rows: end_remove_rows,
|
||||
};
|
||||
let d = Persons::create(emit, model);
|
||||
Box::into_raw(Box::new(d))
|
||||
let d_persons = Persons::create(persons_emit, model);
|
||||
Box::into_raw(Box::new(d_persons))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void persons_data_user_name(const Persons::Private*, int, QString*, qstring_set);
|
||||
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
|
||||
{
|
||||
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
|
||||
|
@ -93,19 +93,19 @@ QModelIndex Persons::parent(const QModelIndex &) 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)
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
persons_fetch_more(d);
|
||||
persons_fetch_more(m_d);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ QVariant Persons::data(const QModelIndex &index, int role) const
|
|||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ bool Persons::setData(const QModelIndex &index, const QVariant &value, int role)
|
|||
bool set = false;
|
||||
if (index.column() == 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) {
|
||||
|
@ -164,9 +164,13 @@ extern "C" {
|
|||
void (*)(Persons*));
|
||||
void persons_free(Persons::Private*);
|
||||
};
|
||||
Persons::Persons(bool /*owned*/, QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
m_d(0),
|
||||
m_ownsPrivate(false) {}
|
||||
Persons::Persons(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(persons_new(this,
|
||||
m_d(persons_new(this,
|
||||
[](const Persons* o) {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
},
|
||||
|
@ -188,13 +192,15 @@ Persons::Persons(QObject *parent):
|
|||
[](Persons* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
Persons::~Persons() {
|
||||
persons_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
persons_free(m_d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ class Persons : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
explicit Persons(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Persons(QObject *parent = nullptr);
|
||||
~Persons();
|
||||
|
@ -32,6 +34,5 @@ signals:
|
|||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // TEST_LIST_RUST_H
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
inline void personUserNameChanged(Person* o)
|
||||
{
|
||||
emit o->userNameChanged();
|
||||
}
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
Person::Private* person_new(Person*, void (*)(Person*));
|
||||
void person_free(Person::Private*);
|
||||
void person_user_name_get(const Person::Private*, QString*, qstring_set);
|
||||
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):
|
||||
QObject(parent),
|
||||
d(person_new(this,
|
||||
[](Person* o) { emit o->userNameChanged(); })) {}
|
||||
m_d(person_new(this,
|
||||
personUserNameChanged)),
|
||||
m_ownsPrivate(true) {
|
||||
}
|
||||
|
||||
Person::~Person() {
|
||||
person_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
person_free(m_d);
|
||||
}
|
||||
}
|
||||
QString Person::userName() const
|
||||
{
|
||||
QString v;
|
||||
person_user_name_get(d, &v, set_qstring);
|
||||
person_user_name_get(m_d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Person::setUserName(const QString& v) {
|
||||
person_user_name_set(d, v);
|
||||
person_user_name_set(m_d, v);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ class Person : public QObject
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged FINAL)
|
||||
explicit Person(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Person(QObject *parent = nullptr);
|
||||
~Person();
|
||||
|
@ -20,7 +22,5 @@ public:
|
|||
void setUserName(const QString& v);
|
||||
signals:
|
||||
void userNameChanged();
|
||||
private:
|
||||
QString m_userName;
|
||||
};
|
||||
#endif // TEST_OBJECT_RUST_H
|
||||
|
|
|
@ -44,6 +44,39 @@ namespace {
|
|||
int row;
|
||||
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*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
Object::Private* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*));
|
||||
void object_free(Object::Private*);
|
||||
|
@ -76,90 +108,98 @@ extern "C" {
|
|||
quint32 object_uinteger_get(const Object::Private*);
|
||||
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):
|
||||
QObject(parent),
|
||||
d(object_new(this,
|
||||
[](Object* o) { emit o->booleanChanged(); },
|
||||
[](Object* o) { emit o->bytearrayChanged(); },
|
||||
[](Object* o) { emit o->integerChanged(); },
|
||||
[](Object* o) { emit o->optionalBytearrayChanged(); },
|
||||
[](Object* o) { emit o->optionalStringChanged(); },
|
||||
[](Object* o) { emit o->stringChanged(); },
|
||||
[](Object* o) { emit o->u64Changed(); },
|
||||
[](Object* o) { emit o->uintegerChanged(); })) {}
|
||||
m_d(object_new(this,
|
||||
objectBooleanChanged,
|
||||
objectBytearrayChanged,
|
||||
objectIntegerChanged,
|
||||
objectOptionalBytearrayChanged,
|
||||
objectOptionalStringChanged,
|
||||
objectStringChanged,
|
||||
objectU64Changed,
|
||||
objectUintegerChanged)),
|
||||
m_ownsPrivate(true) {
|
||||
}
|
||||
|
||||
Object::~Object() {
|
||||
object_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
object_free(m_d);
|
||||
}
|
||||
}
|
||||
bool Object::boolean() const
|
||||
{
|
||||
return object_boolean_get(d);
|
||||
return object_boolean_get(m_d);
|
||||
}
|
||||
void Object::setBoolean(bool v) {
|
||||
object_boolean_set(d, v);
|
||||
object_boolean_set(m_d, v);
|
||||
}
|
||||
QByteArray Object::bytearray() const
|
||||
{
|
||||
QByteArray v;
|
||||
object_bytearray_get(d, &v, set_qbytearray);
|
||||
object_bytearray_get(m_d, &v, set_qbytearray);
|
||||
return v;
|
||||
}
|
||||
void Object::setBytearray(const QByteArray& v) {
|
||||
object_bytearray_set(d, v);
|
||||
object_bytearray_set(m_d, v);
|
||||
}
|
||||
qint32 Object::integer() const
|
||||
{
|
||||
return object_integer_get(d);
|
||||
return object_integer_get(m_d);
|
||||
}
|
||||
void Object::setInteger(qint32 v) {
|
||||
object_integer_set(d, v);
|
||||
object_integer_set(m_d, v);
|
||||
}
|
||||
QByteArray Object::optionalBytearray() const
|
||||
{
|
||||
QByteArray v;
|
||||
object_optional_bytearray_get(d, &v, set_qbytearray);
|
||||
object_optional_bytearray_get(m_d, &v, set_qbytearray);
|
||||
return v;
|
||||
}
|
||||
void Object::setOptionalBytearray(const QByteArray& v) {
|
||||
if (v.isNull()) {
|
||||
object_optional_bytearray_set_none(d);
|
||||
object_optional_bytearray_set_none(m_d);
|
||||
} else {
|
||||
object_optional_bytearray_set(d, v);
|
||||
object_optional_bytearray_set(m_d, v);
|
||||
}
|
||||
}
|
||||
QString Object::optionalString() const
|
||||
{
|
||||
QString v;
|
||||
object_optional_string_get(d, &v, set_qstring);
|
||||
object_optional_string_get(m_d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Object::setOptionalString(const QString& v) {
|
||||
if (v.isNull()) {
|
||||
object_optional_string_set_none(d);
|
||||
object_optional_string_set_none(m_d);
|
||||
} else {
|
||||
object_optional_string_set(d, v);
|
||||
object_optional_string_set(m_d, v);
|
||||
}
|
||||
}
|
||||
QString Object::string() const
|
||||
{
|
||||
QString v;
|
||||
object_string_get(d, &v, set_qstring);
|
||||
object_string_get(m_d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Object::setString(const QString& v) {
|
||||
object_string_set(d, v);
|
||||
object_string_set(m_d, v);
|
||||
}
|
||||
quint64 Object::u64() const
|
||||
{
|
||||
return object_u64_get(d);
|
||||
return object_u64_get(m_d);
|
||||
}
|
||||
void Object::setU64(quint64 v) {
|
||||
object_u64_set(d, v);
|
||||
object_u64_set(m_d, v);
|
||||
}
|
||||
quint32 Object::uinteger() const
|
||||
{
|
||||
return object_uinteger_get(d);
|
||||
return object_uinteger_get(m_d);
|
||||
}
|
||||
void Object::setUinteger(uint v) {
|
||||
object_uinteger_set(d, v);
|
||||
object_uinteger_set(m_d, v);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ class Object : public QObject
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
Q_PROPERTY(bool boolean READ boolean WRITE setBoolean NOTIFY booleanChanged FINAL)
|
||||
Q_PROPERTY(QByteArray bytearray READ bytearray WRITE setBytearray NOTIFY bytearrayChanged 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(quint64 u64 READ u64 WRITE setU64 NOTIFY u64Changed FINAL)
|
||||
Q_PROPERTY(quint32 uinteger READ uinteger WRITE setUinteger NOTIFY uintegerChanged FINAL)
|
||||
explicit Object(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Object(QObject *parent = nullptr);
|
||||
~Object();
|
||||
|
@ -48,14 +50,5 @@ signals:
|
|||
void stringChanged();
|
||||
void u64Changed();
|
||||
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
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -44,6 +44,7 @@ namespace {
|
|||
int row;
|
||||
quintptr id;
|
||||
};
|
||||
|
||||
}
|
||||
typedef void (*qstring_set)(QString*, qstring_t*);
|
||||
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) {
|
||||
*v = *val;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void persons_data_user_name(const Persons::Private*, quintptr, QString*, qstring_set);
|
||||
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) {
|
||||
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
|
||||
|
@ -95,7 +95,7 @@ QModelIndex Persons::index(int row, int column, const QModelIndex &parent) const
|
|||
if (row >= rowCount(parent)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ QModelIndex Persons::parent(const QModelIndex &index) const
|
|||
if (!index.isValid()) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -113,17 +113,17 @@ bool Persons::canFetchMore(const QModelIndex &parent) const
|
|||
if (parent.isValid() && parent.column() != 0) {
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
persons_sort(d, column, order);
|
||||
persons_sort(m_d, column, order);
|
||||
}
|
||||
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::EditRole:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ bool Persons::setData(const QModelIndex &index, const QVariant &value, int role)
|
|||
bool set = false;
|
||||
if (index.column() == 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) {
|
||||
|
@ -182,12 +182,16 @@ extern "C" {
|
|||
void (*)(Persons*));
|
||||
void persons_free(Persons::Private*);
|
||||
};
|
||||
Persons::Persons(bool /*owned*/, QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
m_d(0),
|
||||
m_ownsPrivate(false) {}
|
||||
Persons::Persons(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(persons_new(this,
|
||||
m_d(persons_new(this,
|
||||
[](const Persons* o, quintptr id, bool 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));
|
||||
} else {
|
||||
emit o->newDataReady(QModelIndex());
|
||||
|
@ -201,7 +205,7 @@ Persons::Persons(QObject *parent):
|
|||
},
|
||||
[](Persons* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginInsertRows(QModelIndex(), first, last);
|
||||
|
@ -212,7 +216,7 @@ Persons::Persons(QObject *parent):
|
|||
},
|
||||
[](Persons* o, option<quintptr> id, int first, int last) {
|
||||
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);
|
||||
} else {
|
||||
o->beginRemoveRows(QModelIndex(), first, last);
|
||||
|
@ -221,13 +225,15 @@ Persons::Persons(QObject *parent):
|
|||
[](Persons* o) {
|
||||
o->endRemoveRows();
|
||||
}
|
||||
)) {
|
||||
)),
|
||||
m_ownsPrivate(true) {
|
||||
connect(this, &Persons::newDataReady, this, [this](const QModelIndex& i) {
|
||||
fetchMore(i);
|
||||
}, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
||||
Persons::~Persons() {
|
||||
persons_free(d);
|
||||
if (m_ownsPrivate) {
|
||||
persons_free(m_d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ class Persons : public QAbstractItemModel
|
|||
public:
|
||||
class Private;
|
||||
private:
|
||||
Private * const d;
|
||||
Private * m_d;
|
||||
bool m_ownsPrivate;
|
||||
explicit Persons(bool owned, QObject *parent);
|
||||
public:
|
||||
explicit Persons(QObject *parent = nullptr);
|
||||
~Persons();
|
||||
|
@ -32,6 +34,5 @@ signals:
|
|||
// new data is ready to be made available to the model with fetchMore()
|
||||
void newDataReady(const QModelIndex &parent) const;
|
||||
signals:
|
||||
private:
|
||||
};
|
||||
#endif // TEST_TREE_RUST_H
|
||||
|
|
Loading…
Reference in New Issue