Make it possible to send signals from rust threads

master
Jos van den Oever 2017-08-05 11:37:01 +02:00
parent e3d9df5813
commit 5a52613025
4 changed files with 61 additions and 43 deletions

View File

@ -5,6 +5,7 @@ use std::fs::read_dir;
use std::path::PathBuf; use std::path::PathBuf;
use std::ffi::OsString; use std::ffi::OsString;
use std::default::Default; use std::default::Default;
use std::thread;
pub struct Hello { pub struct Hello {
emit: HelloEmitter, emit: HelloEmitter,
@ -105,6 +106,10 @@ impl<T: Item> RGeneralItemModel<T> {
}; };
if self.entries[p].children.is_none() { if self.entries[p].children.is_none() {
self.retrieve(p); self.retrieve(p);
let emit = self.emit.clone();
thread::spawn(move || {
emit.new_data_ready();
});
} }
p p
} }
@ -150,6 +155,9 @@ impl<T: Item> RItemModelTrait<T> for RGeneralItemModel<T> {
entries: vec![none, root] entries: vec![none, root]
} }
} }
fn emit(&self) -> &RItemModelEmitter {
&self.emit
}
fn column_count(&mut self, _: QModelIndex) -> c_int { fn column_count(&mut self, _: QModelIndex) -> c_int {
2 2
} }

View File

@ -1,6 +1,8 @@
use std::slice; use std::slice;
use libc::{c_int, uint16_t, size_t, c_void}; use libc::{c_int, uint16_t, size_t, c_void};
use types::*; use types::*;
use std::sync::{Arc, Mutex};
use std::ptr::null;
use implementation::*; use implementation::*;
@ -53,17 +55,32 @@ pub extern fn hello_get(ptr: *mut Hello) -> QString {
QString::from(hello.get_hello()) QString::from(hello.get_hello())
} }
pub struct RItemModelQObject {} pub struct RItemModelQObject {}
#[derive (Clone)]
pub struct RItemModelEmitter { pub struct RItemModelEmitter {
qobject: *const RItemModelQObject qobject: Arc<Mutex<*const RItemModelQObject>>,
new_data_ready: fn (*const RItemModelQObject)
} }
unsafe impl Send for RItemModelEmitter {}
impl 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<T> { pub trait RItemModelTrait<T> {
fn create(emit: RItemModelEmitter, root: T) -> Self; fn create(emit: RItemModelEmitter, root: T) -> Self;
fn emit(&self) -> &RItemModelEmitter;
fn column_count(&mut self, parent: QModelIndex) -> c_int; fn column_count(&mut self, parent: QModelIndex) -> c_int;
fn row_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; fn index(&mut self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex;
@ -72,9 +89,10 @@ pub trait RItemModelTrait<T> {
} }
#[no_mangle] #[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 { let emit = RItemModelEmitter {
qobject: qobject qobject: Arc::new(Mutex::new(qobject)),
new_data_ready: new_data_ready
}; };
let ritemmodel = RItemModel::create(emit, DirEntry::create("/")); let ritemmodel = RItemModel::create(emit, DirEntry::create("/"));
Box::into_raw(Box::new(ritemmodel)) Box::into_raw(Box::new(ritemmodel))
@ -82,8 +100,8 @@ pub extern fn ritemmodel_new(qobject: *const RItemModelQObject) -> *mut RItemMod
#[no_mangle] #[no_mangle]
pub extern fn ritemmodel_free(ptr: *mut RItemModel) { pub extern fn ritemmodel_free(ptr: *mut RItemModel) {
if ptr.is_null() { return } let ritemmodel = unsafe { Box::from_raw(ptr) };
unsafe { Box::from_raw(ptr); } ritemmodel.emit().clear();
} }
#[no_mangle] #[no_mangle]

View File

@ -5,7 +5,7 @@
#include <unistd.h> #include <unistd.h>
namespace { namespace {
typedef struct { struct qbytearray_t {
private: private:
const char* data; const char* data;
int len; int len;
@ -13,7 +13,7 @@ namespace {
operator QByteArray() const { operator QByteArray() const {
return QByteArray(data, len); return QByteArray(data, len);
} }
} qbytearray_t; };
struct qstring_t { struct qstring_t {
private: private:
const char* data; const char* data;
@ -23,16 +23,18 @@ namespace {
return QString::fromUtf8(data, len); return QString::fromUtf8(data, len);
} }
}; };
typedef struct { struct qmodelindex_t {
int row; int row;
int column; int column;
uint64_t id; uint64_t id;
} qmodelindex_t; qmodelindex_t(const QModelIndex& m):
typedef struct qvariant_t { row(m.row()), column(m.column()), id(m.internalId()) {}
};
struct qvariant_t {
unsigned int type; unsigned int type;
int value; int value;
const char* data; const char* data;
} qvariant_t; };
QVariant variant(const qvariant_t& v) { QVariant variant(const qvariant_t& v) {
switch (v.type) { switch (v.type) {
case QVariant::Bool: return QVariant((bool)v.value); case QVariant::Bool: return QVariant((bool)v.value);
@ -67,7 +69,7 @@ extern "C" {
void hello_set(RMailObjectInterface*, const uint16_t *, size_t); void hello_set(RMailObjectInterface*, const uint16_t *, size_t);
qstring_t hello_get(RMailObjectInterface*); qstring_t hello_get(RMailObjectInterface*);
RItemModelInterface* ritemmodel_new(void*); RItemModelInterface* ritemmodel_new(void*, void (*)(RItemModel*));
void ritemmodel_free(RItemModelInterface*); void ritemmodel_free(RItemModelInterface*);
int ritemmodel_column_count(RItemModelInterface*, qmodelindex_t parent); int ritemmodel_column_count(RItemModelInterface*, qmodelindex_t parent);
int ritemmodel_row_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): RItemModel::RItemModel(QObject *parent):
QAbstractItemModel(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::~RItemModel() {
ritemmodel_free(d); ritemmodel_free(d);
} }
void RItemModel::handleNewData() {
qDebug() << "new data!";
}
int RItemModel::columnCount(const QModelIndex &parent) const int RItemModel::columnCount(const QModelIndex &parent) const
{ {
const qmodelindex_t p = { return ritemmodel_column_count(d, parent);
.row = parent.row(),
.column = parent.column(),
.id = parent.internalId()
};
return ritemmodel_column_count(d, p);
} }
int RItemModel::rowCount(const QModelIndex &parent) const int RItemModel::rowCount(const QModelIndex &parent) const
{ {
const qmodelindex_t p = { return ritemmodel_row_count(d, parent);
.row = parent.row(),
.column = parent.column(),
.id = parent.internalId()
};
return ritemmodel_row_count(d, p);
} }
void set_variant(void* v, qvariant_t* val) { 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 QVariant RItemModel::data(const QModelIndex &index, int role) const
{ {
const qmodelindex_t i = {
.row = index.row(),
.column = index.column(),
.id = index.internalId()
};
QVariant v; QVariant v;
ritemmodel_data(d, i, role, &v, set_variant); ritemmodel_data(d, index, role, &v, set_variant);
return v; return v;
} }
QModelIndex RItemModel::index(int row, int column, const QModelIndex &parent) const QModelIndex RItemModel::index(int row, int column, const QModelIndex &parent) const
{ {
const qmodelindex_t p = { const qmodelindex_t i = ritemmodel_index(d, row, column, parent);
.row = parent.row(),
.column = parent.column(),
.id = parent.internalId()
};
const qmodelindex_t i = ritemmodel_index(d, row, column, p);
return i.id ?createIndex(i.row, i.column, i.id) :QModelIndex(); return i.id ?createIndex(i.row, i.column, i.id) :QModelIndex();
} }
QModelIndex RItemModel::parent(const QModelIndex &index) const QModelIndex RItemModel::parent(const QModelIndex &index) const
@ -168,11 +159,6 @@ QModelIndex RItemModel::parent(const QModelIndex &index) const
if (!index.isValid()) { if (!index.isValid()) {
return QModelIndex(); return QModelIndex();
} }
const qmodelindex_t i = { const qmodelindex_t parent = ritemmodel_parent(d, index);
.row = index.row(),
.column = index.column(),
.id = index.internalId()
};
const qmodelindex_t parent = ritemmodel_parent(d, i);
return parent.id ?createIndex(parent.row, parent.column, parent.id) :QModelIndex(); return parent.id ?createIndex(parent.row, parent.column, parent.id) :QModelIndex();
} }

View File

@ -45,6 +45,12 @@ public:
QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &index) const; QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
private slots:
void handleNewData();
signals:
void newDataReady();
}; };
#endif // RMAIL_OBJECT_H #endif // RMAIL_OBJECT_H