Progress on QAbstractItemModel
parent
b56d1faf9b
commit
8d4d71a4b8
|
@ -15,6 +15,12 @@ include(KDECMakeSettings)
|
|||
include(KDECompilerSettings)
|
||||
include(FeatureSummary)
|
||||
|
||||
#add_custom_target(rust
|
||||
# OUTPUT "${CMAKE_SOURCE_DIR}/target/debug/librust.a"
|
||||
# COMMAND cargo build
|
||||
# COMMAND cargo build --release
|
||||
# DEPENDS
|
||||
|
||||
set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/Rust)
|
||||
|
||||
ExternalProject_Add(
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
use interface::*;
|
||||
use types::*;
|
||||
use libc::{c_int};
|
||||
|
||||
pub struct Hello {
|
||||
notifier: HelloNotifier,
|
||||
emit: HelloEmitter,
|
||||
hello: String,
|
||||
}
|
||||
|
||||
impl HelloTrait for Hello {
|
||||
fn create(notifier: HelloNotifier) -> Self {
|
||||
fn create(emit: HelloEmitter) -> Self {
|
||||
Hello {
|
||||
notifier: notifier,
|
||||
emit: emit,
|
||||
hello: String::new()
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +19,7 @@ impl HelloTrait for Hello {
|
|||
}
|
||||
fn set_hello(&mut self, value: String) {
|
||||
self.hello = value;
|
||||
self.notifier.hello_changed();
|
||||
self.emit.hello_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,13 +29,29 @@ impl Drop for Hello {
|
|||
}
|
||||
|
||||
pub struct RItemModel {
|
||||
notifier: RItemModelNotifier
|
||||
emit: RItemModelEmitter,
|
||||
// string: String
|
||||
}
|
||||
|
||||
impl RItemModelTrait for RItemModel {
|
||||
fn create(notifier: RItemModelNotifier) -> Self {
|
||||
fn create(emit: RItemModelEmitter) -> Self {
|
||||
RItemModel {
|
||||
notifier: notifier
|
||||
emit: emit
|
||||
}
|
||||
}
|
||||
fn column_count(&self, parent: QModelIndex) -> c_int {
|
||||
if parent.is_valid() { 0 } else { 2 }
|
||||
}
|
||||
fn row_count(&self, parent: QModelIndex) -> c_int {
|
||||
if parent.is_valid() { 0 } else { 2 }
|
||||
}
|
||||
fn index(&self, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
|
||||
QModelIndex::flat(row, column)
|
||||
}
|
||||
fn parent(&self, index: QModelIndex) -> QModelIndex {
|
||||
QModelIndex::invalid()
|
||||
}
|
||||
fn data(&self, index: QModelIndex, role: c_int) -> Variant {
|
||||
Variant::String(String::from("hello"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
use std::slice;
|
||||
use libc::{uint8_t, uint16_t, size_t};
|
||||
use libc::{c_int, uint8_t, uint16_t, size_t, c_void};
|
||||
use types::*;
|
||||
|
||||
use implementation::Hello;
|
||||
use implementation::RItemModel;
|
||||
|
||||
pub struct HelloQObject {}
|
||||
|
||||
pub struct HelloNotifier {
|
||||
pub struct HelloEmitter {
|
||||
qobject: *const HelloQObject,
|
||||
hello_changed: fn (*const HelloQObject)
|
||||
}
|
||||
|
||||
impl HelloNotifier {
|
||||
impl HelloEmitter {
|
||||
pub fn hello_changed(&self) {
|
||||
(self.hello_changed)(self.qobject);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HelloTrait {
|
||||
fn create(notifier: HelloNotifier) -> Self;
|
||||
fn create(emit: HelloEmitter) -> Self;
|
||||
fn get_hello(&self) -> &String;
|
||||
fn set_hello(&mut self, value: String);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_new(qobject: *const HelloQObject, changed: fn(*const HelloQObject)) -> *mut Hello {
|
||||
let notifier = HelloNotifier {
|
||||
let emit = HelloEmitter {
|
||||
qobject: qobject,
|
||||
hello_changed: changed
|
||||
};
|
||||
let hello = Hello::create(notifier);
|
||||
let hello = Hello::create(emit);
|
||||
Box::into_raw(Box::new(hello))
|
||||
}
|
||||
|
||||
|
@ -48,40 +49,37 @@ pub extern fn hello_set(ptr: *mut Hello, s: *const uint16_t, len: size_t) {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_size(ptr: *mut Hello) -> size_t {
|
||||
pub extern fn hello_get(ptr: *mut Hello) -> QString {
|
||||
let hello = unsafe {
|
||||
&mut *ptr
|
||||
};
|
||||
hello.get_hello().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_get(ptr: *mut Hello) -> *const uint8_t {
|
||||
let hello = unsafe {
|
||||
&mut *ptr
|
||||
};
|
||||
hello.get_hello().as_ptr()
|
||||
QString::from(hello.get_hello())
|
||||
}
|
||||
|
||||
pub struct RItemModelQObject {}
|
||||
|
||||
pub struct RItemModelNotifier {
|
||||
pub struct RItemModelEmitter {
|
||||
qobject: *const RItemModelQObject
|
||||
}
|
||||
|
||||
impl RItemModelNotifier {
|
||||
impl RItemModelEmitter {
|
||||
}
|
||||
|
||||
pub trait RItemModelTrait {
|
||||
fn create(notifier: RItemModelNotifier) -> Self;
|
||||
fn create(emit: RItemModelEmitter) -> Self;
|
||||
fn column_count(&self, parent: QModelIndex) -> c_int;
|
||||
fn row_count(&self, parent: QModelIndex) -> c_int;
|
||||
fn index(&self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex;
|
||||
fn parent(&self, index: QModelIndex) -> QModelIndex;
|
||||
fn data(&self, index: QModelIndex, role: c_int) -> Variant;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_new(qobject: *const RItemModelQObject) -> *mut RItemModel {
|
||||
let notifier = RItemModelNotifier {
|
||||
let emit = RItemModelEmitter {
|
||||
qobject: qobject
|
||||
};
|
||||
let ritemmodel = RItemModel::create(notifier);
|
||||
let ritemmodel = RItemModel::create(emit);
|
||||
Box::into_raw(Box::new(ritemmodel))
|
||||
}
|
||||
|
||||
|
@ -90,3 +88,44 @@ pub extern fn ritemmodel_free(ptr: *mut RItemModel) {
|
|||
if ptr.is_null() { return }
|
||||
unsafe { Box::from_raw(ptr); }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_column_count(ptr: *const RItemModel, parent: QModelIndex) -> i32 {
|
||||
let ritemmodel = unsafe {
|
||||
&*ptr
|
||||
};
|
||||
ritemmodel.column_count(parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_row_count(ptr: *const RItemModel, parent: QModelIndex) -> i32 {
|
||||
let ritemmodel = unsafe {
|
||||
&*ptr
|
||||
};
|
||||
ritemmodel.row_count(parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_index(ptr: *const RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
|
||||
let ritemmodel = unsafe {
|
||||
&*ptr
|
||||
};
|
||||
ritemmodel.index(row, column, parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> QModelIndex {
|
||||
let ritemmodel = unsafe {
|
||||
&*ptr
|
||||
};
|
||||
ritemmodel.parent(index)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_data(ptr: *const RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) {
|
||||
let ritemmodel = unsafe {
|
||||
&*ptr
|
||||
};
|
||||
let data = ritemmodel.data(index, role);
|
||||
set(d, &QVariant::from(&data));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
pub mod types;
|
||||
pub mod interface;
|
||||
pub mod implementation;
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
use libc::{c_int, c_uint, uint8_t};
|
||||
use std::ptr::null;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QString {
|
||||
data: *const uint8_t,
|
||||
len: c_int
|
||||
}
|
||||
|
||||
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 enum Variant {
|
||||
None,
|
||||
Bool(bool),
|
||||
String(String)
|
||||
}
|
||||
|
||||
/* values from qvariant.h and qmetatype.h */
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy)]
|
||||
enum VariantType {
|
||||
Invalid = 0,
|
||||
Bool = 1,
|
||||
String = 10,
|
||||
ByteArray = 12,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QVariant<'a> {
|
||||
type_: c_uint,
|
||||
len: c_int,
|
||||
data: *const uint8_t,
|
||||
phantom: PhantomData<&'a u8>
|
||||
}
|
||||
|
||||
impl<'a> QVariant<'a> {
|
||||
pub fn type_(&self) -> u32 {
|
||||
self.type_ as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Variant> for QVariant<'a> {
|
||||
fn from(variant: &'a Variant) -> QVariant {
|
||||
match variant {
|
||||
&Variant::None => QVariant {
|
||||
data: null(),
|
||||
len: 0,
|
||||
type_: VariantType::Invalid as c_uint,
|
||||
phantom: PhantomData
|
||||
},
|
||||
&Variant::Bool(v) => QVariant {
|
||||
data: null(),
|
||||
len: v as c_int,
|
||||
type_: VariantType::Bool as c_uint,
|
||||
phantom: PhantomData
|
||||
},
|
||||
&Variant::String(ref v) => QVariant {
|
||||
data: v.as_ptr(),
|
||||
len: v.len() as c_int,
|
||||
type_: VariantType::String as c_uint,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QModelIndex {
|
||||
row: c_int,
|
||||
column: c_int,
|
||||
internal_id: usize
|
||||
}
|
||||
|
||||
impl QModelIndex {
|
||||
pub fn invalid() -> QModelIndex {
|
||||
QModelIndex {
|
||||
row: -1,
|
||||
column: -1,
|
||||
internal_id: 0
|
||||
}
|
||||
}
|
||||
pub fn flat(row: c_int, column: c_int) -> QModelIndex {
|
||||
QModelIndex {
|
||||
row: row,
|
||||
column: column,
|
||||
internal_id: 1
|
||||
}
|
||||
}
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.internal_id != 0 && self.row >= 0 && self.column >= 0
|
||||
}
|
||||
}
|
|
@ -1,16 +1,79 @@
|
|||
#include "RMailObject.h"
|
||||
#include <QSize>
|
||||
#include <QDebug>
|
||||
#include <cstdint>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
typedef struct {
|
||||
private:
|
||||
const char* data;
|
||||
int len;
|
||||
public:
|
||||
operator QByteArray() const {
|
||||
return QByteArray(data, len);
|
||||
}
|
||||
} qbytearray_t;
|
||||
struct qstring_t {
|
||||
private:
|
||||
const char* data;
|
||||
int len;
|
||||
public:
|
||||
operator QString() const {
|
||||
return QString::fromUtf8(data, len);
|
||||
}
|
||||
};
|
||||
typedef struct {
|
||||
int row;
|
||||
int column;
|
||||
uint64_t id;
|
||||
} qmodelindex_t;
|
||||
typedef 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);
|
||||
case QVariant::String: return QString::fromUtf8(v.data, v.value);
|
||||
default:;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*
|
||||
qvariant_t variant(const QVariant& v) {
|
||||
auto t = v.type();
|
||||
switch (t) {
|
||||
case QVariant::Bool:
|
||||
return { .type = t, .value = { .vbool = 0 } };
|
||||
case QVariant::ByteArray:
|
||||
return { .type = t, .value = { .vbool = 0 } };
|
||||
case QVariant::String:
|
||||
return { .type = t, .value = { .vbool = 0 } };
|
||||
default:;
|
||||
}
|
||||
return { .type = QVariant::Invalid, .value = { .vbool = false } };
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
typedef void (*qvariant_set)(void*, qvariant_t*);
|
||||
|
||||
extern "C" {
|
||||
RMailObjectInterface* hello_new(void*, void (*)(RMailObject*));
|
||||
void hello_free(RMailObjectInterface*);
|
||||
void hello_set(RMailObjectInterface*, const uint16_t *, size_t);
|
||||
size_t hello_size(RMailObjectInterface*);
|
||||
const char* hello_get(RMailObjectInterface*);
|
||||
qstring_t hello_get(RMailObjectInterface*);
|
||||
|
||||
RItemModelInterface* ritemmodel_new(void*);
|
||||
void ritemmodel_free(RItemModelInterface*);
|
||||
int ritemmodel_column_count(RItemModelInterface*, qmodelindex_t parent);
|
||||
int ritemmodel_row_count(RItemModelInterface*, qmodelindex_t parent);
|
||||
qmodelindex_t ritemmodel_index(RItemModelInterface*, int row, int column, qmodelindex_t parent);
|
||||
qmodelindex_t ritemmodel_parent(RItemModelInterface*, qmodelindex_t);
|
||||
void ritemmodel_data(RItemModelInterface*, qmodelindex_t, int, void*, qvariant_set);
|
||||
}
|
||||
|
||||
RMailObject::RMailObject(QObject *parent):
|
||||
|
@ -27,7 +90,7 @@ RMailObject::~RMailObject() {
|
|||
|
||||
QString
|
||||
RMailObject::userName() const {
|
||||
return QString::fromUtf8(hello_get(d), hello_size(d));
|
||||
return hello_get(d);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -58,21 +121,64 @@ RItemModel::~RItemModel() {
|
|||
|
||||
int RItemModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
QVariant RItemModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
QModelIndex RItemModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
QModelIndex RItemModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
return QModelIndex();
|
||||
const qmodelindex_t p = {
|
||||
.row = parent.row(),
|
||||
.column = parent.column(),
|
||||
.id = parent.internalId()
|
||||
};
|
||||
return ritemmodel_column_count(d, p);
|
||||
}
|
||||
int RItemModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 0;
|
||||
const qmodelindex_t p = {
|
||||
.row = parent.row(),
|
||||
.column = parent.column(),
|
||||
.id = parent.internalId()
|
||||
};
|
||||
return ritemmodel_row_count(d, p);
|
||||
}
|
||||
|
||||
void set_variant(void* v, qvariant_t* val) {
|
||||
*static_cast<QVariant*>(v) = variant(*val);
|
||||
}
|
||||
|
||||
QVariant RItemModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
if (role != Qt::DisplayRole) {
|
||||
return QVariant();
|
||||
}
|
||||
const qmodelindex_t i = {
|
||||
.row = index.row(),
|
||||
.column = index.column(),
|
||||
.id = index.internalId()
|
||||
};
|
||||
QVariant v;
|
||||
ritemmodel_data(d, i, 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);
|
||||
return i.id ?createIndex(i.row, i.column, i.id) :QModelIndex();
|
||||
}
|
||||
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);
|
||||
return parent.id ?createIndex(parent.row, parent.column, parent.id) :QModelIndex();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "RMailObject.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <KAboutData>
|
||||
|
@ -44,6 +45,12 @@ int main (int argc, char *argv[])
|
|||
parser.process(app);
|
||||
aboutData.processCommandLine(&parser);
|
||||
|
||||
RItemModel model;
|
||||
QTreeView view;
|
||||
view.setModel(&model);
|
||||
view.show();
|
||||
return app.exec();
|
||||
/*
|
||||
RMailObject rmail;
|
||||
rmail.setUserName("RMail");
|
||||
rmail.userName();
|
||||
|
@ -56,4 +63,5 @@ int main (int argc, char *argv[])
|
|||
KMessageBox::questionYesNo
|
||||
(0, i18n( "Hello World" ), i18n( "Hello" ), yesButton )
|
||||
== KMessageBox::Yes? EXIT_SUCCESS: EXIT_FAILURE;
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue