Add a test
parent
bced2e9ba3
commit
25d65e1b9e
|
@ -15,28 +15,13 @@ 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(
|
||||
rust
|
||||
DOWNLOAD_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND cargo build
|
||||
COMMAND cargo build --release
|
||||
BINARY_DIR "${CMAKE_SOURCE_DIR}/common-rust"
|
||||
INSTALL_COMMAND ""
|
||||
LOG_BUILD ON)
|
||||
|
||||
# Find Qt modules
|
||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||
Core # QCommandLineParser, QStringLiteral
|
||||
Quick
|
||||
Test
|
||||
Widgets # QApplication
|
||||
)
|
||||
|
||||
|
@ -51,12 +36,38 @@ feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAG
|
|||
|
||||
add_subdirectory(rust_qt_binding_generator)
|
||||
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER)
|
||||
if(CMAKE_BUILD_TYPE_UPPER STREQUAL DEBUG)
|
||||
set(RUST_TARGET_DIR target/debug/)
|
||||
set(RUST_BUILD_FLAG)
|
||||
else()
|
||||
set(RUST_TARGET_DIR target/release/)
|
||||
set(RUST_BUILD_FLAG --release)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/common-rust/src/testinterface.rs"
|
||||
COMMAND ${CMAKE_BINARY_DIR}/rust_qt_binding_generator/rust_qt_binding_generator "${CMAKE_CURRENT_SOURCE_DIR}/bindings.json"
|
||||
DEPENDS rust_qt_binding_generator bindings.json
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/common-rust/${RUST_TARGET_DIR}/librust.a"
|
||||
COMMAND cargo build ${RUST_BUILD_FLAG}
|
||||
DEPENDS common-rust/src/lib.rs
|
||||
common-rust/src/testimplementation.rs
|
||||
common-rust/src/testinterface.rs
|
||||
common-rust/src/implementation.rs
|
||||
common-rust/src/interface.rs
|
||||
common-rust/src/types.rs
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/common-rust"
|
||||
)
|
||||
add_custom_target(rust_target DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/common-rust/${RUST_TARGET_DIR}/librust.a")
|
||||
|
||||
set(RMail_SRCS src/main.cpp src/RMailObject.cpp src/tmp.cpp)
|
||||
|
||||
add_executable(RMail ${RMail_SRCS})
|
||||
|
||||
add_dependencies(RMail rust)
|
||||
add_dependencies(RMail rust_target)
|
||||
|
||||
target_link_libraries(RMail
|
||||
Qt5::Quick
|
||||
|
@ -64,8 +75,7 @@ target_link_libraries(RMail
|
|||
KF5::CoreAddons
|
||||
KF5::I18n
|
||||
KF5::WidgetsAddons
|
||||
debug "${CMAKE_SOURCE_DIR}/common-rust/target/debug/librust.a"
|
||||
optimized "${CMAKE_SOURCE_DIR}/common-rust/target/release/librust.a"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/common-rust/${RUST_TARGET_DIR}/librust.a"
|
||||
)
|
||||
|
||||
set_target_properties(RMail PROPERTIES
|
||||
|
@ -74,3 +84,6 @@ set_target_properties(RMail PROPERTIES
|
|||
)
|
||||
|
||||
install(TARGETS RMail ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
add_subdirectory(tests)
|
||||
|
||||
|
|
2
dev
2
dev
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/bash
|
||||
rm -rf __nix_qt5__/
|
||||
nix-shell -p qtcreator cmake ninja gcc rustc cargo qt5.full extra-cmake-modules kdeFrameworks.kwidgetsaddons kdeFrameworks.kcoreaddons kdeFrameworks.ki18n appstream
|
||||
nix-shell -p qtcreator cmake ninja gcc rustc cargo qt5.full extra-cmake-modules kdeFrameworks.kwidgetsaddons kdeFrameworks.kcoreaddons kdeFrameworks.ki18n appstream cmakeCurses
|
||||
|
|
|
@ -100,6 +100,7 @@ parseConfiguration(const QString& path) {
|
|||
const QJsonObject o = doc.object();
|
||||
Configuration c;
|
||||
c.cppFile = QFileInfo(base, o.value("cppFile").toString());
|
||||
QDir(c.cppFile.dir()).mkpath(".");
|
||||
c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h");
|
||||
for (const QJsonValue& val: o.value("objects").toArray()) {
|
||||
c.objects.append(parseObject(val.toObject()));
|
||||
|
|
|
@ -62,7 +62,7 @@ int main (int argc, char *argv[])
|
|||
view.show();
|
||||
|
||||
engine.rootContext()->setContextProperty("fsModel", &model);
|
||||
engine.load(QUrl(QStringLiteral("test.qml")));
|
||||
engine.load(QUrl(QStringLiteral("../test.qml")));
|
||||
|
||||
return app.exec();
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#include "tmp.h"
|
||||
#include <QModelIndex>
|
||||
|
||||
namespace {
|
||||
struct qbytearray_t {
|
||||
private:
|
||||
const char* data;
|
||||
int len;
|
||||
public:
|
||||
qbytearray_t(const QByteArray& v):
|
||||
data(v.data()),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QByteArray() const {
|
||||
return QByteArray(data, len);
|
||||
}
|
||||
};
|
||||
struct qstring_t {
|
||||
private:
|
||||
const void* data;
|
||||
int len;
|
||||
public:
|
||||
qstring_t(const QString& v):
|
||||
data(static_cast<const void*>(v.utf16())),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QString() const {
|
||||
return QString::fromUtf8(static_cast<const char*>(data), len);
|
||||
}
|
||||
};
|
||||
struct qmodelindex_t {
|
||||
int row;
|
||||
int column;
|
||||
uint64_t id;
|
||||
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::Bool: return QVariant((bool)v.value);
|
||||
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(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) {
|
||||
*v = *val;
|
||||
}
|
||||
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*), void (*)(Person*));
|
||||
void person_free(PersonInterface*);
|
||||
void person_user_name_get(PersonInterface*, QString*, qstring_set);
|
||||
void person_user_name_set(void*, qstring_t);
|
||||
int person_age_get(PersonInterface*);
|
||||
bool person_active_get(PersonInterface*);
|
||||
void person_active_set(void*, bool);
|
||||
void person_misc_get(PersonInterface*, QVariant*, qvariant_set);
|
||||
void person_misc_set(void*, qvariant_t);
|
||||
void person_icon_get(PersonInterface*, QByteArray*, qbytearray_set);
|
||||
void person_icon_set(void*, qbytearray_t);
|
||||
DirectoryInterface* directory_new(Directory*, void (*)(Directory*),
|
||||
void (*)(Directory*, int, int),
|
||||
void (*)(Directory*),
|
||||
void (*)(Directory*, int, int),
|
||||
void (*)(Directory*));
|
||||
void directory_free(DirectoryInterface*);
|
||||
void directory_path_get(DirectoryInterface*, QString*, qstring_set);
|
||||
void directory_path_set(void*, qstring_t);
|
||||
};
|
||||
Person::Person(QObject *parent):
|
||||
QObject(parent),
|
||||
d(person_new(this,
|
||||
[](Person* o) { emit o->userNameChanged(); },
|
||||
[](Person* o) { emit o->ageChanged(); },
|
||||
[](Person* o) { emit o->activeChanged(); },
|
||||
[](Person* o) { emit o->miscChanged(); },
|
||||
[](Person* o) { emit o->iconChanged(); })) {}
|
||||
|
||||
Person::~Person() {
|
||||
person_free(d);
|
||||
}
|
||||
QString Person::userName() const
|
||||
{
|
||||
QString v;
|
||||
person_user_name_get(d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Person::setUserName(const QString& v) {
|
||||
person_user_name_set(d, v);
|
||||
}
|
||||
int Person::age() const
|
||||
{
|
||||
return person_age_get(d);
|
||||
}
|
||||
bool Person::active() const
|
||||
{
|
||||
return person_active_get(d);
|
||||
}
|
||||
void Person::setActive(bool v) {
|
||||
person_active_set(d, v);
|
||||
}
|
||||
QVariant Person::misc() const
|
||||
{
|
||||
QVariant v;
|
||||
person_misc_get(d, &v, set_qvariant);
|
||||
return v;
|
||||
}
|
||||
void Person::setMisc(const QVariant& v) {
|
||||
variant(v, d, person_misc_set);
|
||||
}
|
||||
QByteArray Person::icon() const
|
||||
{
|
||||
QByteArray v;
|
||||
person_icon_get(d, &v, set_qbytearray);
|
||||
return v;
|
||||
}
|
||||
void Person::setIcon(const QByteArray& v) {
|
||||
person_icon_set(d, v);
|
||||
}
|
||||
Directory::Directory(QObject *parent):
|
||||
QAbstractItemModel(parent),
|
||||
d(directory_new(this,
|
||||
[](Directory* o) { emit o->pathChanged(); },
|
||||
[](Directory* o, int first, int last) {
|
||||
emit o->beginInsertRows(QModelIndex(), first, last);
|
||||
},
|
||||
[](Directory* o) {
|
||||
emit o->endInsertRows();
|
||||
},
|
||||
[](Directory* o, int first, int last) {
|
||||
emit o->beginRemoveRows(QModelIndex(), first, last);
|
||||
},
|
||||
[](Directory* o) {
|
||||
emit o->endRemoveRows();
|
||||
}
|
||||
)) {}
|
||||
|
||||
Directory::~Directory() {
|
||||
directory_free(d);
|
||||
}
|
||||
QString Directory::path() const
|
||||
{
|
||||
QString v;
|
||||
directory_path_get(d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Directory::setPath(const QString& v) {
|
||||
directory_path_set(d, v);
|
||||
}
|
||||
enum DirectoryRole {
|
||||
DirectoryRoleFileIcon = Qt::DecorationRole,
|
||||
DirectoryRoleFilePath = Qt::UserRole + 1,
|
||||
DirectoryRoleFileName = Qt::UserRole + 2,
|
||||
DirectoryRoleFilePermissions = Qt::UserRole + 3,
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
int directory_row_count(DirectoryInterface*, qmodelindex_t parent);
|
||||
}
|
||||
int Directory::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return (parent.isValid()) ? 0 : 1;
|
||||
}
|
||||
|
||||
int Directory::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return (parent.isValid()) ? 0 : directory_row_count(d, parent);
|
||||
}
|
||||
|
||||
QModelIndex Directory::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!parent.isValid() && column == 0) {
|
||||
return createIndex(row, 0, (quintptr)0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex Directory::parent(const QModelIndex &) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QVariant Directory::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
switch ((DirectoryRole)role) {
|
||||
case DirectoryRoleFileIcon:
|
||||
directory_data_file_icon(d, index.row(), &v, set_qvariant);
|
||||
break;
|
||||
case DirectoryRoleFilePath:
|
||||
directory_data_file_path(d, index.row(), &v, set_qvariant);
|
||||
break;
|
||||
case DirectoryRoleFileName:
|
||||
directory_data_file_name(d, index.row(), &v, set_qvariant);
|
||||
break;
|
||||
case DirectoryRoleFilePermissions:
|
||||
directory_data_file_permissions(d, index.row(), &v, set_qvariant);
|
||||
break;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
QHash<int, QByteArray> Directory::roleNames() const {
|
||||
QHash<int, QByteArray> names;
|
||||
names.insert(Qt::DecorationRole, "FileIcon");
|
||||
names.insert(Qt::UserRole + 1, "FilePath");
|
||||
names.insert(Qt::UserRole + 2, "FileName");
|
||||
names.insert(Qt::UserRole + 3, "FilePermissions");
|
||||
return names;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#ifndef TMP_H
|
||||
#define TMP_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class PersonInterface;
|
||||
class Person : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
PersonInterface * const d;
|
||||
Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged FINAL)
|
||||
Q_PROPERTY(int age READ age NOTIFY ageChanged FINAL)
|
||||
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged FINAL)
|
||||
Q_PROPERTY(QVariant misc READ misc WRITE setMisc NOTIFY miscChanged FINAL)
|
||||
Q_PROPERTY(QByteArray icon READ icon WRITE setIcon NOTIFY iconChanged FINAL)
|
||||
public:
|
||||
explicit Person(QObject *parent = nullptr);
|
||||
~Person();
|
||||
QString userName() const;
|
||||
void setUserName(const QString& v);
|
||||
int age() const;
|
||||
bool active() const;
|
||||
void setActive(bool v);
|
||||
QVariant misc() const;
|
||||
void setMisc(const QVariant& v);
|
||||
QByteArray icon() const;
|
||||
void setIcon(const QByteArray& v);
|
||||
signals:
|
||||
void userNameChanged();
|
||||
void ageChanged();
|
||||
void activeChanged();
|
||||
void miscChanged();
|
||||
void iconChanged();
|
||||
private:
|
||||
QString m_userName;
|
||||
int m_age;
|
||||
bool m_active;
|
||||
QVariant m_misc;
|
||||
QByteArray m_icon;
|
||||
};
|
||||
|
||||
class DirectoryInterface;
|
||||
class Directory : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
DirectoryInterface * const d;
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL)
|
||||
public:
|
||||
explicit Directory(QObject *parent = nullptr);
|
||||
~Directory();
|
||||
QString path() const;
|
||||
void setPath(const QString& v);
|
||||
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
signals:
|
||||
void newDataReady();
|
||||
signals:
|
||||
void pathChanged();
|
||||
private:
|
||||
QString m_path;
|
||||
};
|
||||
#endif // TMP_H
|
|
@ -0,0 +1,33 @@
|
|||
enable_testing()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rust_object/src/interface.rs"
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove "${CMAKE_CURRENT_SOURCE_DIR}/rust_object/src/implementation.rs"
|
||||
COMMAND ${CMAKE_BINARY_DIR}/rust_qt_binding_generator/rust_qt_binding_generator "${CMAKE_CURRENT_SOURCE_DIR}/test_object.json"
|
||||
DEPENDS rust_qt_binding_generator test_object.json
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/rust_object/${RUST_TARGET_DIR}/librust.a"
|
||||
COMMAND cargo build ${RUST_BUILD_FLAG}
|
||||
DEPENDS rust_object/src/lib.rs
|
||||
rust_object/src/implementation.rs
|
||||
rust_object/src/interface.rs
|
||||
rust_object/src/types.rs
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/rust_object"
|
||||
)
|
||||
add_custom_target(test_rust_object DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/rust_object/${RUST_TARGET_DIR}/librust.a")
|
||||
|
||||
add_executable(test_object test_object.cpp test_object_rust.cpp)
|
||||
add_dependencies(test_object test_rust_object)
|
||||
target_link_libraries(test_object
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/rust_object/${RUST_TARGET_DIR}/librust.a"
|
||||
)
|
||||
|
||||
add_test(remove_test_object "${CMAKE_COMMAND}" -E remove test_object)
|
||||
add_test(build_test_object "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target test_object)
|
||||
set_tests_properties(build_test_object PROPERTIES DEPENDS remove_test_object)
|
||||
add_test(test_object test_object)
|
||||
set_tests_properties(test_object PROPERTIES DEPENDS build_test_object)
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "rust_object"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
libc = "*"
|
||||
|
||||
[lib]
|
||||
name = "rust"
|
||||
crate-type = ["staticlib"]
|
|
@ -0,0 +1,27 @@
|
|||
use libc::c_int;
|
||||
use types::*;
|
||||
use interface::*;
|
||||
|
||||
pub struct Person {
|
||||
emit: PersonEmitter,
|
||||
user_name: String,
|
||||
}
|
||||
|
||||
impl PersonTrait for Person {
|
||||
fn create(emit: PersonEmitter) -> Person {
|
||||
Person {
|
||||
emit: emit,
|
||||
user_name: String::new(),
|
||||
}
|
||||
}
|
||||
fn emit(&self) -> &PersonEmitter {
|
||||
&self.emit
|
||||
}
|
||||
fn get_user_name(&self) -> String {
|
||||
self.user_name.clone()
|
||||
}
|
||||
fn set_user_name(&mut self, value: String) {
|
||||
self.user_name = value;
|
||||
self.emit.user_name_changed();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
extern crate libc;
|
||||
|
||||
mod types;
|
||||
pub mod interface;
|
||||
mod implementation;
|
|
@ -0,0 +1,184 @@
|
|||
use std::slice;
|
||||
use libc::{c_int, c_uint, uint8_t, uint16_t};
|
||||
use std::ptr::null;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QString {
|
||||
data: *const uint8_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QStringIn {
|
||||
data: *const uint16_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
impl QStringIn {
|
||||
pub fn convert(&self) -> String {
|
||||
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
|
||||
String::from_utf16_lossy(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a String> for QString {
|
||||
fn from(string: &'a String) -> QString {
|
||||
QString {
|
||||
len: string.len() as c_int,
|
||||
data: string.as_ptr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QByteArray {
|
||||
data: *const uint8_t,
|
||||
len: c_int,
|
||||
}
|
||||
|
||||
impl QByteArray {
|
||||
pub fn convert(&self) -> Vec<u8> {
|
||||
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
|
||||
Vec::from(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Vec<u8>> for QByteArray {
|
||||
fn from(value: &'a Vec<u8>) -> QByteArray {
|
||||
QByteArray {
|
||||
len: value.len() as c_int,
|
||||
data: value.as_ptr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Variant {
|
||||
None,
|
||||
Bool(bool),
|
||||
String(String),
|
||||
ByteArray(Vec<u8>),
|
||||
}
|
||||
|
||||
impl From<bool> for Variant {
|
||||
fn from(value: bool) -> Variant {
|
||||
Variant::Bool(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Variant {
|
||||
fn from(value: String) -> Variant {
|
||||
Variant::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
}
|
||||
pub fn convert(&self) -> Variant {
|
||||
// TODO
|
||||
Variant::None
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
Variant::ByteArray(ref v) => {
|
||||
QVariant {
|
||||
data: v.as_ptr(),
|
||||
len: v.len() as c_int,
|
||||
type_: VariantType::ByteArray 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 create(row: c_int, column: c_int, id: usize) -> QModelIndex {
|
||||
QModelIndex {
|
||||
row: row,
|
||||
column: column,
|
||||
internal_id: id,
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
pub fn row(&self) -> c_int {
|
||||
self.row
|
||||
}
|
||||
pub fn column(&self) -> c_int {
|
||||
self.column
|
||||
}
|
||||
pub fn id(&self) -> usize {
|
||||
self.internal_id
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#include "test_object_rust.h"
|
||||
#include <QTest>
|
||||
|
||||
class TestRustObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void testConstructor();
|
||||
void testStringGetter();
|
||||
void testStringSetter();
|
||||
};
|
||||
|
||||
void TestRustObject::testConstructor()
|
||||
{
|
||||
Person person;
|
||||
}
|
||||
|
||||
void TestRustObject::testStringGetter()
|
||||
{
|
||||
Person person;
|
||||
person.setUserName("Konqi");
|
||||
}
|
||||
|
||||
void TestRustObject::testStringSetter()
|
||||
{
|
||||
Person person;
|
||||
person.setUserName("Konqi");
|
||||
QCOMPARE(person.userName(), QString("Konqi"));
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestRustObject)
|
||||
#include "test_object.moc"
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"cppFile": "test_object_rust.cpp",
|
||||
"rust": {
|
||||
"dir": "rust_object",
|
||||
"interfaceModule": "interface",
|
||||
"implementationModule": "implementation"
|
||||
},
|
||||
"objects": [{
|
||||
"name": "Person",
|
||||
"type": "Object",
|
||||
"properties": [{
|
||||
"name": "userName",
|
||||
"type": "QString",
|
||||
"write": true
|
||||
}]
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#include "test_object_rust.h"
|
||||
#include <QModelIndex>
|
||||
|
||||
namespace {
|
||||
struct qbytearray_t {
|
||||
private:
|
||||
const char* data;
|
||||
int len;
|
||||
public:
|
||||
qbytearray_t(const QByteArray& v):
|
||||
data(v.data()),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QByteArray() const {
|
||||
return QByteArray(data, len);
|
||||
}
|
||||
};
|
||||
struct qstring_t {
|
||||
private:
|
||||
const void* data;
|
||||
int len;
|
||||
public:
|
||||
qstring_t(const QString& v):
|
||||
data(static_cast<const void*>(v.utf16())),
|
||||
len(v.size()) {
|
||||
}
|
||||
operator QString() const {
|
||||
return QString::fromUtf8(static_cast<const char*>(data), len);
|
||||
}
|
||||
};
|
||||
struct qmodelindex_t {
|
||||
int row;
|
||||
int column;
|
||||
uint64_t id;
|
||||
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::Bool: return QVariant((bool)v.value);
|
||||
case QVariant::String: return QString::fromUtf8(static_cast<const char*>(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) {
|
||||
*v = *val;
|
||||
}
|
||||
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_free(PersonInterface*);
|
||||
void person_user_name_get(PersonInterface*, QString*, qstring_set);
|
||||
void person_user_name_set(void*, qstring_t);
|
||||
};
|
||||
Person::Person(QObject *parent):
|
||||
QObject(parent),
|
||||
d(person_new(this,
|
||||
[](Person* o) { emit o->userNameChanged(); })) {}
|
||||
|
||||
Person::~Person() {
|
||||
person_free(d);
|
||||
}
|
||||
QString Person::userName() const
|
||||
{
|
||||
QString v;
|
||||
person_user_name_get(d, &v, set_qstring);
|
||||
return v;
|
||||
}
|
||||
void Person::setUserName(const QString& v) {
|
||||
person_user_name_set(d, v);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* generated by rust_qt_binding_generator */
|
||||
#ifndef TEST_OBJECT_RUST_H
|
||||
#define TEST_OBJECT_RUST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class PersonInterface;
|
||||
class Person : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
PersonInterface * const d;
|
||||
Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged FINAL)
|
||||
public:
|
||||
explicit Person(QObject *parent = nullptr);
|
||||
~Person();
|
||||
QString userName() const;
|
||||
void setUserName(const QString& v);
|
||||
signals:
|
||||
void userNameChanged();
|
||||
private:
|
||||
QString m_userName;
|
||||
};
|
||||
#endif // TEST_OBJECT_RUST_H
|
Loading…
Reference in New Issue