Add a test
parent
bced2e9ba3
commit
25d65e1b9e
|
@ -15,28 +15,13 @@ include(KDECMakeSettings)
|
||||||
include(KDECompilerSettings)
|
include(KDECompilerSettings)
|
||||||
include(FeatureSummary)
|
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)
|
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 Qt modules
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||||
Core # QCommandLineParser, QStringLiteral
|
Core # QCommandLineParser, QStringLiteral
|
||||||
Quick
|
Quick
|
||||||
|
Test
|
||||||
Widgets # QApplication
|
Widgets # QApplication
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,12 +36,38 @@ feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAG
|
||||||
|
|
||||||
add_subdirectory(rust_qt_binding_generator)
|
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)
|
set(RMail_SRCS src/main.cpp src/RMailObject.cpp src/tmp.cpp)
|
||||||
|
|
||||||
add_executable(RMail ${RMail_SRCS})
|
add_executable(RMail ${RMail_SRCS})
|
||||||
|
add_dependencies(RMail rust_target)
|
||||||
add_dependencies(RMail rust)
|
|
||||||
|
|
||||||
target_link_libraries(RMail
|
target_link_libraries(RMail
|
||||||
Qt5::Quick
|
Qt5::Quick
|
||||||
|
@ -64,8 +75,7 @@ target_link_libraries(RMail
|
||||||
KF5::CoreAddons
|
KF5::CoreAddons
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
KF5::WidgetsAddons
|
KF5::WidgetsAddons
|
||||||
debug "${CMAKE_SOURCE_DIR}/common-rust/target/debug/librust.a"
|
"${CMAKE_CURRENT_SOURCE_DIR}/common-rust/${RUST_TARGET_DIR}/librust.a"
|
||||||
optimized "${CMAKE_SOURCE_DIR}/common-rust/target/release/librust.a"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(RMail PROPERTIES
|
set_target_properties(RMail PROPERTIES
|
||||||
|
@ -74,3 +84,6 @@ set_target_properties(RMail PROPERTIES
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS RMail ${INSTALL_TARGETS_DEFAULT_ARGS})
|
install(TARGETS RMail ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||||
|
|
||||||
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
|
2
dev
2
dev
|
@ -1,3 +1,3 @@
|
||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
rm -rf __nix_qt5__/
|
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();
|
const QJsonObject o = doc.object();
|
||||||
Configuration c;
|
Configuration c;
|
||||||
c.cppFile = QFileInfo(base, o.value("cppFile").toString());
|
c.cppFile = QFileInfo(base, o.value("cppFile").toString());
|
||||||
|
QDir(c.cppFile.dir()).mkpath(".");
|
||||||
c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h");
|
c.hFile = QFileInfo(c.cppFile.dir(), c.cppFile.completeBaseName() + ".h");
|
||||||
for (const QJsonValue& val: o.value("objects").toArray()) {
|
for (const QJsonValue& val: o.value("objects").toArray()) {
|
||||||
c.objects.append(parseObject(val.toObject()));
|
c.objects.append(parseObject(val.toObject()));
|
||||||
|
|
|
@ -62,7 +62,7 @@ int main (int argc, char *argv[])
|
||||||
view.show();
|
view.show();
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("fsModel", &model);
|
engine.rootContext()->setContextProperty("fsModel", &model);
|
||||||
engine.load(QUrl(QStringLiteral("test.qml")));
|
engine.load(QUrl(QStringLiteral("../test.qml")));
|
||||||
|
|
||||||
return app.exec();
|
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