Send specific types over model data() calls instead of QVariant

master
Jos van den Oever 2017-08-12 21:41:10 +02:00
parent 30a4076b2f
commit 7707f28ee7
9 changed files with 102 additions and 325 deletions

View File

@ -35,16 +35,20 @@
}],
"roles": [{
"name": "FileIcon",
"value": "Qt::DecorationRole"
"value": "Qt::DecorationRole",
"type": "QByteArray"
}, {
"name": "FilePath",
"value": "Qt::UserRole + 1"
"value": "Qt::UserRole + 1",
"type": "QString"
}, {
"name": "FileName",
"value": "Qt::UserRole + 2"
"value": "Qt::UserRole + 2",
"type": "QString"
}, {
"name": "FilePermissions",
"value": "Qt::UserRole + 3"
"value": "Qt::UserRole + 3",
"type": "int"
}]
}]
}

View File

@ -77,16 +77,16 @@ impl DirectoryTrait for Directory {
fn row_count(&self) -> c_int {
10
}
fn file_icon(&self, row: c_int) -> Variant {
Variant::Bool(row > 0)
fn file_icon(&self, row: c_int) -> Vec<u8> {
Vec::new()
}
fn file_path(&self, row: c_int) -> Variant {
Variant::Bool(row > 0)
fn file_path(&self, row: c_int) -> String {
String::from("file_path")
}
fn file_name(&self, row: c_int) -> Variant {
Variant::Bool(row > 0)
fn file_name(&self, row: c_int) -> String {
String::from("file_name")
}
fn file_permissions(&self, row: c_int) -> Variant {
Variant::Bool(row > 0)
fn file_permissions(&self, row: c_int) -> c_int {
row
}
}

View File

@ -181,10 +181,10 @@ pub trait DirectoryTrait {
fn row_count(&self) -> c_int;
fn can_fetch_more(&self) -> bool { false }
fn fetch_more(&self) {}
fn file_icon(&self, row: c_int) -> Variant;
fn file_path(&self, row: c_int) -> Variant;
fn file_name(&self, row: c_int) -> Variant;
fn file_permissions(&self, row: c_int) -> Variant;
fn file_icon(&self, row: c_int) -> Vec<u8>;
fn file_path(&self, row: c_int) -> String;
fn file_name(&self, row: c_int) -> String;
fn file_permissions(&self, row: c_int) -> c_int;
}
#[no_mangle]
@ -247,36 +247,32 @@ pub unsafe extern "C" fn directory_fetch_more(ptr: *mut Directory) {
#[no_mangle]
pub unsafe extern "C" fn directory_data_file_icon(ptr: *const Directory,
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, &QVariant)) {
let data = (& *ptr).file_icon(row);
set(d, &QVariant::from(&data));
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, QByteArray)) {
let data = (&*ptr).file_icon(row);
set(d, QByteArray::from(&data));
}
#[no_mangle]
pub unsafe extern "C" fn directory_data_file_path(ptr: *const Directory,
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, &QVariant)) {
let data = (& *ptr).file_path(row);
set(d, &QVariant::from(&data));
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, QString)) {
let data = (&*ptr).file_path(row);
set(d, QString::from(&data));
}
#[no_mangle]
pub unsafe extern "C" fn directory_data_file_name(ptr: *const Directory,
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, &QVariant)) {
let data = (& *ptr).file_name(row);
set(d, &QVariant::from(&data));
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, QString)) {
let data = (&*ptr).file_name(row);
set(d, QString::from(&data));
}
#[no_mangle]
pub unsafe extern "C" fn directory_data_file_permissions(ptr: *const Directory,
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, &QVariant)) {
let data = (& *ptr).file_permissions(row);
set(d, &QVariant::from(&data));
pub unsafe extern "C" fn directory_data_file_permissions(ptr: *const Directory, row: c_int) -> c_int {
(&*ptr).file_permissions(row)
}

View File

@ -36,65 +36,6 @@ namespace {
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 variant(const qvariant_t& v) {
switch (v.type) {
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(v.data), v.value);
case QVariant::Bool: return QVariant((bool)v.value);
case QVariant::Int: return QVariant(v.value);
case QVariant::ByteArray: return QVariant(QByteArray(v.data, v.value));
default:;
}
return QVariant();
}
void variant(const QByteArray& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::ByteArray,
.value = v.length(),
.data = v.data()
});
}
void variant(const QString& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::String,
.value = v.size(),
.data = static_cast<const char*>(static_cast<const void*>(v.utf16()))
});
}
void variant(const QVariant& v, void* d, void (*set)(void*, qvariant_t)) {
switch (v.type()) {
case QVariant::Bool:
set(d, {
.type = QVariant::Bool,
.value = v.toBool(),
.data = 0
});
break;
case QVariant::Int:
set(d, {
.type = QVariant::Int,
.value = v.toInt(),
.data = 0
});
break;
case QVariant::ByteArray:
variant(v.toByteArray(), d, set);
break;
case QVariant::String:
variant(v.toString(), d, set);
break;
default:
set(d, {
.type = QVariant::Invalid,
.value = 0,
.data = 0
});
}
}
}
typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) {
@ -104,10 +45,6 @@ typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val;
}
typedef void (*qvariant_set)(QVariant*, qvariant_t*);
void set_qvariant(QVariant* v, qvariant_t* val) {
*v = variant(*val);
}
extern "C" {
PersonInterface* person_new(Person*, void (*)(Person*), void (*)(Person*), void (*)(Person*), void (*)(Person*));
@ -206,10 +143,10 @@ enum DirectoryRole {
};
extern "C" {
void directory_data_file_icon(DirectoryInterface*, int, QVariant*, qvariant_set);
void directory_data_file_path(DirectoryInterface*, int, QVariant*, qvariant_set);
void directory_data_file_name(DirectoryInterface*, int, QVariant*, qvariant_set);
void directory_data_file_permissions(DirectoryInterface*, int, QVariant*, qvariant_set);
void directory_data_file_icon(DirectoryInterface*, int, QByteArray*, qbytearray_set);
void directory_data_file_path(DirectoryInterface*, int, QString*, qstring_set);
void directory_data_file_name(DirectoryInterface*, int, QString*, qstring_set);
int directory_data_file_permissions(DirectoryInterface*, int);
int directory_row_count(DirectoryInterface*);
bool directory_can_fetch_more(DirectoryInterface*);
@ -253,18 +190,23 @@ void Directory::fetchMore(const QModelIndex &parent)
QVariant Directory::data(const QModelIndex &index, int role) const
{
QVariant v;
QString s;
QByteArray b;
switch ((DirectoryRole)role) {
case DirectoryRoleFileIcon:
directory_data_file_icon(d, index.row(), &v, set_qvariant);
directory_data_file_icon(d, index.row(), &b, set_qbytearray);
v.setValue<QByteArray>(b);
break;
case DirectoryRoleFilePath:
directory_data_file_path(d, index.row(), &v, set_qvariant);
directory_data_file_path(d, index.row(), &s, set_qstring);
v.setValue<QString>(s);
break;
case DirectoryRoleFileName:
directory_data_file_name(d, index.row(), &v, set_qvariant);
directory_data_file_name(d, index.row(), &s, set_qstring);
v.setValue<QString>(s);
break;
case DirectoryRoleFilePermissions:
directory_data_file_permissions(d, index.row(), &v, set_qvariant);
v.setValue<int>(directory_data_file_permissions(d, index.row()));
break;
}
return v;

View File

@ -21,8 +21,7 @@ enum class BindingType {
Int,
UInt,
QString,
QByteArray,
QVariant
QByteArray
};
struct BindingTypeProperties {
@ -93,6 +92,7 @@ struct Property {
struct Role {
QString name;
QString value;
BindingTypeProperties type;
};
struct Object {
@ -141,6 +141,7 @@ parseRole(const QJsonObject& json) {
Role r;
r.name = json.value("name").toString();
r.value = json.value("value").toString();
r.type = parseBindingType(json.value("type").toString());
return r;
}
@ -210,8 +211,8 @@ QString writeProperty(const QString& name) {
return "WRITE set" + upperInitial(name) + " ";
}
QString cGetType(const Property& p) {
return p.type.name + "*, " + p.type.name.toLower() + "_set";
QString cGetType(const BindingTypeProperties& type) {
return type.name + "*, " + type.name.toLower() + "_set";
}
QString baseType(const Object& o) {
@ -247,8 +248,13 @@ void writeCppListModel(QTextStream& cpp, const Object& o) {
cpp << "extern \"C\" {\n";
for (auto role: o.roles) {
cpp << QString(" void %2_data_%3(%1Interface*, int, QVariant*, qvariant_set);\n")
.arg(o.name, lcname, snakeCase(role.name));
if (role.type.isComplex()) {
cpp << QString(" void %2_data_%3(%1Interface*, int, %4);\n")
.arg(o.name, lcname, snakeCase(role.name), cGetType(role.type));
} else {
cpp << QString(" %4 %2_data_%3(%1Interface*, int);\n")
.arg(o.name, lcname, snakeCase(role.name), role.type.name);
}
}
cpp << QString(R"(
int %2_row_count(%1Interface*);
@ -293,14 +299,26 @@ void %1::fetchMore(const QModelIndex &parent)
QVariant %1::data(const QModelIndex &index, int role) const
{
QVariant v;
QString s;
QByteArray b;
switch ((%1Role)role) {
)").arg(o.name, lcname);
for (auto role: o.roles) {
cpp << QString(" case %1Role%2:\n").arg(o.name, role.name);
cpp << QString(" %1_data_%2(d, index.row(), &v, set_qvariant);\n")
.arg(lcname, snakeCase(role.name));
cpp << " break;\n";
cpp << QString(" case %1Role%2:\n").arg(o.name, role.name);
if (role.type.name == "QString") {
cpp << QString(" %1_data_%2(d, index.row(), &s, set_%3);\n")
.arg(lcname, snakeCase(role.name), role.type.name.toLower());
cpp << " v.setValue<QString>(s);\n";
} else if (role.type.name == "QByteArray") {
cpp << QString(" %1_data_%2(d, index.row(), &b, set_%3);\n")
.arg(lcname, snakeCase(role.name), role.type.name.toLower());
cpp << " v.setValue<QByteArray>(b);\n";
} else {
cpp << QString(" v.setValue<%3>(%1_data_%2(d, index.row()));\n")
.arg(lcname, snakeCase(role.name), role.type.name);
}
cpp << " break;\n";
}
cpp << " }\n return v;\n}\n";
cpp << "QHash<int, QByteArray> " << o.name << "::roleNames() const {\n";
@ -369,7 +387,7 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
if (p.type.isComplex()) {
cpp << QString(" void %2_get(%1Interface*, %3);")
.arg(o.name, base, cGetType(p)) << endl;
.arg(o.name, base, cGetType(p.type)) << endl;
} else {
cpp << QString(" %3 %2_get(%1Interface*);")
.arg(o.name, base, p.type.name) << endl;
@ -426,11 +444,7 @@ void writeCppObject(QTextStream& cpp, const Object& o) {
}
if (p.write) {
cpp << "void " << o.name << "::set" << upperInitial(p.name) << "(" << p.type.cppSetType << " v) {" << endl;
if (p.type.name == "QVariant") {
cpp << QString(" variant(v, d, %1_set);").arg(base) << endl;
} else {
cpp << QString(" %1_set(d, v);").arg(base) << endl;
}
cpp << QString(" %1_set(d, v);").arg(base) << endl;
cpp << "}" << endl;
}
}
@ -536,65 +550,6 @@ namespace {
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 variant(const qvariant_t& v) {
switch (v.type) {
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(v.data), v.value);
case QVariant::Bool: return QVariant((bool)v.value);
case QVariant::Int: return QVariant(v.value);
case QVariant::ByteArray: return QVariant(QByteArray(v.data, v.value));
default:;
}
return QVariant();
}
void variant(const QByteArray& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::ByteArray,
.value = v.length(),
.data = v.data()
});
}
void variant(const QString& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::String,
.value = v.size(),
.data = static_cast<const char*>(static_cast<const void*>(v.utf16()))
});
}
void variant(const QVariant& v, void* d, void (*set)(void*, qvariant_t)) {
switch (v.type()) {
case QVariant::Bool:
set(d, {
.type = QVariant::Bool,
.value = v.toBool(),
.data = 0
});
break;
case QVariant::Int:
set(d, {
.type = QVariant::Int,
.value = v.toInt(),
.data = 0
});
break;
case QVariant::ByteArray:
variant(v.toByteArray(), d, set);
break;
case QVariant::String:
variant(v.toString(), d, set);
break;
default:
set(d, {
.type = QVariant::Invalid,
.value = 0,
.data = 0
});
}
}
}
typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) {
@ -604,10 +559,6 @@ typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val;
}
typedef void (*qvariant_set)(QVariant*, qvariant_t*);
void set_qvariant(QVariant* v, qvariant_t* val) {
*v = variant(*val);
}
extern "C" {
)").arg(conf.hFile.fileName());
@ -701,8 +652,8 @@ pub trait %1Trait {
r << " fn can_fetch_more(&self) -> bool { false }\n";
r << " fn fetch_more(&self) {}\n";
for (auto role: o.roles) {
r << QString(" fn %1(&self, row: c_int) -> Variant;\n")
.arg(snakeCase(role.name));
r << QString(" fn %1(&self, row: c_int) -> %2;\n")
.arg(snakeCase(role.name), role.type.rustType);
}
}
@ -759,7 +710,7 @@ pub unsafe extern "C" fn %2_free(ptr: *mut %1) {
const QString base = QString("%1_%2").arg(lcname, snakeCase(p.name));
QString ret = ") -> " + p.type.rustType;
if (p.type.isComplex()) {
r << QString(R"(
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_get(ptr: *const %1,
p: *mut c_void,
@ -778,7 +729,7 @@ pub unsafe extern "C" fn %2_set(ptr: *mut %1, v: %4) {
)").arg(o.name, base, snakeCase(p.name), type);
}
} else {
r << QString(R"(
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_get(ptr: *const %1) -> %4 {
(&*ptr).get_%3()
@ -810,16 +761,25 @@ pub unsafe extern "C" fn %2_fetch_more(ptr: *mut %1) {
}
)").arg(o.name, lcname);
for (auto role: o.roles) {
r << QString(R"(
if (role.type.isComplex()) {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_data_%3(ptr: *const %1,
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, &QVariant)) {
let data = (& *ptr).%3(row);
set(d, &QVariant::from(&data));
row: c_int,
d: *mut c_void,
set: fn(*mut c_void, %4)) {
let data = (&*ptr).%3(row);
set(d, %4::from(&data));
}
)").arg(o.name, lcname, snakeCase(role.name));
)").arg(o.name, lcname, snakeCase(role.name), role.type.name);
} else {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %2_data_%3(ptr: *const %1, row: c_int) -> %4 {
(&*ptr).%3(row)
}
)").arg(o.name, lcname, snakeCase(role.name), role.type.rustType);
}
}
}
}

View File

@ -1,5 +1,6 @@
#![allow(unused_imports)]
use libc::c_int;
use libc::c_uint;
use types::*;
use interface::*;

View File

@ -2,7 +2,7 @@
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
#![allow(unused_imports)]
use libc::{c_int, c_void};
use libc::{c_int, c_uint, c_void};
use types::*;
use std::sync::{Arc, Mutex};
use std::ptr::null;

View File

@ -36,65 +36,6 @@ namespace {
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 variant(const qvariant_t& v) {
switch (v.type) {
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(v.data), v.value);
case QVariant::Bool: return QVariant((bool)v.value);
case QVariant::Int: return QVariant(v.value);
case QVariant::ByteArray: return QVariant(QByteArray(v.data, v.value));
default:;
}
return QVariant();
}
void variant(const QByteArray& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::ByteArray,
.value = v.length(),
.data = v.data()
});
}
void variant(const QString& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::String,
.value = v.size(),
.data = static_cast<const char*>(static_cast<const void*>(v.utf16()))
});
}
void variant(const QVariant& v, void* d, void (*set)(void*, qvariant_t)) {
switch (v.type()) {
case QVariant::Bool:
set(d, {
.type = QVariant::Bool,
.value = v.toBool(),
.data = 0
});
break;
case QVariant::Int:
set(d, {
.type = QVariant::Int,
.value = v.toInt(),
.data = 0
});
break;
case QVariant::ByteArray:
variant(v.toByteArray(), d, set);
break;
case QVariant::String:
variant(v.toString(), d, set);
break;
default:
set(d, {
.type = QVariant::Invalid,
.value = 0,
.data = 0
});
}
}
}
typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) {
@ -104,10 +45,6 @@ typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val;
}
typedef void (*qvariant_set)(QVariant*, qvariant_t*);
void set_qvariant(QVariant* v, qvariant_t* val) {
*v = variant(*val);
}
extern "C" {
PersonInterface* person_new(Person*, void (*)(Person*));

View File

@ -36,65 +36,6 @@ namespace {
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 variant(const qvariant_t& v) {
switch (v.type) {
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(v.data), v.value);
case QVariant::Bool: return QVariant((bool)v.value);
case QVariant::Int: return QVariant(v.value);
case QVariant::ByteArray: return QVariant(QByteArray(v.data, v.value));
default:;
}
return QVariant();
}
void variant(const QByteArray& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::ByteArray,
.value = v.length(),
.data = v.data()
});
}
void variant(const QString& v, void* d, void (*set)(void*, qvariant_t)) {
set(d, {
.type = QVariant::String,
.value = v.size(),
.data = static_cast<const char*>(static_cast<const void*>(v.utf16()))
});
}
void variant(const QVariant& v, void* d, void (*set)(void*, qvariant_t)) {
switch (v.type()) {
case QVariant::Bool:
set(d, {
.type = QVariant::Bool,
.value = v.toBool(),
.data = 0
});
break;
case QVariant::Int:
set(d, {
.type = QVariant::Int,
.value = v.toInt(),
.data = 0
});
break;
case QVariant::ByteArray:
variant(v.toByteArray(), d, set);
break;
case QVariant::String:
variant(v.toString(), d, set);
break;
default:
set(d, {
.type = QVariant::Invalid,
.value = 0,
.data = 0
});
}
}
}
typedef void (*qstring_set)(QString*, qstring_t*);
void set_qstring(QString* v, qstring_t* val) {
@ -104,10 +45,6 @@ typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*);
void set_qbytearray(QByteArray* v, qbytearray_t* val) {
*v = *val;
}
typedef void (*qvariant_set)(QVariant*, qvariant_t*);
void set_qvariant(QVariant* v, qvariant_t* val) {
*v = variant(*val);
}
extern "C" {
ObjectInterface* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*));