mirror of
https://github.com/qmlnet/qmlnet.git
synced 2026-05-21 06:45:32 -06:00
Added support for interacting with QObjects.
This commit is contained in:
parent
e7a228a36f
commit
a0afc0506f
35 changed files with 2052 additions and 27 deletions
|
|
@ -50,6 +50,7 @@ enum NetVariantTypeEnum {
|
||||||
NetVariantTypeEnum_DateTime,
|
NetVariantTypeEnum_DateTime,
|
||||||
NetVariantTypeEnum_Object,
|
NetVariantTypeEnum_Object,
|
||||||
NetVariantTypeEnum_JSValue,
|
NetVariantTypeEnum_JSValue,
|
||||||
|
NetVariantTypeEnum_QObject
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
344
src/native/QmlNet/QmlNet/qml/NetQObject.cpp
Normal file
344
src/native/QmlNet/QmlNet/qml/NetQObject.cpp
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
#include <QmlNet/qml/NetQObject.h>
|
||||||
|
#include <QmlNet/qml/NetQObjectSignalConnection.h>
|
||||||
|
#include <QmlNet/qml/NetQObjectArg.h>
|
||||||
|
#include <QmlNet/types/NetDelegate.h>
|
||||||
|
#include <QmlNet/types/Callbacks.h>
|
||||||
|
#include <QMetaMethod>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
NetQObject::NetQObject(QObject* qObject, bool ownsObject) :
|
||||||
|
_qObject(qObject),
|
||||||
|
_ownsObject(ownsObject)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObject::~NetQObject()
|
||||||
|
{
|
||||||
|
if(_ownsObject) {
|
||||||
|
_qObject->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* NetQObject::getQObject()
|
||||||
|
{
|
||||||
|
return _qObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetVariant> NetQObject::getProperty(QString propertyName, bool* wasSuccess)
|
||||||
|
{
|
||||||
|
QSharedPointer<NetVariant> netVariant;
|
||||||
|
QByteArray propertyNameLocal = propertyName.toLocal8Bit();
|
||||||
|
|
||||||
|
if(_qObject->metaObject()->indexOfProperty(propertyNameLocal.data()) == -1) {
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant result = _qObject->property(propertyNameLocal.data());
|
||||||
|
if(!result.isNull()) {
|
||||||
|
netVariant = QSharedPointer<NetVariant>(new NetVariant());
|
||||||
|
NetVariant::fromQVariant(&result, netVariant);
|
||||||
|
}
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = true;
|
||||||
|
}
|
||||||
|
return netVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetQObject::setProperty(QString propertyName, QSharedPointer<NetVariant> value, bool* wasSuccess)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
if(value == nullptr) {
|
||||||
|
result = _qObject->setProperty(propertyName.toLocal8Bit().data(), QVariant());
|
||||||
|
} else {
|
||||||
|
result = _qObject->setProperty(propertyName.toLocal8Bit().data(), value->toQVariant());
|
||||||
|
}
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetVariant> NetQObject::invokeMethod(QString methodName, QSharedPointer<NetVariantList> parameters, bool* wasSuccess)
|
||||||
|
{
|
||||||
|
int parameterCount = 0;
|
||||||
|
if(parameters != nullptr) {
|
||||||
|
parameterCount = parameters->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the best method
|
||||||
|
int methodIndex = -1;
|
||||||
|
QMetaMethod method;
|
||||||
|
for(int x = 0; x < _qObject->metaObject()->methodCount(); x++) {
|
||||||
|
method = _qObject->metaObject()->method(x);
|
||||||
|
if(method.methodType() == QMetaMethod::Slot || method.methodType() == QMetaMethod::Method) {
|
||||||
|
if(methodName.compare(method.name()) == 0) {
|
||||||
|
// make sure number of parameters match
|
||||||
|
if(method.parameterCount() == parameterCount) {
|
||||||
|
methodIndex = x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(methodIndex == -1) {
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(parameterCount > 10) {
|
||||||
|
qWarning() << "Attempting to invoke a method with too many parameters: current: " << parameters->count() << " expected: <=10";
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectArg returnValue(method.returnType());
|
||||||
|
NetQObjectArg val0;
|
||||||
|
NetQObjectArg val1;
|
||||||
|
NetQObjectArg val2;
|
||||||
|
NetQObjectArg val3;
|
||||||
|
NetQObjectArg val4;
|
||||||
|
NetQObjectArg val5;
|
||||||
|
NetQObjectArg val6;
|
||||||
|
NetQObjectArg val7;
|
||||||
|
NetQObjectArg val8;
|
||||||
|
NetQObjectArg val9;
|
||||||
|
|
||||||
|
if(parameterCount >= 1) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(0), parameters->get(0));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 2) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(1), parameters->get(1));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 3) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(2), parameters->get(2));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 4) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(3), parameters->get(3));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 5) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(4), parameters->get(4));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 6) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(5), parameters->get(5));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 7) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(6), parameters->get(6));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 8) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(7), parameters->get(7));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 9) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(8), parameters->get(8));
|
||||||
|
}
|
||||||
|
if(parameterCount >= 10) {
|
||||||
|
val0 = NetQObjectArg(method.parameterType(9), parameters->get(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!method.invoke(_qObject,
|
||||||
|
Qt::DirectConnection,
|
||||||
|
returnValue.genericReturnArguemnet(),
|
||||||
|
val0.genericArgument(),
|
||||||
|
val1.genericArgument(),
|
||||||
|
val2.genericArgument(),
|
||||||
|
val3.genericArgument(),
|
||||||
|
val4.genericArgument(),
|
||||||
|
val5.genericArgument(),
|
||||||
|
val6.genericArgument(),
|
||||||
|
val7.genericArgument(),
|
||||||
|
val8.genericArgument(),
|
||||||
|
val9.genericArgument())) {
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wasSuccess) {
|
||||||
|
*wasSuccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue.unpack();
|
||||||
|
return returnValue.getNetVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> NetQObject::attachSignal(QString signalName, QSharedPointer<NetReference> delegate, bool* wasSucessful)
|
||||||
|
{
|
||||||
|
int signalMethodIndex = -1;
|
||||||
|
QMetaMethod signalMethod;
|
||||||
|
for(int x = 0; x <_qObject->metaObject()->methodCount(); x++) {
|
||||||
|
signalMethod = _qObject->metaObject()->method(x);
|
||||||
|
if(signalMethod.methodType() == QMetaMethod::Signal) {
|
||||||
|
if(signalName.compare(signalMethod.name()) == 0) {
|
||||||
|
signalMethodIndex = x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If signal not found, dump the registered signals for debugging.
|
||||||
|
if(signalMethodIndex < 0) {
|
||||||
|
if(wasSucessful) {
|
||||||
|
*wasSucessful = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> signalConnection = QSharedPointer<NetQObjectSignalConnection>(new NetQObjectSignalConnection(delegate, _qObject));
|
||||||
|
QMetaObject::Connection connection = QObject::connect(_qObject,
|
||||||
|
signalMethod,
|
||||||
|
signalConnection.data(),
|
||||||
|
signalConnection->getSignalHandler());
|
||||||
|
|
||||||
|
if(!connection) {
|
||||||
|
if(wasSucessful) {
|
||||||
|
*wasSucessful = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wasSucessful) {
|
||||||
|
*wasSucessful = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return signalConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> NetQObject::attachNotifySignal(QString propertyName, QSharedPointer<NetReference> delegate, bool* wasSuccessful)
|
||||||
|
{
|
||||||
|
int propertyIndex = _qObject->metaObject()->indexOfProperty(propertyName.toLocal8Bit().data());
|
||||||
|
if(propertyIndex == -1) {
|
||||||
|
if(wasSuccessful) {
|
||||||
|
*wasSuccessful = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaProperty property = _qObject->metaObject()->property(propertyIndex);
|
||||||
|
|
||||||
|
if(property.notifySignalIndex() == -1) {
|
||||||
|
if(wasSuccessful) {
|
||||||
|
*wasSuccessful = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> signalConnection = QSharedPointer<NetQObjectSignalConnection>(new NetQObjectSignalConnection(delegate, _qObject));
|
||||||
|
QMetaObject::Connection connection = QObject::connect(_qObject,
|
||||||
|
property.notifySignal(),
|
||||||
|
signalConnection.data(),
|
||||||
|
signalConnection->getSignalHandler());
|
||||||
|
|
||||||
|
if(!connection) {
|
||||||
|
if(wasSuccessful) {
|
||||||
|
*wasSuccessful = false;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wasSuccessful) {
|
||||||
|
*wasSuccessful = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return signalConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void net_qobject_destroy(NetQObjectContainer* qObjectContainer)
|
||||||
|
{
|
||||||
|
delete qObjectContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT NetVariantContainer* net_qobject_getProperty(NetQObjectContainer* qObjectContainer, LPWCSTR propertyName, uchar* result)
|
||||||
|
{
|
||||||
|
bool wasSuccesful = false;
|
||||||
|
auto value = qObjectContainer->qObject->getProperty(QString::fromUtf16(propertyName), &wasSuccesful);
|
||||||
|
if(wasSuccesful) {
|
||||||
|
*result = 1;
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if(value == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new NetVariantContainer{ value };
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void net_qobject_setProperty(NetQObjectContainer* qObjectContainer, LPWCSTR propertyName, NetVariantContainer* netVariantContainer, uchar* result)
|
||||||
|
{
|
||||||
|
bool wasSuccesful = false;
|
||||||
|
if(netVariantContainer == nullptr) {
|
||||||
|
qObjectContainer->qObject->setProperty(QString::fromUtf16(propertyName), nullptr, &wasSuccesful);
|
||||||
|
} else {
|
||||||
|
qObjectContainer->qObject->setProperty(QString::fromUtf16(propertyName), netVariantContainer->variant, &wasSuccesful);
|
||||||
|
}
|
||||||
|
if(wasSuccesful) {
|
||||||
|
*result = 1;
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT NetVariantContainer* net_qobject_invokeMethod(NetQObjectContainer* qObjectContainer, LPWCSTR methodName, NetVariantListContainer* parametersContainer, uchar* result)
|
||||||
|
{
|
||||||
|
QSharedPointer<NetVariantList> parameters = nullptr;
|
||||||
|
if(parametersContainer != nullptr) {
|
||||||
|
parameters = parametersContainer->list;
|
||||||
|
}
|
||||||
|
bool wasSuccesful = false;
|
||||||
|
auto value = qObjectContainer->qObject->invokeMethod(QString::fromUtf16(methodName), parameters, &wasSuccesful);
|
||||||
|
if(wasSuccesful) {
|
||||||
|
*result = 1;
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if(value == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new NetVariantContainer { value };
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT NetQObjectSignalConnectionContainer* net_qobject_attachSignal(NetQObjectContainer* qObjectContainer, LPWCSTR signalName, NetReferenceContainer* delegate, uchar* result)
|
||||||
|
{
|
||||||
|
bool wasSuccesful = false;
|
||||||
|
auto signalConnection = qObjectContainer->qObject->attachSignal(QString::fromUtf16(signalName), delegate->instance, &wasSuccesful);
|
||||||
|
if(wasSuccesful) {
|
||||||
|
*result = 1;
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if(signalConnection == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new NetQObjectSignalConnectionContainer { signalConnection };
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT NetQObjectSignalConnectionContainer* net_qobject_attachNotifySignal(NetQObjectContainer* qObjectContainer, LPWCSTR propertyName, NetReferenceContainer* delegate, uchar* result)
|
||||||
|
{
|
||||||
|
bool wasSuccesful = false;
|
||||||
|
auto signalConnection = qObjectContainer->qObject->attachNotifySignal(QString::fromUtf16(propertyName), delegate->instance, &wasSuccesful);
|
||||||
|
if(wasSuccesful) {
|
||||||
|
*result = 1;
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
if(signalConnection == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new NetQObjectSignalConnectionContainer { signalConnection };
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void net_qobject_signal_handler_destroy(NetQObjectSignalConnectionContainer* signalContainer)
|
||||||
|
{
|
||||||
|
delete signalContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
src/native/QmlNet/QmlNet/qml/NetQObject.h
Normal file
32
src/native/QmlNet/QmlNet/qml/NetQObject.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef NETQOBJECT_H
|
||||||
|
#define NETQOBJECT_H
|
||||||
|
|
||||||
|
#include <QmlNet.h>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class NetVariant;
|
||||||
|
class NetVariantList;
|
||||||
|
class NetQObjectSignalConnection;
|
||||||
|
class NetReference;
|
||||||
|
|
||||||
|
class NetQObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetQObject(QObject* qObject, bool ownsObject = false);
|
||||||
|
~NetQObject();
|
||||||
|
QObject* getQObject();
|
||||||
|
QSharedPointer<NetVariant> getProperty(QString propertyName, bool* wasSuccess);
|
||||||
|
void setProperty(QString propertyName, QSharedPointer<NetVariant> value, bool* wasSuccess);
|
||||||
|
QSharedPointer<NetVariant> invokeMethod(QString methodName, QSharedPointer<NetVariantList> parameters, bool* wasSuccess);
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> attachSignal(QString signalName, QSharedPointer<NetReference> delegate, bool* wasSuccess);
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> attachNotifySignal(QString propertyName, QSharedPointer<NetReference> delegate, bool* wasSuccess);
|
||||||
|
private:
|
||||||
|
QObject* _qObject;
|
||||||
|
bool _ownsObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetQObjectContainer {
|
||||||
|
QSharedPointer<NetQObject> qObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETQOBJECT_H
|
||||||
139
src/native/QmlNet/QmlNet/qml/NetQObjectArg.cpp
Normal file
139
src/native/QmlNet/QmlNet/qml/NetQObjectArg.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
#include <QmlNet/qml/NetQObjectArg.h>
|
||||||
|
#include <QmlNet/qml/NetVariant.h>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
NetQObjectArg::NetQObjectArg() :
|
||||||
|
_metaTypeId(QMetaType::Void),
|
||||||
|
_data(nullptr)
|
||||||
|
{
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectArg::NetQObjectArg(const int metaTypeId, QSharedPointer<NetVariant> netVariant) :
|
||||||
|
_metaTypeId(metaTypeId),
|
||||||
|
_data(nullptr),
|
||||||
|
_netVariant(netVariant)
|
||||||
|
{
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectArg::~NetQObjectArg()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QGenericArgument NetQObjectArg::genericArgument()
|
||||||
|
{
|
||||||
|
if(_metaTypeId == QMetaType::Void) {
|
||||||
|
return QGenericArgument();
|
||||||
|
}
|
||||||
|
if(_metaTypeId == QMetaType::QVariant) {
|
||||||
|
return QGenericArgument("QVariant", &_variant);
|
||||||
|
}
|
||||||
|
return QGenericArgument(_variant.typeName(), _variant.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
QGenericReturnArgument NetQObjectArg::genericReturnArguemnet()
|
||||||
|
{
|
||||||
|
if(_metaTypeId == QMetaType::Void) {
|
||||||
|
return QGenericReturnArgument();
|
||||||
|
}
|
||||||
|
if(_metaTypeId == QMetaType::QVariant) {
|
||||||
|
return QGenericReturnArgument("QVariant", &_variant);
|
||||||
|
}
|
||||||
|
return QGenericReturnArgument(_variant.typeName(), _variant.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetVariant> NetQObjectArg::getNetVariant()
|
||||||
|
{
|
||||||
|
return _netVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetQObjectArg::pack()
|
||||||
|
{
|
||||||
|
if(_netVariant == nullptr) {
|
||||||
|
switch(_metaTypeId) {
|
||||||
|
case QMetaType::Void:
|
||||||
|
break;
|
||||||
|
case QMetaType::QVariant:
|
||||||
|
_variant = QVariant();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_variant = QVariant(_metaTypeId, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_metaTypeId) {
|
||||||
|
case QMetaType::Void:
|
||||||
|
break;
|
||||||
|
case QMetaType::QVariant:
|
||||||
|
_variant = _netVariant->toQVariant();
|
||||||
|
break;
|
||||||
|
case QMetaType::Bool:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getBool());
|
||||||
|
break;
|
||||||
|
case QMetaType::QChar:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getChar());
|
||||||
|
break;
|
||||||
|
case qMetaTypeId<qint32>():
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getInt());
|
||||||
|
break;
|
||||||
|
case qMetaTypeId<quint32>():
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getUInt());
|
||||||
|
break;
|
||||||
|
case qMetaTypeId<qint64>():
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getLong());
|
||||||
|
break;
|
||||||
|
case qMetaTypeId<quint64>():
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getULong());
|
||||||
|
break;
|
||||||
|
case QMetaType::Long:
|
||||||
|
_variant = QVariant::fromValue<long>(static_cast<long>(_netVariant->getLong()));
|
||||||
|
break;
|
||||||
|
case QMetaType::ULong:
|
||||||
|
_variant = QVariant::fromValue<ulong>(static_cast<ulong>(_netVariant->getULong()));
|
||||||
|
break;
|
||||||
|
case QMetaType::Float:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getFloat());
|
||||||
|
break;
|
||||||
|
case QMetaType::Double:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getDouble());
|
||||||
|
break;
|
||||||
|
case QMetaType::QString:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getString());
|
||||||
|
break;
|
||||||
|
case QMetaType::QDateTime:
|
||||||
|
_variant = QVariant::fromValue(_netVariant->getDateTime());
|
||||||
|
break;
|
||||||
|
case QMetaType::QObjectStar:
|
||||||
|
switch(_netVariant->getVariantType()) {
|
||||||
|
case NetVariantTypeEnum_Invalid:
|
||||||
|
_variant = QVariant::fromValue<QObject*>(nullptr);
|
||||||
|
break;
|
||||||
|
case NetVariantTypeEnum_Object:
|
||||||
|
case NetVariantTypeEnum_QObject:
|
||||||
|
_variant = _netVariant->toQVariant();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning() << "Unabled to convert " << _netVariant->getVariantType() << " to QObject*";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning() << "Unsupported type: " << QMetaType::typeName(_metaTypeId);
|
||||||
|
_variant = QVariant(_metaTypeId, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetQObjectArg::unpack()
|
||||||
|
{
|
||||||
|
if(_metaTypeId == QMetaType::Void) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(_netVariant == nullptr) {
|
||||||
|
_netVariant = QSharedPointer<NetVariant>(new NetVariant());
|
||||||
|
}
|
||||||
|
NetVariant::fromQVariant(&_variant, _netVariant);
|
||||||
|
}
|
||||||
28
src/native/QmlNet/QmlNet/qml/NetQObjectArg.h
Normal file
28
src/native/QmlNet/QmlNet/qml/NetQObjectArg.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef NETQOBJECTARG_H
|
||||||
|
#define NETQOBJECTARG_H
|
||||||
|
|
||||||
|
#include <QMetaMethod>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class NetVariant;
|
||||||
|
|
||||||
|
class NetQObjectArg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetQObjectArg();
|
||||||
|
NetQObjectArg(int metaTypeId, QSharedPointer<NetVariant> netVariant = nullptr);
|
||||||
|
~NetQObjectArg();
|
||||||
|
QGenericArgument genericArgument();
|
||||||
|
QGenericReturnArgument genericReturnArguemnet();
|
||||||
|
QSharedPointer<NetVariant> getNetVariant();
|
||||||
|
void pack();
|
||||||
|
void unpack();
|
||||||
|
private:
|
||||||
|
int _metaTypeId;
|
||||||
|
void* _data;
|
||||||
|
int test;
|
||||||
|
QVariant _variant;
|
||||||
|
QSharedPointer<NetVariant> _netVariant;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETQOBJECTARG_H
|
||||||
65
src/native/QmlNet/QmlNet/qml/NetQObjectSignalConnection.cpp
Normal file
65
src/native/QmlNet/QmlNet/qml/NetQObjectSignalConnection.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include <QmlNet/qml/NetQObjectSignalConnection.h>
|
||||||
|
#include <QmlNet/qml/NetVariant.h>
|
||||||
|
#include <QmlNet/qml/NetVariantList.h>
|
||||||
|
#include <QmlNet/types/Callbacks.h>
|
||||||
|
#include <QMetaMethod>
|
||||||
|
|
||||||
|
NetQObjectSignalConnectionBase::NetQObjectSignalConnectionBase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectSignalConnectionBase::~NetQObjectSignalConnectionBase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaMethod NetQObjectSignalConnectionBase::getSignalHandler()
|
||||||
|
{
|
||||||
|
return metaObject()->method(metaObject()->methodOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetQObjectSignalConnectionBase::signalRaised()
|
||||||
|
{
|
||||||
|
// Dummy, handled in NetQObjectSignalConnection::qt_metacall()
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectSignalConnection::NetQObjectSignalConnection(QSharedPointer<NetReference> delegate,
|
||||||
|
QObject* qObject)
|
||||||
|
: _delegate(delegate),
|
||||||
|
_qObject(qObject)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQObjectSignalConnection::~NetQObjectSignalConnection()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int NetQObjectSignalConnection::qt_metacall(QMetaObject::Call c, int id, void** a)
|
||||||
|
{
|
||||||
|
if(c == QMetaObject::InvokeMetaMethod) {
|
||||||
|
int offset = this->metaObject()->methodOffset();
|
||||||
|
if(id < offset) {
|
||||||
|
return QObject::qt_metacall(c, id, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->metaObject()->indexOfSlot("signalRaised()") == id) {
|
||||||
|
QMetaMethod signal = _qObject->metaObject()->method(senderSignalIndex());
|
||||||
|
|
||||||
|
// Convert signal args to QVariantList
|
||||||
|
QSharedPointer<NetVariantList> netParameters = QSharedPointer<NetVariantList>(new NetVariantList());
|
||||||
|
for (int i = 0; i < signal.parameterCount(); ++i) {
|
||||||
|
QVariant arg = QVariant(signal.parameterType(i), a[i+1]);
|
||||||
|
netParameters->add(NetVariant::fromQVariant(&arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlNet::invokeDelegate(_delegate, netParameters);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
35
src/native/QmlNet/QmlNet/qml/NetQObjectSignalConnection.h
Normal file
35
src/native/QmlNet/QmlNet/qml/NetQObjectSignalConnection.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef NETQOBJECTSIGNALCONNECTION_H
|
||||||
|
#define NETQOBJECTSIGNALCONNECTION_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class NetReference;
|
||||||
|
|
||||||
|
class NetQObjectSignalConnectionBase : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
NetQObjectSignalConnectionBase();
|
||||||
|
~NetQObjectSignalConnectionBase();
|
||||||
|
QMetaMethod getSignalHandler();
|
||||||
|
public slots:
|
||||||
|
void signalRaised();
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetQObjectSignalConnection : public NetQObjectSignalConnectionBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetQObjectSignalConnection(QSharedPointer<NetReference> delegate, QObject* qObject);
|
||||||
|
~NetQObjectSignalConnection() override;
|
||||||
|
int qt_metacall(QMetaObject::Call c, int id, void** a) override;
|
||||||
|
private:
|
||||||
|
QSharedPointer<NetReference> _delegate;
|
||||||
|
QObject* _qObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetQObjectSignalConnectionContainer {
|
||||||
|
QSharedPointer<NetQObjectSignalConnection> signalConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETQOBJECTSIGNALCONNECTION_H
|
||||||
|
|
@ -2,12 +2,176 @@
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
TestQObject::TestQObject()
|
||||||
|
: QObject(nullptr),
|
||||||
|
_writeOnly(0),
|
||||||
|
_readAndWrite(0),
|
||||||
|
_propWithSignal(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TestQObject::~TestQObject()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestQObject::getReadOnly()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::setWriteOnly(int value)
|
||||||
|
{
|
||||||
|
_writeOnly = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestQObject::getReadAndWrite()
|
||||||
|
{
|
||||||
|
return _readAndWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::setReadAndWrite(int value)
|
||||||
|
{
|
||||||
|
_readAndWrite = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestQObject::getPropWithSignal()
|
||||||
|
{
|
||||||
|
return _propWithSignal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::setPropWithSignal(int value)
|
||||||
|
{
|
||||||
|
if(value == _propWithSignal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_propWithSignal = value;
|
||||||
|
emit propWithSignalChanged(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TestQObject::getVariantProperty()
|
||||||
|
{
|
||||||
|
return _variantValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::setVariantProperty(QVariant value)
|
||||||
|
{
|
||||||
|
_variantValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::testSlot()
|
||||||
|
{
|
||||||
|
emit testSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQObject::testSlotWithArg(int arg)
|
||||||
|
{
|
||||||
|
emit testSignalWithArg(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TestQObject::testVariantReturn()
|
||||||
|
{
|
||||||
|
return getVariantProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestQObject::testSlotBool(bool value)
|
||||||
|
{
|
||||||
|
emit testSignalBool(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QChar TestQObject::testSlotChar(QChar value)
|
||||||
|
{
|
||||||
|
emit testSignalChar(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestQObject::testSlotInt(int value)
|
||||||
|
{
|
||||||
|
emit testSignalInt(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint TestQObject::testSlotUInt(uint value)
|
||||||
|
{
|
||||||
|
emit testSignalUInt(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
long TestQObject::testSlotLong(long value)
|
||||||
|
{
|
||||||
|
emit testSignalLong(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong TestQObject::testSlotULong(ulong value)
|
||||||
|
{
|
||||||
|
emit testSignalULong(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TestQObject::testSlotFloat(float value)
|
||||||
|
{
|
||||||
|
emit testSignalFloat(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double TestQObject::testSlotDouble(double value)
|
||||||
|
{
|
||||||
|
emit testSignalDouble(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TestQObject::testSlotString(QString value)
|
||||||
|
{
|
||||||
|
emit testSignalString(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime TestQObject::testSlotDateTime(QDateTime value)
|
||||||
|
{
|
||||||
|
emit testSignalDateTime(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* TestQObject::testSlotQObject(QObject* value)
|
||||||
|
{
|
||||||
|
emit testSignalQObject(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 TestQObject::testSlotQInt32(qint32 value)
|
||||||
|
{
|
||||||
|
emit testSignalQInt32(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 TestQObject::testSlotQUInt32(quint32 value)
|
||||||
|
{
|
||||||
|
emit testSignalQUInt32(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 TestQObject::testSlotQInt64(qint64 value)
|
||||||
|
{
|
||||||
|
emit testSignalQInt64(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 TestQObject::testSlotQUInt64(quint64 value)
|
||||||
|
{
|
||||||
|
emit testSignalQUInt64(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
Q_DECL_EXPORT void net_test_helper_runQml(QQmlApplicationEngineContainer* qmlEngineContainer, LPWSTR qml) {
|
Q_DECL_EXPORT void net_test_helper_runQml(QQmlApplicationEngineContainer* qmlEngineContainer, LPWSTR qml) {
|
||||||
QQmlComponent component(qmlEngineContainer->qmlEngine);
|
QQmlComponent component(qmlEngineContainer->qmlEngine);
|
||||||
QString qmlString = QString::fromUtf16(static_cast<const char16_t*>(qml));
|
QString qmlString = QString::fromUtf16(static_cast<const char16_t*>(qml));
|
||||||
component.setData(qmlString.toUtf8(), QUrl());
|
component.setData(qmlString.toUtf8(), QUrl());
|
||||||
|
|
||||||
QObject *object = component.create();
|
QObject *object = component.create();
|
||||||
|
|
||||||
if(object == nullptr) {
|
if(object == nullptr) {
|
||||||
|
|
@ -15,6 +179,10 @@ Q_DECL_EXPORT void net_test_helper_runQml(QQmlApplicationEngineContainer* qmlEng
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<TestQObject> testQObject = QSharedPointer<TestQObject>(new TestQObject());
|
||||||
|
object->setProperty("testQObject", QVariant::fromValue(testQObject.data()));
|
||||||
|
QMetaObject::invokeMethod(object, "runTest");
|
||||||
|
|
||||||
delete object;
|
delete object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,72 @@
|
||||||
|
|
||||||
#include <QmlNet.h>
|
#include <QmlNet.h>
|
||||||
#include <QmlNet/qml/QQmlApplicationEngine.h>
|
#include <QmlNet/qml/QQmlApplicationEngine.h>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class TestQObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int readOnly READ getReadOnly)
|
||||||
|
Q_PROPERTY(int writeOnly WRITE setWriteOnly)
|
||||||
|
Q_PROPERTY(int readAndWrite READ getReadAndWrite WRITE setReadAndWrite)
|
||||||
|
Q_PROPERTY(int propWithSignal READ getPropWithSignal WRITE setPropWithSignal NOTIFY propWithSignalChanged)
|
||||||
|
Q_PROPERTY(QVariant variantProperty READ getVariantProperty WRITE setVariantProperty)
|
||||||
|
public:
|
||||||
|
TestQObject();
|
||||||
|
~TestQObject();
|
||||||
|
int getReadOnly();
|
||||||
|
void setWriteOnly(int value);
|
||||||
|
int getReadAndWrite();
|
||||||
|
void setReadAndWrite(int value);
|
||||||
|
int getPropWithSignal();
|
||||||
|
void setPropWithSignal(int value);
|
||||||
|
QVariant getVariantProperty();
|
||||||
|
void setVariantProperty(QVariant value);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void propWithSignalChanged(int value);
|
||||||
|
void testSignal();
|
||||||
|
void testSignalWithArg(int arg);
|
||||||
|
void testSignalBool(bool value);
|
||||||
|
void testSignalChar(QChar value);
|
||||||
|
void testSignalInt(int value);
|
||||||
|
void testSignalUInt(uint value);
|
||||||
|
void testSignalLong(long value);
|
||||||
|
void testSignalULong(ulong value);
|
||||||
|
void testSignalFloat(float value);
|
||||||
|
void testSignalDouble(double value);
|
||||||
|
void testSignalString(QString value);
|
||||||
|
void testSignalDateTime(QDateTime value);
|
||||||
|
void testSignalQObject(QObject* qObject);
|
||||||
|
void testSignalQInt32(qint32 value);
|
||||||
|
void testSignalQUInt32(quint32 value);
|
||||||
|
void testSignalQInt64(qint64 value);
|
||||||
|
void testSignalQUInt64(quint64 value);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void testSlot();
|
||||||
|
void testSlotWithArg(int arg);
|
||||||
|
QVariant testVariantReturn();
|
||||||
|
bool testSlotBool(bool value);
|
||||||
|
QChar testSlotChar(QChar value);
|
||||||
|
int testSlotInt(int value);
|
||||||
|
uint testSlotUInt(uint value);
|
||||||
|
long testSlotLong(long value);
|
||||||
|
ulong testSlotULong(ulong value);
|
||||||
|
float testSlotFloat(float value);
|
||||||
|
double testSlotDouble(double value);
|
||||||
|
QString testSlotString(QString value);
|
||||||
|
QDateTime testSlotDateTime(QDateTime value);
|
||||||
|
QObject* testSlotQObject(QObject* value);
|
||||||
|
qint32 testSlotQInt32(qint32 value);
|
||||||
|
quint32 testSlotQUInt32(quint32 value);
|
||||||
|
qint64 testSlotQInt64(qint64 value);
|
||||||
|
quint64 testSlotQUInt64(quint64 value);
|
||||||
|
private:
|
||||||
|
int _writeOnly;
|
||||||
|
int _readAndWrite;
|
||||||
|
int _propWithSignal;
|
||||||
|
QVariant _variantValue;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // NETTESTHELPER_H
|
#endif // NETTESTHELPER_H
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include <QmlNet/qml/NetValueMetaObjectPacker.h>
|
#include <QmlNet/qml/NetValueMetaObjectPacker.h>
|
||||||
#include <QmlNet/qml/NetVariant.h>
|
#include <QmlNet/qml/NetVariant.h>
|
||||||
#include <QmlNet/qml/NetValue.h>
|
#include <QmlNet/qml/NetValue.h>
|
||||||
|
#include <QmlNet/qml/NetJsValue.h>
|
||||||
|
#include <QmlNet/qml/NetQObject.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
const char* NetValueTypePacker::getQmlType()
|
const char* NetValueTypePacker::getQmlType()
|
||||||
|
|
@ -55,6 +57,9 @@ void NetValueTypePacker::pack(const QSharedPointer<NetVariant>& source, void* de
|
||||||
case NetVariantTypeEnum_JSValue:
|
case NetVariantTypeEnum_JSValue:
|
||||||
destinationVariant->setValue(source->getJsValue()->getJsValue());
|
destinationVariant->setValue(source->getJsValue()->getJsValue());
|
||||||
break;
|
break;
|
||||||
|
case NetVariantTypeEnum_QObject:
|
||||||
|
destinationVariant->setValue(source->getQObject()->getQObject());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,8 +121,11 @@ void NetValueTypePacker::unpack(const QSharedPointer<NetVariant>& destination, v
|
||||||
NetValueInterface* netValue = qobject_cast<NetValueInterface*>(value);
|
NetValueInterface* netValue = qobject_cast<NetValueInterface*>(value);
|
||||||
if(netValue) {
|
if(netValue) {
|
||||||
destination->setNetReference(netValue->getNetReference());
|
destination->setNetReference(netValue->getNetReference());
|
||||||
return;
|
} else {
|
||||||
|
QSharedPointer<NetQObject> netQObject(new NetQObject(value));
|
||||||
|
destination->setQObject(netQObject);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +139,12 @@ void NetValueTypePacker::unpack(const QSharedPointer<NetVariant>& destination, v
|
||||||
// TODO: Try to convert other types to JS Value.
|
// TODO: Try to convert other types to JS Value.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NetVariantTypeEnum_QObject:
|
||||||
|
{
|
||||||
|
if(sourceVariant->userType() == QMetaType::QObjectStar) {
|
||||||
|
QSharedPointer<NetQObject> netQObject(new NetQObject(sourceVariant->value<QObject*>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetVariant::fromQVariant(sourceVariant, destination);
|
NetVariant::fromQVariant(sourceVariant, destination);
|
||||||
|
|
@ -192,6 +206,7 @@ NetValueMetaObjectPacker::NetValueMetaObjectPacker()
|
||||||
case NetVariantTypeEnum_DateTime:
|
case NetVariantTypeEnum_DateTime:
|
||||||
case NetVariantTypeEnum_Object:
|
case NetVariantTypeEnum_Object:
|
||||||
case NetVariantTypeEnum_JSValue:
|
case NetVariantTypeEnum_JSValue:
|
||||||
|
case NetVariantTypeEnum_QObject:
|
||||||
packers[type] = variantPacker;
|
packers[type] = variantPacker;
|
||||||
break;
|
break;
|
||||||
case NetVariantTypeEnum_String:
|
case NetVariantTypeEnum_String:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
#include <QmlNet/types/NetReference.h>
|
||||||
#include <QmlNet/qml/NetVariant.h>
|
#include <QmlNet/qml/NetVariant.h>
|
||||||
#include <QmlNet/qml/NetValue.h>
|
#include <QmlNet/qml/NetValue.h>
|
||||||
#include <QmlNet/qml/NetJsValue.h>
|
#include <QmlNet/qml/NetJsValue.h>
|
||||||
|
#include <QmlNet/qml/NetQObject.h>
|
||||||
#include <QmlNetUtilities.h>
|
#include <QmlNetUtilities.h>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
@ -18,15 +20,22 @@ struct NetJsValueQmlContainer
|
||||||
{
|
{
|
||||||
QSharedPointer<NetJSValue> jsValue;
|
QSharedPointer<NetJSValue> jsValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NetQObjectQmlContainer
|
||||||
|
{
|
||||||
|
QSharedPointer<NetQObject> netQObject;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(NetReferenceQmlContainer)
|
Q_DECLARE_METATYPE(NetReferenceQmlContainer)
|
||||||
Q_DECLARE_METATYPE(NetJsValueQmlContainer)
|
Q_DECLARE_METATYPE(NetJsValueQmlContainer)
|
||||||
|
Q_DECLARE_METATYPE(NetQObjectQmlContainer)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const int NetReferenceQmlContainerTypeId = qMetaTypeId<NetReferenceQmlContainer>();
|
const int NetReferenceQmlContainerTypeId = qMetaTypeId<NetReferenceQmlContainer>();
|
||||||
const int NetJsValueQmlContainerTypeId = qMetaTypeId<NetJsValueQmlContainer>();
|
const int NetJsValueQmlContainerTypeId = qMetaTypeId<NetJsValueQmlContainer>();
|
||||||
|
const int NetQObjectQmlContainerTypeId = qMetaTypeId<NetQObjectQmlContainer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetVariant::NetVariant() = default;
|
NetVariant::NetVariant() = default;
|
||||||
|
|
@ -68,7 +77,11 @@ NetVariantTypeEnum NetVariant::getVariantType() const
|
||||||
}
|
}
|
||||||
else if(type == NetJsValueQmlContainerTypeId) {
|
else if(type == NetJsValueQmlContainerTypeId) {
|
||||||
return NetVariantTypeEnum_JSValue;
|
return NetVariantTypeEnum_JSValue;
|
||||||
} else {
|
}
|
||||||
|
else if(type == NetQObjectQmlContainerTypeId) {
|
||||||
|
return NetVariantTypeEnum_QObject;
|
||||||
|
}
|
||||||
|
else {
|
||||||
qWarning() << "Unknown type for NetVariant: " << variant.typeName();
|
qWarning() << "Unknown type for NetVariant: " << variant.typeName();
|
||||||
return NetVariantTypeEnum_Invalid;
|
return NetVariantTypeEnum_Invalid;
|
||||||
}
|
}
|
||||||
|
|
@ -206,6 +219,16 @@ QSharedPointer<NetJSValue> NetVariant::getJsValue() const
|
||||||
return getValue<NetJsValueQmlContainer>().jsValue;
|
return getValue<NetJsValueQmlContainer>().jsValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetVariant::setQObject(QSharedPointer<NetQObject> netQObject)
|
||||||
|
{
|
||||||
|
setValue(NetQObjectQmlContainer{ std::move(netQObject) });
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<NetQObject> NetVariant::getQObject() const
|
||||||
|
{
|
||||||
|
return getValue<NetQObjectQmlContainer>().netQObject;
|
||||||
|
}
|
||||||
|
|
||||||
void NetVariant::clear()
|
void NetVariant::clear()
|
||||||
{
|
{
|
||||||
clearNetReference();
|
clearNetReference();
|
||||||
|
|
@ -274,13 +297,23 @@ void NetVariant::fromQVariant(const QVariant* variant, const QSharedPointer<NetV
|
||||||
case QMetaType::QDateTime:
|
case QMetaType::QDateTime:
|
||||||
destination->setValueVariant(*variant);
|
destination->setValueVariant(*variant);
|
||||||
break;
|
break;
|
||||||
|
case QMetaType::ULong:
|
||||||
|
destination->setULong(variant->value<quint64>());
|
||||||
|
break;
|
||||||
|
case QMetaType::Long:
|
||||||
|
destination->setLong(variant->value<qint64>());
|
||||||
|
break;
|
||||||
case QMetaType::QObjectStar: {
|
case QMetaType::QObjectStar: {
|
||||||
QObject* value = variant->value<QObject*>();
|
QObject* value = variant->value<QObject*>();
|
||||||
|
if(value == nullptr) {
|
||||||
|
destination->clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
NetValueInterface* netValue = qobject_cast<NetValueInterface*>(value);
|
NetValueInterface* netValue = qobject_cast<NetValueInterface*>(value);
|
||||||
if(netValue) {
|
if(netValue) {
|
||||||
destination->setNetReference(netValue->getNetReference());
|
destination->setNetReference(netValue->getNetReference());
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Unsupported variant type: " << variant->type() << variant->typeName();
|
destination->setQObject(QSharedPointer<NetQObject>(new NetQObject(value)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +347,8 @@ QVariant NetVariant::toQVariant() const
|
||||||
return getJsValue()->getJsValue().toVariant();
|
return getJsValue()->getJsValue().toVariant();
|
||||||
case NetVariantTypeEnum_Object:
|
case NetVariantTypeEnum_Object:
|
||||||
return QVariant::fromValue<QObject*>(NetValue::forInstance(getNetReference()));
|
return QVariant::fromValue<QObject*>(NetValue::forInstance(getNetReference()));
|
||||||
|
case NetVariantTypeEnum_QObject:
|
||||||
|
return QVariant::fromValue<QObject*>(this->getQObject()->getQObject());
|
||||||
default:
|
default:
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
@ -341,6 +376,10 @@ void NetVariant::clearNetReference()
|
||||||
variant.value<NetJsValueQmlContainer>().jsValue.clear();
|
variant.value<NetJsValueQmlContainer>().jsValue.clear();
|
||||||
variant.clear();
|
variant.clear();
|
||||||
}
|
}
|
||||||
|
else if(variant.canConvert<NetQObjectQmlContainer>()) {
|
||||||
|
variant.value<NetQObjectQmlContainer>().netQObject.clear();
|
||||||
|
variant.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -559,6 +598,24 @@ Q_DECL_EXPORT NetJSValueContainer* net_variant_getJsValue(NetVariantContainer* c
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void net_variant_setQObject(NetVariantContainer* container, NetQObjectContainer* qObjectContainer) {
|
||||||
|
if(qObjectContainer == nullptr) {
|
||||||
|
container->variant->setQObject(nullptr);
|
||||||
|
} else {
|
||||||
|
container->variant->setQObject(qObjectContainer->qObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT NetQObjectContainer* net_variant_getQObject(NetVariantContainer* container) {
|
||||||
|
const QSharedPointer<NetQObject>& instance = container->variant->getQObject();
|
||||||
|
if(instance == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
NetQObjectContainer* result = new NetQObjectContainer();
|
||||||
|
result->qObject = instance;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECL_EXPORT void net_variant_clear(NetVariantContainer* container) {
|
Q_DECL_EXPORT void net_variant_clear(NetVariantContainer* container) {
|
||||||
container->variant->clear();
|
container->variant->clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
#ifndef NETVARIANT_H
|
#ifndef NETVARIANT_H
|
||||||
#define NETVARIANT_H
|
#define NETVARIANT_H
|
||||||
|
|
||||||
#include <QmlNet/types/NetReference.h>
|
#include <QmlNet.h>
|
||||||
#include <QmlNet/qml/NetJsValue.h>
|
#include <QSharedPointer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QJSValue>
|
#include <QJSValue>
|
||||||
|
|
||||||
|
class NetJSValue;
|
||||||
|
class NetQObject;
|
||||||
|
class NetReference;
|
||||||
|
|
||||||
class NetVariant
|
class NetVariant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -38,6 +42,8 @@ public:
|
||||||
QDateTime getDateTime() const;
|
QDateTime getDateTime() const;
|
||||||
void setJsValue(QSharedPointer<NetJSValue> jsValue);
|
void setJsValue(QSharedPointer<NetJSValue> jsValue);
|
||||||
QSharedPointer<NetJSValue> getJsValue() const;
|
QSharedPointer<NetJSValue> getJsValue() const;
|
||||||
|
void setQObject(QSharedPointer<NetQObject> netQObject);
|
||||||
|
QSharedPointer<NetQObject> getQObject() const;
|
||||||
void clear();
|
void clear();
|
||||||
static QSharedPointer<NetVariant> fromQJSValue(const QJSValue& qJsValue);
|
static QSharedPointer<NetVariant> fromQJSValue(const QJSValue& qJsValue);
|
||||||
QJSValue toQJSValue() const;
|
QJSValue toQJSValue() const;
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,26 @@ Q_DECL_EXPORT int qqmlapplicationengine_registerType(NetTypeInfoContainer* typeC
|
||||||
NETVALUETYPE_CASE(148)
|
NETVALUETYPE_CASE(148)
|
||||||
NETVALUETYPE_CASE(149)
|
NETVALUETYPE_CASE(149)
|
||||||
NETVALUETYPE_CASE(150)
|
NETVALUETYPE_CASE(150)
|
||||||
|
NETVALUETYPE_CASE(151)
|
||||||
|
NETVALUETYPE_CASE(152)
|
||||||
|
NETVALUETYPE_CASE(153)
|
||||||
|
NETVALUETYPE_CASE(154)
|
||||||
|
NETVALUETYPE_CASE(155)
|
||||||
|
NETVALUETYPE_CASE(156)
|
||||||
|
NETVALUETYPE_CASE(157)
|
||||||
|
NETVALUETYPE_CASE(158)
|
||||||
|
NETVALUETYPE_CASE(159)
|
||||||
|
NETVALUETYPE_CASE(160)
|
||||||
|
NETVALUETYPE_CASE(161)
|
||||||
|
NETVALUETYPE_CASE(162)
|
||||||
|
NETVALUETYPE_CASE(163)
|
||||||
|
NETVALUETYPE_CASE(164)
|
||||||
|
NETVALUETYPE_CASE(165)
|
||||||
|
NETVALUETYPE_CASE(166)
|
||||||
|
NETVALUETYPE_CASE(167)
|
||||||
|
NETVALUETYPE_CASE(168)
|
||||||
|
NETVALUETYPE_CASE(169)
|
||||||
|
NETVALUETYPE_CASE(170)
|
||||||
}
|
}
|
||||||
qFatal("Too many registered types: %d", netValueTypeNumber);
|
qFatal("Too many registered types: %d", netValueTypeNumber);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -395,6 +415,26 @@ Q_DECL_EXPORT int qqmlapplicationengine_registerSingletonTypeNet(NetTypeInfoCont
|
||||||
NETVALUETYPESINGLETON_CASE(148)
|
NETVALUETYPESINGLETON_CASE(148)
|
||||||
NETVALUETYPESINGLETON_CASE(149)
|
NETVALUETYPESINGLETON_CASE(149)
|
||||||
NETVALUETYPESINGLETON_CASE(150)
|
NETVALUETYPESINGLETON_CASE(150)
|
||||||
|
NETVALUETYPESINGLETON_CASE(151)
|
||||||
|
NETVALUETYPESINGLETON_CASE(152)
|
||||||
|
NETVALUETYPESINGLETON_CASE(153)
|
||||||
|
NETVALUETYPESINGLETON_CASE(154)
|
||||||
|
NETVALUETYPESINGLETON_CASE(155)
|
||||||
|
NETVALUETYPESINGLETON_CASE(156)
|
||||||
|
NETVALUETYPESINGLETON_CASE(157)
|
||||||
|
NETVALUETYPESINGLETON_CASE(158)
|
||||||
|
NETVALUETYPESINGLETON_CASE(159)
|
||||||
|
NETVALUETYPESINGLETON_CASE(160)
|
||||||
|
NETVALUETYPESINGLETON_CASE(161)
|
||||||
|
NETVALUETYPESINGLETON_CASE(162)
|
||||||
|
NETVALUETYPESINGLETON_CASE(163)
|
||||||
|
NETVALUETYPESINGLETON_CASE(164)
|
||||||
|
NETVALUETYPESINGLETON_CASE(165)
|
||||||
|
NETVALUETYPESINGLETON_CASE(166)
|
||||||
|
NETVALUETYPESINGLETON_CASE(167)
|
||||||
|
NETVALUETYPESINGLETON_CASE(168)
|
||||||
|
NETVALUETYPESINGLETON_CASE(169)
|
||||||
|
NETVALUETYPESINGLETON_CASE(170)
|
||||||
}
|
}
|
||||||
qFatal("Too many registered types: %d", netValueTypeNumber);
|
qFatal("Too many registered types: %d", netValueTypeNumber);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ HEADERS += \
|
||||||
$$PWD/NetListModel.h \
|
$$PWD/NetListModel.h \
|
||||||
$$PWD/QtWebEngine.h \
|
$$PWD/QtWebEngine.h \
|
||||||
$$PWD/QCoreApplication.h \
|
$$PWD/QCoreApplication.h \
|
||||||
$$PWD/QTest.h
|
$$PWD/QTest.h \
|
||||||
|
$$PWD/NetQObject.h \
|
||||||
|
$$PWD/NetQObjectSignalConnection.h \
|
||||||
|
$$PWD/NetQObjectArg.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/QQmlApplicationEngine.cpp \
|
$$PWD/QQmlApplicationEngine.cpp \
|
||||||
|
|
@ -34,4 +37,7 @@ SOURCES += \
|
||||||
$$PWD/NetListModel.cpp \
|
$$PWD/NetListModel.cpp \
|
||||||
$$PWD/QtWebEngine.cpp \
|
$$PWD/QtWebEngine.cpp \
|
||||||
$$PWD/QCoreApplication.cpp \
|
$$PWD/QCoreApplication.cpp \
|
||||||
$$PWD/QTest.cpp
|
$$PWD/QTest.cpp \
|
||||||
|
$$PWD/NetQObject.cpp \
|
||||||
|
$$PWD/NetQObjectSignalConnection.cpp \
|
||||||
|
$$PWD/NetQObjectArg.cpp
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using gcCollectCb = void (*)(int);
|
||||||
using raiseNetSignalsCb = uchar (*)(NetReferenceContainer *, LPWCSTR, NetVariantListContainer *);
|
using raiseNetSignalsCb = uchar (*)(NetReferenceContainer *, LPWCSTR, NetVariantListContainer *);
|
||||||
using awaitTaskCb = void (*)(NetReferenceContainer *, NetJSValueContainer *, NetJSValueContainer *);
|
using awaitTaskCb = void (*)(NetReferenceContainer *, NetJSValueContainer *, NetJSValueContainer *);
|
||||||
using serializeNetToStringCb = uchar (*)(NetReferenceContainer *, NetVariantContainer *);
|
using serializeNetToStringCb = uchar (*)(NetReferenceContainer *, NetVariantContainer *);
|
||||||
|
using invokeDelegateCb = void (*)(NetReferenceContainer *, NetVariantListContainer *);
|
||||||
|
|
||||||
struct Q_DECL_EXPORT NetTypeInfoManagerCallbacks {
|
struct Q_DECL_EXPORT NetTypeInfoManagerCallbacks {
|
||||||
isTypeValidCb isTypeValid;
|
isTypeValidCb isTypeValid;
|
||||||
|
|
@ -35,6 +36,7 @@ struct Q_DECL_EXPORT NetTypeInfoManagerCallbacks {
|
||||||
raiseNetSignalsCb raiseNetSignals;
|
raiseNetSignalsCb raiseNetSignals;
|
||||||
awaitTaskCb awaitTask;
|
awaitTaskCb awaitTask;
|
||||||
serializeNetToStringCb serializeNetToString;
|
serializeNetToStringCb serializeNetToString;
|
||||||
|
invokeDelegateCb invokeDelegate;
|
||||||
};
|
};
|
||||||
|
|
||||||
static NetTypeInfoManagerCallbacks sharedCallbacks;
|
static NetTypeInfoManagerCallbacks sharedCallbacks;
|
||||||
|
|
@ -175,6 +177,12 @@ bool serializeNetToString(QSharedPointer<NetReference> instance, QSharedPointer<
|
||||||
new NetVariantContainer{std::move(result)}) == 1;
|
new NetVariantContainer{std::move(result)}) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void invokeDelegate(QSharedPointer<NetReference> del, QSharedPointer<NetVariantList> parameters)
|
||||||
|
{
|
||||||
|
sharedCallbacks.invokeDelegate(new NetReferenceContainer{std::move(del)},
|
||||||
|
new NetVariantListContainer{std::move(parameters)});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QmlNet/types/NetReference.h>
|
#include <QmlNet/types/NetReference.h>
|
||||||
#include <QmlNet/qml/NetVariant.h>
|
#include <QmlNet/qml/NetVariant.h>
|
||||||
#include <QmlNet/qml/NetVariantList.h>
|
#include <QmlNet/qml/NetVariantList.h>
|
||||||
|
#include <QmlNet/qml/NetJsValue.h>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
|
@ -43,6 +44,8 @@ void awaitTask(QSharedPointer<NetReference> target, QSharedPointer<NetJSValue> s
|
||||||
|
|
||||||
bool serializeNetToString(QSharedPointer<NetReference> instance, QSharedPointer<NetVariant> result);
|
bool serializeNetToString(QSharedPointer<NetReference> instance, QSharedPointer<NetVariant> result);
|
||||||
|
|
||||||
|
void invokeDelegate(QSharedPointer<NetReference> del, QSharedPointer<NetVariantList> parameters);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NET_TYPE_INFO_MANAGER_H
|
#endif // NET_TYPE_INFO_MANAGER_H
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,8 @@ namespace Qml.Net.Tests.Qml
|
||||||
import tests 1.0
|
import tests 1.0
|
||||||
{0} {{
|
{0} {{
|
||||||
id: {1}
|
id: {1}
|
||||||
Component.onCompleted: function() {{
|
property var testQObject: null
|
||||||
|
function runTest() {{
|
||||||
{2}
|
{2}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ namespace Qml.Net.Tests.Qml
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Can_read_properties_from_js_object()
|
public void Can_read_properties_from_js_object()
|
||||||
{
|
{
|
||||||
var testObject = new JsValueTests.JsTestsQml.TestObject();
|
var testObject = new JsTestsQml.TestObject();
|
||||||
dynamic result = null;
|
dynamic result = null;
|
||||||
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>())).Callback(new Action<dynamic>(jsValue =>
|
Mock.Setup(x => x.Method(It.IsAny<INetJsValue>())).Callback(new Action<dynamic>(jsValue =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ namespace Qml.Net.Tests.Qml
|
||||||
{
|
{
|
||||||
public virtual void DerivedMethod()
|
public virtual void DerivedMethod()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,7 +16,6 @@ namespace Qml.Net.Tests.Qml
|
||||||
{
|
{
|
||||||
public virtual void BaseMethod()
|
public virtual void BaseMethod()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
584
src/net/Qml.Net.Tests/Qml/QObjectTests.cs
Normal file
584
src/net/Qml.Net.Tests/Qml/QObjectTests.cs
Normal file
|
|
@ -0,0 +1,584 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using FluentAssertions;
|
||||||
|
using FluentAssertions.Execution;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Qml.Net.Tests.Qml
|
||||||
|
{
|
||||||
|
public class QObjectTests : BaseQmlTests<QObjectTests.QObjectTestsQml>
|
||||||
|
{
|
||||||
|
public class QObjectTestsQml
|
||||||
|
{
|
||||||
|
public virtual void Method(dynamic value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Exception_throw_when_using_invalid_methods()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
qObject.InvokeMethod("testSlot");
|
||||||
|
Assert.Throws<Exception>(() => { qObject.InvokeMethod("nonexistant"); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Exception_thrown_when_using_invalid_properties()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
qObject.SetProperty("readAndWrite", 3);
|
||||||
|
Assert.Throws<Exception>(() => { qObject.SetProperty("nonexistant", 3); });
|
||||||
|
Assert.Throws<Exception>(() => { qObject.GetProperty("nonexistant"); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Exception_thrown_when_attaching_to_invalid_signal()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
var handler = qObject.AttachSignal("testSignal", parameters =>
|
||||||
|
{
|
||||||
|
});
|
||||||
|
handler.Dispose();
|
||||||
|
Assert.Throws<Exception>(() =>
|
||||||
|
{
|
||||||
|
qObject.AttachSignal(
|
||||||
|
"nonexistant",
|
||||||
|
parameters =>
|
||||||
|
{
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Exception_thrown_when_attaching_to_invalid_notify_signal()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
var handler = qObject.AttachNotifySignal("propWithSignal", parameters =>
|
||||||
|
{
|
||||||
|
});
|
||||||
|
handler.Dispose();
|
||||||
|
Assert.Throws<Exception>(() =>
|
||||||
|
{
|
||||||
|
qObject.AttachNotifySignal(
|
||||||
|
"readAndWrite",
|
||||||
|
parameters =>
|
||||||
|
{
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Assert.Throws<Exception>(() =>
|
||||||
|
{
|
||||||
|
qObject.AttachNotifySignal(
|
||||||
|
"nonexistant",
|
||||||
|
parameters =>
|
||||||
|
{
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_get_property_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
qObject.GetProperty("readOnly").Should().Be(3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_set_property_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// No real way to test this.
|
||||||
|
// I suppose it doesn't throw, eh?
|
||||||
|
qObject.SetProperty("writeOnly", 3);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_set_and_get_property_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
qObject.SetProperty("readAndWrite", 340);
|
||||||
|
qObject.GetProperty("readAndWrite").Should().Be(340);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_get_set_object_name()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var d = (dynamic)qObject;
|
||||||
|
d.objectName = "testtt";
|
||||||
|
((string)d.objectName).Should().Be("testtt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_set_random_types_on_property()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
qObject.GetProperty("variantProperty").Should().BeNull();
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", true);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(true);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", 'T');
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be('T');
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", int.MinValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(int.MinValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", uint.MaxValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(uint.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", long.MaxValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(long.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", ulong.MaxValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(ulong.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", float.MaxValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(float.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", double.MaxValue);
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be(double.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", "");
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be("");
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", "test");
|
||||||
|
qObject.GetProperty("variantProperty").Should().Be("test");
|
||||||
|
|
||||||
|
var dateTime = DateTimeOffset.Now;
|
||||||
|
dateTime = new DateTimeOffset(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond, dateTime.Offset);
|
||||||
|
qObject.SetProperty("variantProperty", dateTime);
|
||||||
|
var resultDateTime = (DateTimeOffset)qObject.GetProperty("variantProperty");
|
||||||
|
resultDateTime = new DateTimeOffset(resultDateTime.Year, resultDateTime.Month, resultDateTime.Day, resultDateTime.Hour, resultDateTime.Minute, resultDateTime.Second, resultDateTime.Millisecond, resultDateTime.Offset);
|
||||||
|
resultDateTime.Should().Be(dateTime);
|
||||||
|
|
||||||
|
var o = new object();
|
||||||
|
qObject.SetProperty("variantProperty", o);
|
||||||
|
qObject.GetProperty("variantProperty").Should().BeSameAs(o);
|
||||||
|
|
||||||
|
qObject.SetProperty("objectName", "ttttt");
|
||||||
|
qObject.SetProperty("variantProperty", qObject);
|
||||||
|
var result = qObject.GetProperty("variantProperty");
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
var resultQObject = result as INetQObject;
|
||||||
|
resultQObject.Should().NotBeNull();
|
||||||
|
resultQObject.GetProperty("objectName").Should().Be("ttttt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_return_random_types_from_method()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(null);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", true);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(true);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", 'T');
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be('T');
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", int.MinValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(int.MinValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", uint.MaxValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(uint.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", long.MaxValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(long.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", ulong.MaxValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(ulong.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", float.MaxValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(float.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", double.MaxValue);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be(double.MaxValue);
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", "");
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be("");
|
||||||
|
|
||||||
|
qObject.SetProperty("variantProperty", "test");
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().Be("test");
|
||||||
|
|
||||||
|
var dateTime = DateTimeOffset.Now;
|
||||||
|
dateTime = new DateTimeOffset(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond, dateTime.Offset);
|
||||||
|
qObject.SetProperty("variantProperty", dateTime);
|
||||||
|
var resultDateTime = (DateTimeOffset)qObject.InvokeMethod("testVariantReturn");
|
||||||
|
resultDateTime = new DateTimeOffset(resultDateTime.Year, resultDateTime.Month, resultDateTime.Day, resultDateTime.Hour, resultDateTime.Minute, resultDateTime.Second, resultDateTime.Millisecond, resultDateTime.Offset);
|
||||||
|
resultDateTime.Should().Be(dateTime);
|
||||||
|
|
||||||
|
var o = new object();
|
||||||
|
qObject.SetProperty("variantProperty", o);
|
||||||
|
qObject.InvokeMethod("testVariantReturn").Should().BeSameAs(o);
|
||||||
|
|
||||||
|
qObject.SetProperty("objectName", "ttttt");
|
||||||
|
qObject.SetProperty("variantProperty", qObject);
|
||||||
|
var result = qObject.InvokeMethod("testVariantReturn");
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
var resultQObject = result as INetQObject;
|
||||||
|
resultQObject.Should().NotBeNull();
|
||||||
|
resultQObject.GetProperty("objectName").Should().Be("ttttt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_set_qobject_on_global_context_property()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var d = (dynamic)qObject;
|
||||||
|
var property = Guid.NewGuid().ToString().Replace("-", "");
|
||||||
|
d.objectName = property;
|
||||||
|
qmlApplicationEngine.SetContextProperty(property, d);
|
||||||
|
var result = qmlApplicationEngine.GetContextProperty(property);
|
||||||
|
(result is INetQObject).Should().BeTrue();
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
((string)d.objectName).Should().Be(property);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_invoke_method_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
// TODO: Assert
|
||||||
|
qObject.InvokeMethod("testSlot");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_attach_notify_signal_to_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var raised = false;
|
||||||
|
var expected = 0;
|
||||||
|
var handler = qObject.AttachNotifySignal("propWithSignal", parameters =>
|
||||||
|
{
|
||||||
|
raised = true;
|
||||||
|
parameters.Count.Should().Be(1);
|
||||||
|
parameters[0].Should().Be(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
expected = 43;
|
||||||
|
qObject.SetProperty("propWithSignal", 43);
|
||||||
|
raised.Should().BeTrue();
|
||||||
|
|
||||||
|
raised = false;
|
||||||
|
qObject.SetProperty("propWithSignal", 43);
|
||||||
|
raised.Should().BeFalse();
|
||||||
|
|
||||||
|
expected = 44;
|
||||||
|
raised = false;
|
||||||
|
qObject.SetProperty("propWithSignal", 44);
|
||||||
|
raised.Should().BeTrue();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_attach_signal_to_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var raised = 0;
|
||||||
|
var handler = qObject.AttachSignal("testSignal", parameters =>
|
||||||
|
{
|
||||||
|
raised++;
|
||||||
|
});
|
||||||
|
handler.Should().NotBeNull();
|
||||||
|
|
||||||
|
qObject.InvokeMethod("testSlot");
|
||||||
|
raised.Should().Be(1);
|
||||||
|
|
||||||
|
handler.Dispose();
|
||||||
|
|
||||||
|
qObject.InvokeMethod("testSlot");
|
||||||
|
raised.Should().Be(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_attach_signal_with_arg_to_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var raised = false;
|
||||||
|
var handler = qObject.AttachSignal("testSignalWithArg", parameters =>
|
||||||
|
{
|
||||||
|
raised = true;
|
||||||
|
parameters.Should().NotBeNull();
|
||||||
|
parameters.Count.Should().Be(1);
|
||||||
|
parameters[0].Should().Be(33);
|
||||||
|
});
|
||||||
|
|
||||||
|
qObject.InvokeMethod("testSlotWithArg", 33);
|
||||||
|
|
||||||
|
handler.Dispose();
|
||||||
|
raised = false;
|
||||||
|
|
||||||
|
qObject.InvokeMethod("testSlotWithArg", 33);
|
||||||
|
raised.Should().BeFalse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_bool_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Bool", true);
|
||||||
|
AssertValue(qObject, "Bool", false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_char_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Char", 'T');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_int_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Int", int.MinValue);
|
||||||
|
AssertValue(qObject, "Int", int.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_uint_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "UInt", uint.MinValue);
|
||||||
|
AssertValue(qObject, "UInt", uint.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_long_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Long", -23423);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_ulong_on_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "ULong", 2323);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_float_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Float", float.MinValue);
|
||||||
|
AssertValue(qObject, "Float", float.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_double_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "Double", double.MinValue);
|
||||||
|
AssertValue(qObject, "Double", double.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_string_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "String", "test");
|
||||||
|
AssertValue(qObject, "String", "");
|
||||||
|
AssertValue(qObject, "String", null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_datetime_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var value = DateTimeOffset.Now;
|
||||||
|
value = new DateTimeOffset(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second, value.Millisecond, value.Offset);
|
||||||
|
AssertValue(qObject, "DateTime", value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_qobject_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
qObject.SetProperty("objectName", "testttdd");
|
||||||
|
AssertValue(qObject, "QObject", qObject, result =>
|
||||||
|
{
|
||||||
|
result.Should().BeAssignableTo<INetQObject>()
|
||||||
|
.Subject.GetProperty("objectName").Should().Be("testttdd");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_object_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
var o = new object();
|
||||||
|
AssertValue(qObject, "QObject", o, result =>
|
||||||
|
{
|
||||||
|
result.Should().BeSameAs(o);
|
||||||
|
});
|
||||||
|
|
||||||
|
AssertValue(qObject, "QObject", null, result =>
|
||||||
|
{
|
||||||
|
result.Should().BeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_qint32_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "QInt32", int.MinValue);
|
||||||
|
AssertValue(qObject, "QInt32", int.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_quint32_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "QUInt32", uint.MinValue);
|
||||||
|
AssertValue(qObject, "QUInt32", uint.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_qint64_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "QInt64", long.MinValue);
|
||||||
|
AssertValue(qObject, "QInt64", long.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_use_quint64_with_qobject()
|
||||||
|
{
|
||||||
|
AssertQObject(qObject =>
|
||||||
|
{
|
||||||
|
AssertValue(qObject, "QUInt64", ulong.MinValue);
|
||||||
|
AssertValue(qObject, "QUInt64", ulong.MaxValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertValue(INetQObject qObject, string method, object value)
|
||||||
|
{
|
||||||
|
var raised = false;
|
||||||
|
var handler = qObject.AttachSignal($"testSignal{method}", parameters =>
|
||||||
|
{
|
||||||
|
raised = true;
|
||||||
|
parameters.Count.Should().Be(1);
|
||||||
|
parameters[0].Should().Be(value);
|
||||||
|
});
|
||||||
|
using (handler)
|
||||||
|
{
|
||||||
|
var invokeResult = qObject.InvokeMethod($"testSlot{method}", value);
|
||||||
|
invokeResult.Should().Be(value);
|
||||||
|
raised.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertValue(INetQObject qObject, string method, object value, Action<object> assert)
|
||||||
|
{
|
||||||
|
var raised = false;
|
||||||
|
var handler = qObject.AttachSignal($"testSignal{method}", parameters =>
|
||||||
|
{
|
||||||
|
raised = true;
|
||||||
|
parameters.Count.Should().Be(1);
|
||||||
|
assert(parameters[0]);
|
||||||
|
});
|
||||||
|
using (handler)
|
||||||
|
{
|
||||||
|
assert(qObject.InvokeMethod($"testSlot{method}", value));
|
||||||
|
raised.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertQObject(Action<INetQObject> action)
|
||||||
|
{
|
||||||
|
Exception assertException = null;
|
||||||
|
|
||||||
|
Mock.Setup(x => x.Method(It.IsAny<INetQObject>()))
|
||||||
|
.Callback(new Action<dynamic>(x =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action(x as INetQObject);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
assertException = ex;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
RunQmlTest(
|
||||||
|
"test",
|
||||||
|
@"
|
||||||
|
test.method(testQObject)
|
||||||
|
");
|
||||||
|
|
||||||
|
Mock.Verify(x => x.Method(It.IsAny<INetQObject>()), Times.Once);
|
||||||
|
if (assertException != null)
|
||||||
|
{
|
||||||
|
throw new Exception(assertException.Message, assertException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,4 +3,5 @@
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OSX/@EntryIndexedValue">OSX</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OSX/@EntryIndexedValue">OSX</s:String>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=gstream/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=gstream/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pixmaps/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pixmaps/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=qobject/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Runtimes/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Runtimes/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
|
|
@ -10,6 +10,8 @@ namespace Qml.Net
|
||||||
|
|
||||||
object GetProperty(string propertyName);
|
object GetProperty(string propertyName);
|
||||||
|
|
||||||
|
void SetProperty(string propertyName, object value);
|
||||||
|
|
||||||
object GetItemAtIndex(int arrayIndex);
|
object GetItemAtIndex(int arrayIndex);
|
||||||
|
|
||||||
object Call(params object[] parameters);
|
object Call(params object[] parameters);
|
||||||
|
|
|
||||||
20
src/net/Qml.Net/INetQObject.cs
Normal file
20
src/net/Qml.Net/INetQObject.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Qml.Net
|
||||||
|
{
|
||||||
|
public interface INetQObject : IDisposable
|
||||||
|
{
|
||||||
|
object GetProperty(string propertyName);
|
||||||
|
|
||||||
|
void SetProperty(string propertyName, object value);
|
||||||
|
|
||||||
|
object InvokeMethod(string methodName, params object[] parameters);
|
||||||
|
|
||||||
|
IDisposable AttachSignal(string signalName, SignalHandler handler);
|
||||||
|
|
||||||
|
IDisposable AttachNotifySignal(string propertyName, SignalHandler handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void SignalHandler(List<object> parameters);
|
||||||
|
}
|
||||||
|
|
@ -248,6 +248,10 @@ namespace Qml.Net.Internal.CodeGen
|
||||||
{
|
{
|
||||||
variant.JsValue = valueJsValue;
|
variant.JsValue = valueJsValue;
|
||||||
}
|
}
|
||||||
|
else if (value is NetQObject valueQObject)
|
||||||
|
{
|
||||||
|
variant.QObject = valueQObject;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
variant.Instance = NetReference.CreateForObject(value);
|
variant.Instance = NetReference.CreateForObject(value);
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,8 @@ namespace Qml.Net.Internal.CodeGen
|
||||||
break;
|
break;
|
||||||
case NetVariantType.JsValue:
|
case NetVariantType.JsValue:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
case NetVariantType.QObject:
|
||||||
|
throw new NotImplementedException();
|
||||||
case NetVariantType.Invalid:
|
case NetVariantType.Invalid:
|
||||||
throw new Exception("invalid type");
|
throw new Exception("invalid type");
|
||||||
default:
|
default:
|
||||||
|
|
@ -224,6 +226,8 @@ namespace Qml.Net.Internal.CodeGen
|
||||||
break;
|
break;
|
||||||
case NetVariantType.JsValue:
|
case NetVariantType.JsValue:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
case NetVariantType.QObject:
|
||||||
|
throw new NotImplementedException();
|
||||||
case NetVariantType.Invalid:
|
case NetVariantType.Invalid:
|
||||||
throw new Exception("invalid type");
|
throw new Exception("invalid type");
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,24 @@ namespace Qml.Net.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InvokeDelegate(IntPtr del, IntPtr parameters)
|
||||||
|
{
|
||||||
|
using (var netReference = new NetReference(del))
|
||||||
|
{
|
||||||
|
using (var netParameters = new NetVariantList(parameters))
|
||||||
|
{
|
||||||
|
var o = netReference.Instance;
|
||||||
|
var oDel = o as Del;
|
||||||
|
if (oDel == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"NetReferecnce is invalid type: {o.GetType().FullName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
oDel.Raise(netParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private NetVariantType GetPrefVariantType(Type typeInfo)
|
private NetVariantType GetPrefVariantType(Type typeInfo)
|
||||||
{
|
{
|
||||||
if (typeInfo == typeof(bool))
|
if (typeInfo == typeof(bool))
|
||||||
|
|
|
||||||
16
src/net/Qml.Net/Internal/Del.cs
Normal file
16
src/net/Qml.Net/Internal/Del.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using Qml.Net.Internal.Qml;
|
||||||
|
|
||||||
|
namespace Qml.Net.Internal
|
||||||
|
{
|
||||||
|
internal class Del
|
||||||
|
{
|
||||||
|
public event Action<NetVariantList> Invoked;
|
||||||
|
|
||||||
|
public void Raise(NetVariantList parameters)
|
||||||
|
{
|
||||||
|
var handler = Invoked;
|
||||||
|
handler?.Invoke(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -55,6 +55,8 @@ namespace Qml.Net.Internal
|
||||||
destination.DateTime = ((DateTimeOffset)source).DateTime;
|
destination.DateTime = ((DateTimeOffset)source).DateTime;
|
||||||
else if (typeof(INetJsValue).IsAssignableFrom(type))
|
else if (typeof(INetJsValue).IsAssignableFrom(type))
|
||||||
destination.JsValue = ((NetJsValue.NetJsValueDynamic)source).JsValue;
|
destination.JsValue = ((NetJsValue.NetJsValueDynamic)source).JsValue;
|
||||||
|
else if (typeof(INetQObject).IsAssignableFrom(type))
|
||||||
|
destination.QObject = ((NetQObject.NetQObjectDynamic)source).QObject;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type.IsEnum)
|
if (type.IsEnum)
|
||||||
|
|
@ -131,6 +133,9 @@ namespace Qml.Net.Internal
|
||||||
case NetVariantType.JsValue:
|
case NetVariantType.JsValue:
|
||||||
destination = source.JsValue.AsDynamic();
|
destination = source.JsValue.AsDynamic();
|
||||||
break;
|
break;
|
||||||
|
case NetVariantType.QObject:
|
||||||
|
destination = source.QObject.AsDynamic();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unsupported variant type.");
|
throw new Exception("Unsupported variant type.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@ namespace Qml.Net.Internal
|
||||||
Utilities = LoadInteropType<UtilitiesInterop>(library, loader);
|
Utilities = LoadInteropType<UtilitiesInterop>(library, loader);
|
||||||
QtWebEngine = LoadInteropType<QtWebEngineInterop>(library, loader);
|
QtWebEngine = LoadInteropType<QtWebEngineInterop>(library, loader);
|
||||||
QTest = LoadInteropType<QTestInterop>(library, loader);
|
QTest = LoadInteropType<QTestInterop>(library, loader);
|
||||||
|
NetQObject = LoadInteropType<NetQObjectInterop>(library, loader);
|
||||||
|
NetQObjectSignalConnection = LoadInteropType<NetQObjectSignalConnectionInterop>(library, loader);
|
||||||
|
|
||||||
// RuntimeManager.ConfigureRuntimeDirectory may set these environment variables.
|
// RuntimeManager.ConfigureRuntimeDirectory may set these environment variables.
|
||||||
// However, they only really work when called with Qt.PutEnv.
|
// However, they only really work when called with Qt.PutEnv.
|
||||||
|
|
@ -122,6 +124,10 @@ namespace Qml.Net.Internal
|
||||||
public static QtWebEngineInterop QtWebEngine { get; }
|
public static QtWebEngineInterop QtWebEngine { get; }
|
||||||
|
|
||||||
public static QTestInterop QTest { get; }
|
public static QTestInterop QTest { get; }
|
||||||
|
|
||||||
|
public static NetQObjectInterop NetQObject { get; }
|
||||||
|
|
||||||
|
public static NetQObjectSignalConnectionInterop NetQObjectSignalConnection { get; set; }
|
||||||
|
|
||||||
private static T LoadInteropType<T>(IntPtr library, IPlatformLoader loader)
|
private static T LoadInteropType<T>(IntPtr library, IPlatformLoader loader)
|
||||||
where T : new()
|
where T : new()
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,22 @@ namespace Qml.Net.Internal.Qml
|
||||||
return unpacked;
|
return unpacked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetProperty(string propertyName, object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
_jsValue.SetProperty(propertyName, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (var variant = new NetVariant())
|
||||||
|
{
|
||||||
|
Helpers.Pack(value, variant, value.GetType());
|
||||||
|
_jsValue.SetProperty(propertyName, variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public object GetItemAtIndex(int arrayIndex)
|
public object GetItemAtIndex(int arrayIndex)
|
||||||
{
|
{
|
||||||
var result = _jsValue.GetItemAtIndex(arrayIndex);
|
var result = _jsValue.GetItemAtIndex(arrayIndex);
|
||||||
|
|
@ -170,19 +186,7 @@ namespace Qml.Net.Internal.Qml
|
||||||
|
|
||||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||||
{
|
{
|
||||||
if (value == null)
|
SetProperty(binder.Name, value);
|
||||||
{
|
|
||||||
_jsValue.SetProperty(binder.Name, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var variant = new NetVariant())
|
|
||||||
{
|
|
||||||
Helpers.PackValue(value, variant);
|
|
||||||
_jsValue.SetProperty(binder.Name, variant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
270
src/net/Qml.Net/Internal/Qml/NetQObject.cs
Normal file
270
src/net/Qml.Net/Internal/Qml/NetQObject.cs
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Qml.Net.Internal.Types;
|
||||||
|
|
||||||
|
namespace Qml.Net.Internal.Qml
|
||||||
|
{
|
||||||
|
internal class NetQObject : BaseDisposable
|
||||||
|
{
|
||||||
|
public NetQObject(IntPtr handle, bool ownsHandle = true)
|
||||||
|
: base(handle, ownsHandle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeUnmanaged(IntPtr ptr)
|
||||||
|
{
|
||||||
|
Interop.NetQObject.Destroy(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetVariant GetProperty(string propertyName)
|
||||||
|
{
|
||||||
|
byte wasSuccessful = 0;
|
||||||
|
var result = Interop.NetQObject.GetProperty(Handle, propertyName, ref wasSuccessful);
|
||||||
|
if (wasSuccessful == 0)
|
||||||
|
{
|
||||||
|
// Dispose of the type before we throw
|
||||||
|
using (result == IntPtr.Zero ? null : new NetVariant(result)) { }
|
||||||
|
throw new Exception("Getting property failed.");
|
||||||
|
}
|
||||||
|
return result != IntPtr.Zero ? new NetVariant(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetProperty(string propertyName, NetVariant value)
|
||||||
|
{
|
||||||
|
byte wasSuccessful = 0;
|
||||||
|
Interop.NetQObject.SetProperty(Handle, propertyName, value?.Handle ?? IntPtr.Zero, ref wasSuccessful);
|
||||||
|
if (wasSuccessful == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Setting property failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetVariant InvokeMethod(string methodName, NetVariantList parameters)
|
||||||
|
{
|
||||||
|
byte wasSuccessful = 0;
|
||||||
|
var result = Interop.NetQObject.InvokeMethod(Handle, methodName, parameters?.Handle ?? IntPtr.Zero, ref wasSuccessful);
|
||||||
|
|
||||||
|
if (wasSuccessful == 0)
|
||||||
|
{
|
||||||
|
// Dispose of the type before we throw
|
||||||
|
using (result == IntPtr.Zero ? null : new NetVariant(result)) { }
|
||||||
|
throw new Exception("Invoking method failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result != IntPtr.Zero ? new NetVariant(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetQObjectSignalConnection AttachSignal(string signalName, Del del)
|
||||||
|
{
|
||||||
|
using (var delReference = NetReference.CreateForObject(del))
|
||||||
|
{
|
||||||
|
byte wasSuccessful = 0;
|
||||||
|
var result = Interop.NetQObject.AttachSignal(Handle, signalName, delReference.Handle, ref wasSuccessful);
|
||||||
|
|
||||||
|
if (wasSuccessful == 0)
|
||||||
|
{
|
||||||
|
// Dispose of the type before we throw
|
||||||
|
using (result == IntPtr.Zero ? null : new NetQObjectSignalConnection(result)) { }
|
||||||
|
throw new Exception("Attaching to signal failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result == IntPtr.Zero ? null : new NetQObjectSignalConnection(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetQObjectSignalConnection AttachNotifySignal(string propertyName, Del del)
|
||||||
|
{
|
||||||
|
using (var delReference = NetReference.CreateForObject(del))
|
||||||
|
{
|
||||||
|
byte wasSuccessful = 0;
|
||||||
|
var result = Interop.NetQObject.AttachNotifySignal(Handle, propertyName, delReference.Handle, ref wasSuccessful);
|
||||||
|
|
||||||
|
if (wasSuccessful == 0)
|
||||||
|
{
|
||||||
|
// Dispose of the type before we throw
|
||||||
|
using (result == IntPtr.Zero ? null : new NetQObjectSignalConnection(result)) { }
|
||||||
|
throw new Exception("Attaching to notify signal failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result == IntPtr.Zero ? null : new NetQObjectSignalConnection(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public dynamic AsDynamic()
|
||||||
|
{
|
||||||
|
return new NetQObjectDynamic(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NetQObjectDynamic : DynamicObject, INetQObject
|
||||||
|
{
|
||||||
|
readonly NetQObject _qObject;
|
||||||
|
|
||||||
|
public NetQObjectDynamic(NetQObject qObject)
|
||||||
|
{
|
||||||
|
_qObject = qObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_qObject.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetQObject QObject => _qObject;
|
||||||
|
|
||||||
|
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||||
|
{
|
||||||
|
result = GetProperty(binder.Name);
|
||||||
|
// TODO: Check if this was actually a property
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||||
|
{
|
||||||
|
SetProperty(binder.Name, value);
|
||||||
|
// TODO: Check if this was actually a property
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetProperty(string propertyName)
|
||||||
|
{
|
||||||
|
var property = _qObject.GetProperty(propertyName);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
object unpacked = null;
|
||||||
|
Helpers.Unpackvalue(ref unpacked, property);
|
||||||
|
property.Dispose();
|
||||||
|
return unpacked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetProperty(string propertyName, object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
_qObject.SetProperty(propertyName, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (var variant = new NetVariant())
|
||||||
|
{
|
||||||
|
Helpers.PackValue(value, variant);
|
||||||
|
_qObject.SetProperty(propertyName, variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object InvokeMethod(string methodName, params object[] parameters)
|
||||||
|
{
|
||||||
|
NetVariantList variantParameters = null;
|
||||||
|
if (parameters != null && parameters.Length > 0)
|
||||||
|
{
|
||||||
|
variantParameters = new NetVariantList();
|
||||||
|
foreach (var parameter in parameters)
|
||||||
|
{
|
||||||
|
using (var variantParameter = NetVariant.From(parameter))
|
||||||
|
{
|
||||||
|
variantParameters.Add(variantParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (variantParameters)
|
||||||
|
using (var result = _qObject.InvokeMethod(methodName, variantParameters))
|
||||||
|
{
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
object unpacked = null;
|
||||||
|
Helpers.Unpackvalue(ref unpacked, result);
|
||||||
|
result.Dispose();
|
||||||
|
return unpacked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDisposable AttachSignal(string signalName, SignalHandler handler)
|
||||||
|
{
|
||||||
|
var del = new Del();
|
||||||
|
del.Invoked += parameters =>
|
||||||
|
{
|
||||||
|
var result = new List<object>();
|
||||||
|
|
||||||
|
var parametersCount = parameters.Count;
|
||||||
|
for (var x = 0; x < parametersCount; x++)
|
||||||
|
{
|
||||||
|
using (var parameter = parameters.Get(x))
|
||||||
|
{
|
||||||
|
object parameterValue = null;
|
||||||
|
Helpers.Unpackvalue(ref parameterValue, parameter);
|
||||||
|
result.Add(parameterValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
return _qObject.AttachSignal(signalName, del);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDisposable AttachNotifySignal(string propertyName, SignalHandler handler)
|
||||||
|
{
|
||||||
|
var del = new Del();
|
||||||
|
del.Invoked += parameters =>
|
||||||
|
{
|
||||||
|
var result = new List<object>();
|
||||||
|
|
||||||
|
var parametersCount = parameters.Count;
|
||||||
|
for (var x = 0; x < parametersCount; x++)
|
||||||
|
{
|
||||||
|
using (var parameter = parameters.Get(x))
|
||||||
|
{
|
||||||
|
object parameterValue = null;
|
||||||
|
Helpers.Unpackvalue(ref parameterValue, parameter);
|
||||||
|
result.Add(parameterValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
return _qObject.AttachNotifySignal(propertyName, del);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NetQObjectInterop
|
||||||
|
{
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_destroy")]
|
||||||
|
public DestroyDel Destroy { get; set; }
|
||||||
|
|
||||||
|
public delegate void DestroyDel(IntPtr qObject);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_getProperty")]
|
||||||
|
public GetPropertyDel GetProperty { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr GetPropertyDel(IntPtr qObject, [MarshalAs(UnmanagedType.LPWStr)] string propertyName, ref byte result);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_setProperty")]
|
||||||
|
public SetPropertyDel SetProperty { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr SetPropertyDel(IntPtr qObject, [MarshalAs(UnmanagedType.LPWStr)] string propertyName, IntPtr netVariant, ref byte result);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_invokeMethod")]
|
||||||
|
public InvokeMethodDel InvokeMethod { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr InvokeMethodDel(IntPtr qObject, [MarshalAs(UnmanagedType.LPWStr)] string methodName, IntPtr parameters, ref byte result);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_attachSignal")]
|
||||||
|
public AttachSignalDel AttachSignal { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr AttachSignalDel(IntPtr qObject, [MarshalAs(UnmanagedType.LPWStr)] string signalName, IntPtr del, ref byte result);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_attachNotifySignal")]
|
||||||
|
public AttachNotifySignalDel AttachNotifySignal { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr AttachNotifySignalDel(IntPtr qObject, [MarshalAs(UnmanagedType.LPWStr)] string signalName, IntPtr del, ref byte result);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/net/Qml.Net/Internal/Qml/NetQObjectSignalConnection.cs
Normal file
25
src/net/Qml.Net/Internal/Qml/NetQObjectSignalConnection.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Qml.Net.Internal.Qml
|
||||||
|
{
|
||||||
|
internal class NetQObjectSignalConnection : BaseDisposable
|
||||||
|
{
|
||||||
|
public NetQObjectSignalConnection(IntPtr handle, bool ownsHandle = true)
|
||||||
|
: base(handle, ownsHandle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeUnmanaged(IntPtr ptr)
|
||||||
|
{
|
||||||
|
Interop.NetQObjectSignalConnection.Destroy(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NetQObjectSignalConnectionInterop
|
||||||
|
{
|
||||||
|
[NativeSymbol(Entrypoint = "net_qobject_signal_handler_destroy")]
|
||||||
|
public DestroyDel Destroy { get; set; }
|
||||||
|
|
||||||
|
public delegate void DestroyDel(IntPtr signalHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Qml.Net.Internal.Qml
|
||||||
get => Utilities.ContainerToString(Interop.NetVariant.GetString(Handle));
|
get => Utilities.ContainerToString(Interop.NetVariant.GetString(Handle));
|
||||||
set => Interop.NetVariant.SetString(Handle, value);
|
set => Interop.NetVariant.SetString(Handle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTimeOffset? DateTime
|
public DateTimeOffset? DateTime
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -135,6 +135,16 @@ namespace Qml.Net.Internal.Qml
|
||||||
set => Interop.NetVariant.SetJsValue(Handle, value?.Handle ?? IntPtr.Zero);
|
set => Interop.NetVariant.SetJsValue(Handle, value?.Handle ?? IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NetQObject QObject
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = Interop.NetVariant.GetQObject(Handle);
|
||||||
|
return result == IntPtr.Zero ? null : new NetQObject(result);
|
||||||
|
}
|
||||||
|
set => Interop.NetVariant.SetQObject(Handle, value?.Handle ?? IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
Interop.NetVariant.Clear(Handle);
|
Interop.NetVariant.Clear(Handle);
|
||||||
|
|
@ -174,6 +184,8 @@ namespace Qml.Net.Internal.Qml
|
||||||
|
|
||||||
case NetVariantType.JsValue:
|
case NetVariantType.JsValue:
|
||||||
return JsValue.AsDynamic();
|
return JsValue.AsDynamic();
|
||||||
|
case NetVariantType.QObject:
|
||||||
|
return QObject.AsDynamic();
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"unhandled type {VariantType}");
|
throw new NotImplementedException($"unhandled type {VariantType}");
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +199,20 @@ namespace Qml.Net.Internal.Qml
|
||||||
public static NetVariant From<T>(T value)
|
public static NetVariant From<T>(T value)
|
||||||
{
|
{
|
||||||
var variant = new NetVariant();
|
var variant = new NetVariant();
|
||||||
Helpers.Pack(value, variant, typeof(T));
|
if (value != null)
|
||||||
|
{
|
||||||
|
Helpers.Pack(value, variant, typeof(T));
|
||||||
|
}
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetVariant From(object value)
|
||||||
|
{
|
||||||
|
var variant = new NetVariant();
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
Helpers.Pack(value, variant, value.GetType());
|
||||||
|
}
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -329,6 +354,16 @@ namespace Qml.Net.Internal.Qml
|
||||||
|
|
||||||
public delegate IntPtr GetJsValueDel(IntPtr variant);
|
public delegate IntPtr GetJsValueDel(IntPtr variant);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_variant_setQObject")]
|
||||||
|
public SetQObjectDel SetQObject { get; set; }
|
||||||
|
|
||||||
|
public delegate void SetQObjectDel(IntPtr variant, IntPtr jsValue);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "net_variant_getQObject")]
|
||||||
|
public GetQObjectDel GetQObject { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr GetQObjectDel(IntPtr variant);
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "net_variant_clear")]
|
[NativeSymbol(Entrypoint = "net_variant_clear")]
|
||||||
public ClearDel Clear { get; set; }
|
public ClearDel Clear { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Dynamic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ namespace Qml.Net.Internal.Types
|
||||||
public IntPtr RaseNetSignals;
|
public IntPtr RaseNetSignals;
|
||||||
public IntPtr AwaitTask;
|
public IntPtr AwaitTask;
|
||||||
public IntPtr Serialize;
|
public IntPtr Serialize;
|
||||||
|
public IntPtr InvokeDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CallbacksInterop
|
internal class CallbacksInterop
|
||||||
|
|
@ -88,6 +90,8 @@ namespace Qml.Net.Internal.Types
|
||||||
Task AwaitTask(IntPtr target, IntPtr succesCallback, IntPtr failureCallback);
|
Task AwaitTask(IntPtr target, IntPtr succesCallback, IntPtr failureCallback);
|
||||||
|
|
||||||
bool Serialize(IntPtr instance, IntPtr result);
|
bool Serialize(IntPtr instance, IntPtr result);
|
||||||
|
|
||||||
|
void InvokeDelegate(IntPtr del, IntPtr parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CallbacksImpl
|
internal class CallbacksImpl
|
||||||
|
|
@ -108,6 +112,7 @@ namespace Qml.Net.Internal.Types
|
||||||
RaiseNetSignalsDelegate _raiseNetSignalsDelegate;
|
RaiseNetSignalsDelegate _raiseNetSignalsDelegate;
|
||||||
AwaitTaskDelegate _awaitTaskDelegate;
|
AwaitTaskDelegate _awaitTaskDelegate;
|
||||||
SerializeDelegate _serializeDelegate;
|
SerializeDelegate _serializeDelegate;
|
||||||
|
InvokeDelegateDelegate _invokeDelegateDelegate;
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
delegate byte IsTypeValidDelegate([MarshalAs(UnmanagedType.LPWStr)]string typeName);
|
delegate byte IsTypeValidDelegate([MarshalAs(UnmanagedType.LPWStr)]string typeName);
|
||||||
|
|
@ -153,6 +158,9 @@ namespace Qml.Net.Internal.Types
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
delegate byte SerializeDelegate(IntPtr instance, IntPtr result);
|
delegate byte SerializeDelegate(IntPtr instance, IntPtr result);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate void InvokeDelegateDelegate(IntPtr del, IntPtr parameters);
|
||||||
|
|
||||||
public CallbacksImpl(ICallbacks callbacks)
|
public CallbacksImpl(ICallbacks callbacks)
|
||||||
{
|
{
|
||||||
|
|
@ -202,6 +210,9 @@ namespace Qml.Net.Internal.Types
|
||||||
|
|
||||||
_serializeDelegate = Serialize;
|
_serializeDelegate = Serialize;
|
||||||
GCHandle.Alloc(_serializeDelegate);
|
GCHandle.Alloc(_serializeDelegate);
|
||||||
|
|
||||||
|
_invokeDelegateDelegate = InvokeDelegate;
|
||||||
|
GCHandle.Alloc(_invokeDelegateDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte IsTypeValid(string typeName)
|
private byte IsTypeValid(string typeName)
|
||||||
|
|
@ -282,6 +293,11 @@ namespace Qml.Net.Internal.Types
|
||||||
return _callbacks.Serialize(instance, result) ? (byte)1 : (byte)0;
|
return _callbacks.Serialize(instance, result) ? (byte)1 : (byte)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InvokeDelegate(IntPtr del, IntPtr parameters)
|
||||||
|
{
|
||||||
|
_callbacks.InvokeDelegate(del, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
public Callbacks Callbacks()
|
public Callbacks Callbacks()
|
||||||
{
|
{
|
||||||
return new Callbacks
|
return new Callbacks
|
||||||
|
|
@ -300,7 +316,8 @@ namespace Qml.Net.Internal.Types
|
||||||
GCCollect = Marshal.GetFunctionPointerForDelegate(_gcCollectDelegate),
|
GCCollect = Marshal.GetFunctionPointerForDelegate(_gcCollectDelegate),
|
||||||
RaseNetSignals = Marshal.GetFunctionPointerForDelegate(_raiseNetSignalsDelegate),
|
RaseNetSignals = Marshal.GetFunctionPointerForDelegate(_raiseNetSignalsDelegate),
|
||||||
AwaitTask = Marshal.GetFunctionPointerForDelegate(_awaitTaskDelegate),
|
AwaitTask = Marshal.GetFunctionPointerForDelegate(_awaitTaskDelegate),
|
||||||
Serialize = Marshal.GetFunctionPointerForDelegate(_serializeDelegate)
|
Serialize = Marshal.GetFunctionPointerForDelegate(_serializeDelegate),
|
||||||
|
InvokeDelegate = Marshal.GetFunctionPointerForDelegate(_invokeDelegateDelegate)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,6 @@
|
||||||
DateTime,
|
DateTime,
|
||||||
Object,
|
Object,
|
||||||
JsValue,
|
JsValue,
|
||||||
|
QObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue