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::ffi::OsString;
use std::default::Default;
use std::thread;
pub struct Hello {
emit: HelloEmitter,
@ -105,6 +106,10 @@ impl<T: Item> RGeneralItemModel<T> {
};
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<T: Item> RItemModelTrait<T> for RGeneralItemModel<T> {
entries: vec![none, root]
}
}
fn emit(&self) -> &RItemModelEmitter {
&self.emit
}
fn column_count(&mut self, _: QModelIndex) -> c_int {
2
}

View File

@ -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<Mutex<*const RItemModelQObject>>,
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<T> {
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<T> {
}
#[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]

View File

@ -5,7 +5,7 @@
#include <unistd.h>
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();
}

View File

@ -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