Closed #39 Add support for QVariantList

This adds support for marshalling arrays of QVariant (QVariantList) in/out from DosQVariant.
We added the following 3 API:
dos_qvariant_create_array
dos_qvariant_setArray
dos_qvariant_toArray

Support for QVariantList in property definition of QObjects is already enabled. The end
user should use the QVariantList metatype.
This commit is contained in:
Filippo Cucchetto 2016-07-04 18:20:02 +02:00
parent a86aa43a97
commit 819409fa94
7 changed files with 190 additions and 6 deletions

View File

@ -64,6 +64,9 @@ DOS_API void DOS_CALL dos_qqmlcontext_setcontextproperty(DosQQmlContext *vptr,
/// @param ptr The string
DOS_API void DOS_CALL dos_chararray_delete(char *ptr);
/// Delete a DosQVariantArray
DOS_API void DOS_CALL dos_qvariantarray_delete(DosQVariantArray *ptr);
// QVariant
DOS_API DosQVariant *DOS_CALL dos_qvariant_create();
DOS_API DosQVariant *DOS_CALL dos_qvariant_create_int(int value);
@ -73,12 +76,14 @@ DOS_API DosQVariant *DOS_CALL dos_qvariant_create_qobject(DosQObject *value);
DOS_API DosQVariant *DOS_CALL dos_qvariant_create_qvariant(const DosQVariant *value);
DOS_API DosQVariant *DOS_CALL dos_qvariant_create_float(float value);
DOS_API DosQVariant *DOS_CALL dos_qvariant_create_double(double value);
DOS_API DosQVariant *DOS_CALL dos_qvariant_create_array(int size, DosQVariant** array);
DOS_API void DOS_CALL dos_qvariant_setInt (DosQVariant *vptr, int value);
DOS_API void DOS_CALL dos_qvariant_setBool (DosQVariant *vptr, bool value);
DOS_API void DOS_CALL dos_qvariant_setFloat (DosQVariant *vptr, float value);
DOS_API void DOS_CALL dos_qvariant_setDouble (DosQVariant *vptr, double value);
DOS_API void DOS_CALL dos_qvariant_setString (DosQVariant *vptr, const char *value);
DOS_API void DOS_CALL dos_qvariant_setQObject(DosQVariant *vptr, DosQObject *value);
DOS_API void DOS_CALL dos_qvariant_setArray (DosQVariant *vptr, int size, DosQVariant** array);
DOS_API bool DOS_CALL dos_qvariant_isnull (const DosQVariant *vptr);
DOS_API void DOS_CALL dos_qvariant_delete (DosQVariant *vptr);
DOS_API void DOS_CALL dos_qvariant_assign (DosQVariant *vptr, const DosQVariant *other);
@ -87,6 +92,7 @@ DOS_API bool DOS_CALL dos_qvariant_toBool (const DosQVariant *vptr);
DOS_API char *DOS_CALL dos_qvariant_toString (const DosQVariant *vptr);
DOS_API float DOS_CALL dos_qvariant_toFloat (const DosQVariant *vptr);
DOS_API double DOS_CALL dos_qvariant_toDouble (const DosQVariant *vptr);
DOS_API DosQVariantArray* DOS_CALL dos_qvariant_toArray(const DosQVariant *vptr);
DOS_API DosQObject *DOS_CALL dos_qvariant_toQObject(const DosQVariant *vptr);
// QMetaObject

View File

@ -62,6 +62,11 @@ typedef void (DOS_CALL *HeaderDataCallback) (void *self, int section, int orie
typedef void (DOS_CALL *CreateDObject)(int, void *, void **, void **);
typedef void (DOS_CALL *DeleteDObject)(int, void *);
struct DosQVariantArray {
int size;
DosQVariant** data;
};
struct QmlRegisterType {
int major;
int minor;

View File

@ -179,6 +179,21 @@ void dos_chararray_delete(char *ptr)
if (ptr) delete[] ptr;
}
void dos_qvariantarray_delete(DosQVariantArray *ptr)
{
if (!ptr || !ptr->data)
return;
// Delete each variant
for (int i = 0; i < ptr->size; ++i)
dos_qvariant_delete(ptr->data[i]);
// Delete the array
delete[] ptr->data;
ptr->data = nullptr;
ptr->size = 0;
// Delete the wrapped struct
delete ptr;
}
char *dos_qqmlcontext_baseUrl(const ::DosQQmlContext *vptr)
{
auto context = static_cast<const QQmlContext *>(vptr);
@ -239,6 +254,15 @@ void dos_qqmlcontext_setcontextproperty(::DosQQmlContext *vptr, const char *name
return new QVariant(value);
}
::DosQVariant *dos_qvariant_create_array(int size, ::DosQVariant** array)
{
QList<QVariant> data;
data.reserve(size);
for (int i = 0; i < size; ++i)
data << *(static_cast<QVariant*>(array[i]));
return new QVariant(data);
}
bool dos_qvariant_isnull(const DosQVariant *vptr)
{
auto variant = static_cast<const QVariant *>(vptr);
@ -288,6 +312,18 @@ char *dos_qvariant_toString(const DosQVariant *vptr)
return convert_to_cstring(variant->toString());
}
DosQVariantArray *dos_qvariant_toArray(const DosQVariant *vptr)
{
auto variant = static_cast<const QVariant *>(vptr);
QVariantList data = variant->toList();
auto result = new DosQVariantArray();
result->size = data.size();
result->data = new DosQVariant*[result->size];
for (int i = 0; i < result->size; ++i)
result->data[i] = new QVariant(data[i]);
return result;
}
::DosQObject *dos_qvariant_toQObject(const DosQVariant *vptr)
{
auto variant = static_cast<const QVariant *>(vptr);
@ -331,6 +367,16 @@ void dos_qvariant_setQObject(::DosQVariant *vptr, ::DosQObject *value)
variant->setValue<QObject *>(qobject);
}
void dos_qvariant_setArray(::DosQVariant *vptr, int size, ::DosQVariant **array)
{
auto variant = static_cast<QVariant *>(vptr);
QVariantList data;
data.reserve(size);
for (int i = 0; i < size; ++i)
data << *(static_cast<QVariant *>(array[i]));
variant->setValue(data);
}
::DosQMetaObject *dos_qobject_qmetaobject()
{
return new DOS::DosIQMetaObjectHolder(std::make_shared<DOS::DosQObjectMetaObject>());

View File

@ -14,19 +14,28 @@ namespace {
{
void* superClassMetaObject = dos_qobject_qmetaobject();
// Signals
::SignalDefinition signalDefinitionArray[1];
::SignalDefinition signalDefinitionArray[2];
// nameChanged
signalDefinitionArray[0].name = "nameChanged";
signalDefinitionArray[0].parametersCount = 1;
int nameChanged[1];
nameChanged[0] = QMetaType::QString;
signalDefinitionArray[0].parametersMetaTypes = nameChanged;
// arrayPropertyChanged
signalDefinitionArray[1].name = "arrayPropertyChanged";
signalDefinitionArray[1].parametersCount = 1;
int arrayPropertyChanged[1];
arrayPropertyChanged[0] = QMetaType::QVariantList;
signalDefinitionArray[1].parametersMetaTypes = arrayPropertyChanged;
::SignalDefinitions signalDefinitions;
signalDefinitions.count = 1;
signalDefinitions.count = 2;
signalDefinitions.definitions = signalDefinitionArray;
// Slots
::SlotDefinition slotDefinitionArray[2];
::SlotDefinition slotDefinitionArray[4];
slotDefinitionArray[0].name = "name";
slotDefinitionArray[0].returnMetaType = QMetaType::QString;
@ -40,20 +49,38 @@ namespace {
slotDefinitionArray[1].parametersCount = 1;
slotDefinitionArray[1].parametersMetaTypes = setNameParameters;
slotDefinitionArray[2].name = "arrayProperty";
slotDefinitionArray[2].returnMetaType = QMetaType::QVariantList;
slotDefinitionArray[2].parametersCount = 0;
slotDefinitionArray[2].parametersMetaTypes = nullptr;
slotDefinitionArray[3].name = "setArrayProperty";
slotDefinitionArray[3].returnMetaType = QMetaType::Void;
int setArrayPropertyParameters[1];
setArrayPropertyParameters[0] = QMetaType::QVariantList;
slotDefinitionArray[3].parametersCount = 1;
slotDefinitionArray[3].parametersMetaTypes = setArrayPropertyParameters;
::SlotDefinitions slotDefinitions;
slotDefinitions.count = 2;
slotDefinitions.count = 4;
slotDefinitions.definitions = slotDefinitionArray;
// Properties
::PropertyDefinition propertyDefinitionArray[1];
::PropertyDefinition propertyDefinitionArray[2];
propertyDefinitionArray[0].name = "name";
propertyDefinitionArray[0].notifySignal = "nameChanged";
propertyDefinitionArray[0].propertyMetaType = QMetaType::QString;
propertyDefinitionArray[0].readSlot = "name";
propertyDefinitionArray[0].writeSlot = "setName";
propertyDefinitionArray[1].name = "arrayProperty";
propertyDefinitionArray[1].notifySignal = "arrayPropertyChanged";
propertyDefinitionArray[1].propertyMetaType = QMetaType::QVariantList;
propertyDefinitionArray[1].readSlot = "arrayProperty";
propertyDefinitionArray[1].writeSlot = "setArrayProperty";
::PropertyDefinitions propertyDefinitions;
propertyDefinitions.count = 1;
propertyDefinitions.count = 2;
propertyDefinitions.definitions = propertyDefinitionArray;
return VoidPointer(dos_qmetaobject_create(superClassMetaObject, "MockQObject", &signalDefinitions, &slotDefinitions, &propertyDefinitions),
@ -64,6 +91,7 @@ namespace {
MockQObject::MockQObject()
: m_vptr(dos_qobject_create(this, metaObject(), &onSlotCalled), &dos_qobject_delete)
, m_arrayProperty({10, 5.3, false})
{}
MockQObject::~MockQObject() = default;
@ -122,6 +150,35 @@ void MockQObject::nameChanged(const string &name)
dos_qvariant_delete(argv[0]);
}
std::tuple<int, double, bool> MockQObject::arrayProperty() const
{
return m_arrayProperty;
}
void MockQObject::setArrayProperty(std::tuple<int, double, bool> value)
{
if (m_arrayProperty == value)
return;
m_arrayProperty = std::move(value);
arrayPropertyChanged(value);
}
void MockQObject::arrayPropertyChanged(const std::tuple<int, double, bool> &value)
{
std::vector<DosQVariant*> valueAsDosQVariant ({
dos_qvariant_create_int(std::get<0>(value)),
dos_qvariant_create_double(std::get<1>(value)),
dos_qvariant_create_bool(std::get<2>(value))
});
int argc = 1;
DosQVariant* argv[1];
argv[0] = dos_qvariant_create_array(valueAsDosQVariant.size(), &valueAsDosQVariant[0]);
dos_qobject_signal_emit(m_vptr.get(), "arrayPropertyChanged", argc, argv);
dos_qvariant_delete(argv[0]);
std::for_each(valueAsDosQVariant.begin(), valueAsDosQVariant.end(), &dos_qvariant_delete);
}
void MockQObject::onSlotCalled(void *selfVPtr, DosQVariant *dosSlotNameVariant, int dosSlotArgc, DosQVariant **dosSlotArgv) {
MockQObject* self = static_cast<MockQObject*>(selfVPtr);
@ -136,4 +193,29 @@ void MockQObject::onSlotCalled(void *selfVPtr, DosQVariant *dosSlotNameVariant,
self->setName(toStringFromQVariant(dosSlotArgv[1]));
return;
}
if (slotName == "arrayProperty") {
auto value = self->arrayProperty();
std::vector<DosQVariant*> data {
dos_qvariant_create_int(std::get<0>(value)),
dos_qvariant_create_double(std::get<1>(value)),
dos_qvariant_create_bool(std::get<2>(value))
};
VoidPointer arrayProperty(dos_qvariant_create_array(data.size(), &data[0]), &dos_qvariant_delete);
dos_qvariant_assign(dosSlotArgv[0], arrayProperty.get());
std::for_each(data.begin(), data.end(), &dos_qvariant_delete);
return;
}
if (slotName == "setArrayProperty") {
std::tuple<int, double, bool> value;
DosQVariantArray* array = dos_qvariant_toArray(dosSlotArgv[1]);
std::get<0>(value) = dos_qvariant_toInt(array->data[0]);
std::get<1>(value) = dos_qvariant_toDouble(array->data[1]);
std::get<2>(value) = dos_qvariant_toBool(array->data[2]);
dos_qvariantarray_delete(array);
self->setArrayProperty(std::move(value));
return;
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <tuple>
#include <Global.h>
class MockQObject
@ -21,9 +22,14 @@ public:
void setName(const std::string& name);
void nameChanged(const std::string& name);
std::tuple<int, double, bool> arrayProperty() const;
void setArrayProperty(std::tuple<int, double, bool> value);
void arrayPropertyChanged(const std::tuple<int, double, bool>& value);
private:
static void onSlotCalled(void *selfVPtr, DosQVariant *dosSlotNameVariant, int dosSlotArgc, DosQVariant **dosSlotArgv);
VoidPointer m_vptr;
std::string m_name;
std::tuple<int, double, bool> m_arrayProperty;
};

View File

@ -29,4 +29,14 @@ QtObject {
testObject.name = "bar"
return result
}
function testArrayProperty() {
if (!testObject)
return false
var values = testObject.arrayProperty
if (values[0] != 10 || values[1] != 5.3 || values[2] != false)
return false
testObject.arrayProperty = [404, 6.3, true]
return values[0] != 404 || values[1] != 6.3 || values[2] != true
}
}

View File

@ -184,6 +184,26 @@ private slots:
QVERIFY(value == nullptr);
}
void testArray() {
std::vector<DosQVariant*> data ({
dos_qvariant_create_int(10),
dos_qvariant_create_double(4.3),
dos_qvariant_create_bool(false),
dos_qvariant_create_string("FooBar")
});
VoidPointer variant (dos_qvariant_create_array(data.size(), &data[0]), &dos_qvariant_delete);
DosQVariantArray* array = dos_qvariant_toArray(variant.get());
QVERIFY(array);
QCOMPARE(int(data.size()), array->size);
QCOMPARE(dos_qvariant_toInt(array->data[0]), int(10));
QCOMPARE(dos_qvariant_toDouble(array->data[1]), double(4.3));
QCOMPARE(dos_qvariant_toBool(array->data[2]), false);
dos_qvariantarray_delete(array);
std::for_each(data.begin(), data.end(), &dos_qvariant_delete);
}
};
/*
@ -388,6 +408,15 @@ private slots:
QVERIFY(result.toBool());
}
void testArrayProperty() {
QObject* testCase = engine->rootObjects().first();
QVERIFY(testCase);
QVariant result;
QVERIFY(QMetaObject::invokeMethod(testCase, "testArrayProperty", Q_RETURN_ARG(QVariant, result)));
QVERIFY(result.type() == QVariant::Bool);
QVERIFY(result.toBool());
}
private:
QString value;
unique_ptr<MockQObject> testObject;