Fully supporting typed QObject parameters and return types (and casting/null).

This commit is contained in:
Paul Knopf 2019-04-24 13:18:10 -04:00
parent a7e362239a
commit c35ca8c24d
6 changed files with 169 additions and 7 deletions

View file

@ -99,7 +99,16 @@ QSharedPointer<NetVariant> NetQObject::invokeMethod(QString methodName, QSharedP
return nullptr;
}
NetQObjectArg returnValue(method.returnType());
int returnType = method.returnType();
if(returnType == QMetaType::UnknownType) {
qWarning() << "Unable to return type" << method.typeName() << ", it wasn't registered with the meta object system";
if(wasSuccess) {
*wasSuccess = false;
}
return nullptr;
}
NetQObjectArg returnValue(returnType);
NetQObjectArg val0;
NetQObjectArg val1;
NetQObjectArg val2;

View file

@ -124,6 +124,34 @@ void NetQObjectArg::pack()
}
break;
default:
QMetaType::TypeFlags flags = QMetaType::typeFlags(_metaTypeId);
if(flags & QMetaType::PointerToQObject) {
// If the netvariant is a QObject and is of the same type,
// let's use it.
QVariant possibleQObjectVariant = _netVariant->toQVariant();
if(possibleQObjectVariant.userType() == QMetaType::QObjectStar) {
QObject* value = possibleQObjectVariant.value<QObject*>();
if(value == nullptr) {
_variant = QVariant(_metaTypeId, nullptr);
break;
}
const QMetaObject* targetMetaObject = QMetaType::metaObjectForType(_metaTypeId);
QObject* casted = targetMetaObject->cast(value);
if(casted == nullptr) {
qWarning() << "Can't convert " << value->metaObject()->className() << "to" << QMetaType::typeName(_metaTypeId);
_variant = QVariant(_metaTypeId, nullptr);
break;
}
_variant = qVariantFromValue(casted);
break;
}
}
qWarning() << "Unsupported type: " << QMetaType::typeName(_metaTypeId);
_variant = QVariant(_metaTypeId, nullptr);
break;

View file

@ -2,13 +2,22 @@
#include <QQmlComponent>
#include <QDebug>
TestBaseQObject::TestBaseQObject()
: QObject(nullptr)
{
}
TestBaseQObject::~TestBaseQObject()
{
}
TestQObject::TestQObject()
: QObject(nullptr),
_writeOnly(0),
: _writeOnly(0),
_readAndWrite(0),
_propWithSignal(0)
{
}
TestQObject::~TestQObject()
@ -141,6 +150,24 @@ QObject* TestQObject::testSlotQObject(QObject* value)
return value;
}
TestBaseQObject* TestQObject::testSlotTypedBaseQObject(TestBaseQObject* value)
{
emit testSignalTypedBaseQObject(value);
return value;
}
TestQObject* TestQObject::testSlotTypedQObject(TestQObject* value)
{
emit testSignalTypedQObject(value);
return value;
}
TestDerivedQObject* TestQObject::testSlotTypedDerivedQObject(TestDerivedQObject* value)
{
emit testSignalTypedDerivedQObject(value);
return value;
}
qint32 TestQObject::testSlotQInt32(qint32 value)
{
emit testSignalQInt32(value);
@ -171,9 +198,23 @@ QVariantList TestQObject::testSlotQVariantList(QVariantList variantList)
return variantList;
}
TestDerivedQObject::TestDerivedQObject()
{
}
TestDerivedQObject::~TestDerivedQObject()
{
}
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)
{
qRegisterMetaType<TestBaseQObject*>();
qRegisterMetaType<TestQObject*>();
qRegisterMetaType<TestDerivedQObject*>();
QQmlComponent component(qmlEngineContainer->qmlEngine);
QString qmlString = QString::fromUtf16(static_cast<const char16_t*>(qml));
component.setData(qmlString.toUtf8(), QUrl());

View file

@ -5,7 +5,19 @@
#include <QmlNet/qml/QQmlApplicationEngine.h>
#include <QDateTime>
class TestQObject : public QObject
class TestBaseQObject;
class TestQObject;
class TestDerivedQObject;
class TestBaseQObject : public QObject
{
Q_OBJECT
public:
TestBaseQObject();
~TestBaseQObject();
};
class TestQObject : public TestBaseQObject
{
Q_OBJECT
Q_PROPERTY(int readOnly READ getReadOnly)
@ -40,6 +52,9 @@ signals:
void testSignalString(QString value);
void testSignalDateTime(QDateTime value);
void testSignalQObject(QObject* qObject);
void testSignalTypedBaseQObject(TestBaseQObject* value);
void testSignalTypedQObject(TestQObject* value);
void testSignalTypedDerivedQObject(TestDerivedQObject* value);
void testSignalQInt32(qint32 value);
void testSignalQUInt32(quint32 value);
void testSignalQInt64(qint64 value);
@ -61,11 +76,15 @@ public slots:
QString testSlotString(QString value);
QDateTime testSlotDateTime(QDateTime value);
QObject* testSlotQObject(QObject* value);
TestBaseQObject* testSlotTypedBaseQObject(TestBaseQObject* value);
TestQObject* testSlotTypedQObject(TestQObject* value);
TestDerivedQObject* testSlotTypedDerivedQObject(TestDerivedQObject* value);
qint32 testSlotQInt32(qint32 value);
quint32 testSlotQUInt32(quint32 value);
qint64 testSlotQInt64(qint64 value);
quint64 testSlotQUInt64(quint64 value);
QVariantList testSlotQVariantList(QVariantList variantList);
private:
int _writeOnly;
int _readAndWrite;
@ -73,4 +92,18 @@ private:
QVariant _variantValue;
};
class TestDerivedQObject : public TestQObject
{
Q_OBJECT
public:
TestDerivedQObject();
~TestDerivedQObject();
private:
};
Q_DECLARE_METATYPE(TestBaseQObject*);
Q_DECLARE_METATYPE(TestQObject*);
Q_DECLARE_METATYPE(TestDerivedQObject*);
#endif // NETTESTHELPER_H

View file

@ -401,6 +401,17 @@ void NetVariant::fromQVariant(const QVariant* variant, const QSharedPointer<NetV
break;
}
QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
if(flags & QMetaType::PointerToQObject) {
QObject* value = variant->value<QObject*>();
if(value == nullptr) {
destination->clear();
break;
}
destination->setQObject(QSharedPointer<NetQObject>(new NetQObject(value)));
break;
}
qDebug() << "Unsupported variant type: " << variant->type() << variant->typeName();
break;
}

View file

@ -472,6 +472,46 @@ namespace Qml.Net.Tests.Qml
});
}
[Fact]
public void Can_used_typed_base_qobject_with_qobject()
{
AssertQObject(qObject =>
{
qObject.SetProperty("objectName", "wer");
AssertValue(qObject, "TypedBaseQObject", qObject, result =>
{
var resultQObject = result.Should().NotBeNull().And.BeAssignableTo<INetQObject>().Subject;
resultQObject.GetProperty("objectName").Should().Be("wer");
});
});
}
[Fact]
public void Can_used_typed_qobject_with_qobject()
{
AssertQObject(qObject =>
{
qObject.SetProperty("objectName", "wer");
AssertValue(qObject, "TypedQObject", qObject, result =>
{
var resultQObject = result.Should().NotBeNull().And.BeAssignableTo<INetQObject>().Subject;
resultQObject.GetProperty("objectName").Should().Be("wer");
});
});
}
[Fact]
public void Value_is_null_when_using_invalid_qobject_type_with_qobject()
{
AssertQObject(qObject =>
{
AssertValue(qObject, "TypedDerivedQObject", qObject, result =>
{
result.Should().BeNull();
});
});
}
[Fact]
public void Can_use_object_with_qobject()
{
@ -554,7 +594,7 @@ namespace Qml.Net.Tests.Qml
});
});
}
private void AssertValue(INetQObject qObject, string method, object value)
{
var raised = false;