diff --git a/common-rust/src/implementation.rs b/common-rust/src/implementation.rs index f41ddab..9bbe0d0 100644 --- a/common-rust/src/implementation.rs +++ b/common-rust/src/implementation.rs @@ -5,6 +5,7 @@ use std::fs::read_dir; use std::path::PathBuf; use std::ffi::OsString; use std::default::Default; +use std::thread; pub struct Hello { emit: HelloEmitter, @@ -105,6 +106,10 @@ impl RGeneralItemModel { }; if self.entries[p].children.is_none() { self.retrieve(p); + let emit = self.emit.clone(); + thread::spawn(move || { + emit.new_data_ready(); + }); } p } @@ -150,6 +155,9 @@ impl RItemModelTrait for RGeneralItemModel { entries: vec![none, root] } } + fn emit(&self) -> &RItemModelEmitter { + &self.emit + } fn column_count(&mut self, _: QModelIndex) -> c_int { 2 } diff --git a/common-rust/src/interface.rs b/common-rust/src/interface.rs index f15ed6d..39d57ce 100644 --- a/common-rust/src/interface.rs +++ b/common-rust/src/interface.rs @@ -1,6 +1,8 @@ use std::slice; use libc::{c_int, uint16_t, size_t, c_void}; use types::*; +use std::sync::{Arc, Mutex}; +use std::ptr::null; use implementation::*; @@ -53,17 +55,32 @@ pub extern fn hello_get(ptr: *mut Hello) -> QString { QString::from(hello.get_hello()) } + pub struct RItemModelQObject {} +#[derive (Clone)] pub struct RItemModelEmitter { - qobject: *const RItemModelQObject + qobject: Arc>, + new_data_ready: fn (*const RItemModelQObject) } +unsafe impl Send for RItemModelEmitter {} + impl RItemModelEmitter { + pub fn new_data_ready(&self) { + let ptr = *self.qobject.lock().unwrap(); + if !ptr.is_null() { + (self.new_data_ready)(ptr); + } + } + fn clear(&self) { + *self.qobject.lock().unwrap() = null(); + } } pub trait RItemModelTrait { fn create(emit: RItemModelEmitter, root: T) -> Self; + fn emit(&self) -> &RItemModelEmitter; fn column_count(&mut self, parent: QModelIndex) -> c_int; fn row_count(&mut self, parent: QModelIndex) -> c_int; fn index(&mut self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex; @@ -72,9 +89,10 @@ pub trait RItemModelTrait { } #[no_mangle] -pub extern fn ritemmodel_new(qobject: *const RItemModelQObject) -> *mut RItemModel { +pub extern fn ritemmodel_new(qobject: *const RItemModelQObject, new_data_ready: fn(*const RItemModelQObject)) -> *mut RItemModel { let emit = RItemModelEmitter { - qobject: qobject + qobject: Arc::new(Mutex::new(qobject)), + new_data_ready: new_data_ready }; let ritemmodel = RItemModel::create(emit, DirEntry::create("/")); Box::into_raw(Box::new(ritemmodel)) @@ -82,8 +100,8 @@ pub extern fn ritemmodel_new(qobject: *const RItemModelQObject) -> *mut RItemMod #[no_mangle] pub extern fn ritemmodel_free(ptr: *mut RItemModel) { - if ptr.is_null() { return } - unsafe { Box::from_raw(ptr); } + let ritemmodel = unsafe { Box::from_raw(ptr) }; + ritemmodel.emit().clear(); } #[no_mangle] diff --git a/src/RMailObject.cpp b/src/RMailObject.cpp index 263f918..e1a2fe5 100644 --- a/src/RMailObject.cpp +++ b/src/RMailObject.cpp @@ -5,7 +5,7 @@ #include namespace { - typedef struct { + struct qbytearray_t { private: const char* data; int len; @@ -13,7 +13,7 @@ namespace { operator QByteArray() const { return QByteArray(data, len); } - } qbytearray_t; + }; struct qstring_t { private: const char* data; @@ -23,16 +23,18 @@ namespace { return QString::fromUtf8(data, len); } }; - typedef struct { + struct qmodelindex_t { int row; int column; uint64_t id; - } qmodelindex_t; - typedef struct qvariant_t { + qmodelindex_t(const QModelIndex& m): + row(m.row()), column(m.column()), id(m.internalId()) {} + }; + struct qvariant_t { unsigned int type; int value; const char* data; - } qvariant_t; + }; QVariant variant(const qvariant_t& v) { switch (v.type) { case QVariant::Bool: return QVariant((bool)v.value); @@ -67,7 +69,7 @@ extern "C" { void hello_set(RMailObjectInterface*, const uint16_t *, size_t); qstring_t hello_get(RMailObjectInterface*); - RItemModelInterface* ritemmodel_new(void*); + RItemModelInterface* ritemmodel_new(void*, void (*)(RItemModel*)); void ritemmodel_free(RItemModelInterface*); int ritemmodel_column_count(RItemModelInterface*, qmodelindex_t parent); int ritemmodel_row_count(RItemModelInterface*, qmodelindex_t parent); @@ -111,31 +113,30 @@ RMailObject::setTree(const QVariantMap& tree) { RItemModel::RItemModel(QObject *parent): QAbstractItemModel(parent), - d(ritemmodel_new(this)) + d(ritemmodel_new(this, + [](RItemModel* o) { emit o->newDataReady(); } + )) { + connect(this, &RItemModel::newDataReady, this, &RItemModel::handleNewData, + Qt::QueuedConnection); + qDebug() << sizeof(QObject) << sizeof(RItemModel); } RItemModel::~RItemModel() { ritemmodel_free(d); } +void RItemModel::handleNewData() { + qDebug() << "new data!"; +} + int RItemModel::columnCount(const QModelIndex &parent) const { - const qmodelindex_t p = { - .row = parent.row(), - .column = parent.column(), - .id = parent.internalId() - }; - return ritemmodel_column_count(d, p); + return ritemmodel_column_count(d, parent); } int RItemModel::rowCount(const QModelIndex &parent) const { - const qmodelindex_t p = { - .row = parent.row(), - .column = parent.column(), - .id = parent.internalId() - }; - return ritemmodel_row_count(d, p); + return ritemmodel_row_count(d, parent); } void set_variant(void* v, qvariant_t* val) { @@ -144,23 +145,13 @@ void set_variant(void* v, qvariant_t* val) { QVariant RItemModel::data(const QModelIndex &index, int role) const { - const qmodelindex_t i = { - .row = index.row(), - .column = index.column(), - .id = index.internalId() - }; QVariant v; - ritemmodel_data(d, i, role, &v, set_variant); + ritemmodel_data(d, index, role, &v, set_variant); return v; } QModelIndex RItemModel::index(int row, int column, const QModelIndex &parent) const { - const qmodelindex_t p = { - .row = parent.row(), - .column = parent.column(), - .id = parent.internalId() - }; - const qmodelindex_t i = ritemmodel_index(d, row, column, p); + const qmodelindex_t i = ritemmodel_index(d, row, column, parent); return i.id ?createIndex(i.row, i.column, i.id) :QModelIndex(); } QModelIndex RItemModel::parent(const QModelIndex &index) const @@ -168,11 +159,6 @@ QModelIndex RItemModel::parent(const QModelIndex &index) const if (!index.isValid()) { return QModelIndex(); } - const qmodelindex_t i = { - .row = index.row(), - .column = index.column(), - .id = index.internalId() - }; - const qmodelindex_t parent = ritemmodel_parent(d, i); + const qmodelindex_t parent = ritemmodel_parent(d, index); return parent.id ?createIndex(parent.row, parent.column, parent.id) :QModelIndex(); } diff --git a/src/RMailObject.h b/src/RMailObject.h index f1ae001..34c12ce 100644 --- a/src/RMailObject.h +++ b/src/RMailObject.h @@ -45,6 +45,12 @@ public: QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent) const; + +private slots: + void handleNewData(); + +signals: + void newDataReady(); }; #endif // RMAIL_OBJECT_H