mirror of
https://github.com/qmlnet/qmlnet.git
synced 2026-05-21 06:45:32 -06:00
Added support for associated signals with properties.
This commit is contained in:
parent
ee7ac16c5f
commit
79bd19d6df
11 changed files with 245 additions and 71 deletions
|
|
@ -199,54 +199,13 @@ QMetaObject *metaObjectFor(QSharedPointer<NetTypeInfo> typeInfo)
|
|||
for(uint index = 0; index <= typeInfo->getSignalCount() - 1; index++)
|
||||
{
|
||||
QSharedPointer<NetSignalInfo> signalInfo = typeInfo->getSignal(index);
|
||||
QString signature = signalInfo->getName();
|
||||
|
||||
signature.append("(");
|
||||
|
||||
if(signalInfo->getParameterCount() > 0) {
|
||||
for(uint parameterIndex = 0; parameterIndex <= signalInfo->getParameterCount() - 1; parameterIndex++)
|
||||
{
|
||||
if(parameterIndex > 0) {
|
||||
signature.append(", ");
|
||||
}
|
||||
signature.append("QVariant");
|
||||
}
|
||||
}
|
||||
|
||||
signature.append(")");
|
||||
|
||||
mob.addSignal(signature.toLocal8Bit().constData());
|
||||
QString signature = signalInfo->getSignature();
|
||||
mob.addSignal(QMetaObject::normalizedSignature(signature.toLocal8Bit().constData()));
|
||||
}
|
||||
}
|
||||
|
||||
if(typeInfo->getMethodCount() > 0) {
|
||||
for(uint index = 0; index <= typeInfo->getMethodCount() - 1; index++)
|
||||
{
|
||||
QSharedPointer<NetMethodInfo> methodInfo = typeInfo->getMethodInfo(index);
|
||||
QSharedPointer<NetTypeInfo> returnType = methodInfo->getReturnType();
|
||||
QString signature = methodInfo->getMethodName();
|
||||
|
||||
signature.append("(");
|
||||
|
||||
if(methodInfo->getParameterCount() > 0) {
|
||||
for(uint parameterIndex = 0; parameterIndex <= methodInfo->getParameterCount() - 1; parameterIndex++)
|
||||
{
|
||||
if(parameterIndex > 0) {
|
||||
signature.append(", ");
|
||||
}
|
||||
signature.append("QVariant");
|
||||
}
|
||||
}
|
||||
|
||||
signature.append(")");
|
||||
|
||||
if(returnType != NULL) {
|
||||
mob.addMethod(signature.toLocal8Bit().constData(), "QVariant");
|
||||
} else {
|
||||
mob.addMethod(signature.toLocal8Bit().constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: It is important to register properties after the signals (before methods)
|
||||
// because of the assumptions we make about getting the "notifySignal" by index.
|
||||
|
||||
if(typeInfo->getPropertyCount() > 0) {
|
||||
for(uint index = 0; index <= typeInfo->getPropertyCount() - 1; index++)
|
||||
|
|
@ -255,11 +214,37 @@ QMetaObject *metaObjectFor(QSharedPointer<NetTypeInfo> typeInfo)
|
|||
QMetaPropertyBuilder propb = mob.addProperty(propertyInfo->getPropertyName().toLatin1(),
|
||||
"QVariant",
|
||||
index);
|
||||
QSharedPointer<NetSignalInfo> notifySignal = propertyInfo->getNotifySignal();
|
||||
if(notifySignal != NULL) {
|
||||
// The signal was previously registered, find the index.
|
||||
for(uint signalIndex = 0; signalIndex <= typeInfo->getSignalCount() - 1; signalIndex++)
|
||||
{
|
||||
if(typeInfo->getSignal(signalIndex) == notifySignal) {
|
||||
QMetaMethodBuilder notifySignalBuilder = mob.method(signalIndex);
|
||||
propb.setNotifySignal(notifySignalBuilder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
propb.setWritable(propertyInfo->canWrite());
|
||||
propb.setReadable(propertyInfo->canRead());
|
||||
}
|
||||
}
|
||||
|
||||
if(typeInfo->getMethodCount() > 0) {
|
||||
for(uint index = 0; index <= typeInfo->getMethodCount() - 1; index++)
|
||||
{
|
||||
QSharedPointer<NetMethodInfo> methodInfo = typeInfo->getMethodInfo(index);
|
||||
QSharedPointer<NetTypeInfo> returnType = methodInfo->getReturnType();
|
||||
QString signature = methodInfo->getSignature();
|
||||
if(returnType != NULL) {
|
||||
mob.addMethod(QMetaObject::normalizedSignature(signature.toLocal8Bit().constData()), "QVariant");
|
||||
} else {
|
||||
mob.addMethod(QMetaObject::normalizedSignature(signature.toLocal8Bit().constData()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMetaObject *mo = mob.toMetaObject();
|
||||
typeInfo->metaObject = mo;
|
||||
return mo;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,26 @@ QSharedPointer<NetMethodInfoArguement> NetMethodInfo::getParameter(uint index) {
|
|||
return _parameters.at(index);
|
||||
}
|
||||
|
||||
QString NetMethodInfo::getSignature() {
|
||||
QString signature = _methodName;
|
||||
|
||||
signature.append("(");
|
||||
|
||||
if(_parameters.size() > 0) {
|
||||
for(int parameterIndex = 0; parameterIndex <= _parameters.size() - 1; parameterIndex++)
|
||||
{
|
||||
if(parameterIndex > 0) {
|
||||
signature.append(",");
|
||||
}
|
||||
signature.append("QVariant");
|
||||
}
|
||||
}
|
||||
|
||||
signature.append(")");
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Q_DECL_EXPORT void method_info_parameter_destroy(NetMethodInfoArguementContainer* container) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ public:
|
|||
uint getParameterCount();
|
||||
QSharedPointer<NetMethodInfoArguement> getParameter(uint index);
|
||||
|
||||
QString getSignature();
|
||||
|
||||
private:
|
||||
QSharedPointer<NetTypeInfo> _parentTypeInfo;
|
||||
QString _methodName;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
#include <QtNetCoreQml/types/NetPropertyInfo.h>
|
||||
#include <QtNetCoreQml/types/NetSignalInfo.h>
|
||||
|
||||
NetPropertyInfo::NetPropertyInfo(QSharedPointer<NetTypeInfo> parentType,
|
||||
QString name,
|
||||
QSharedPointer<NetTypeInfo> returnType,
|
||||
bool canRead,
|
||||
bool canWrite) :
|
||||
bool canWrite,
|
||||
QSharedPointer<NetSignalInfo> notifySignal) :
|
||||
_parentType(parentType),
|
||||
_name(name),
|
||||
_returnType(returnType),
|
||||
_canRead(canRead),
|
||||
_canWrite(canWrite)
|
||||
_canWrite(canWrite),
|
||||
_notifySignal(notifySignal)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -39,19 +42,30 @@ bool NetPropertyInfo::canWrite()
|
|||
return _canWrite;
|
||||
}
|
||||
|
||||
QSharedPointer<NetSignalInfo> NetPropertyInfo::getNotifySignal()
|
||||
{
|
||||
return _notifySignal;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Q_DECL_EXPORT NetPropertyInfoContainer* property_info_create(NetTypeInfoContainer* parentType,
|
||||
Q_DECL_EXPORT NetPropertyInfoContainer* property_info_create(NetTypeInfoContainer* parentTypeContainer,
|
||||
LPWSTR name,
|
||||
NetTypeInfoContainer* returnType,
|
||||
bool canRead,
|
||||
bool canWrite) {
|
||||
bool canWrite,
|
||||
NetSignalInfoContainer* notifySignalContainer) {
|
||||
NetPropertyInfoContainer* result = new NetPropertyInfoContainer();
|
||||
NetPropertyInfo* instance = new NetPropertyInfo(parentType->netTypeInfo,
|
||||
QSharedPointer<NetSignalInfo> notifySignal;
|
||||
if(notifySignalContainer != NULL) {
|
||||
notifySignal = notifySignalContainer->signal;
|
||||
}
|
||||
NetPropertyInfo* instance = new NetPropertyInfo(parentTypeContainer->netTypeInfo,
|
||||
QString::fromUtf16((const char16_t*)name),
|
||||
returnType->netTypeInfo,
|
||||
canRead,
|
||||
canWrite);
|
||||
canWrite,
|
||||
notifySignal);
|
||||
result->property = QSharedPointer<NetPropertyInfo>(instance);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -85,4 +99,12 @@ Q_DECL_EXPORT bool property_info_canWrite(NetPropertyInfoContainer* container) {
|
|||
return container->property->canWrite();
|
||||
}
|
||||
|
||||
Q_DECL_EXPORT NetSignalInfoContainer* property_info_getNotifySignal(NetPropertyInfoContainer* container) {
|
||||
QSharedPointer<NetSignalInfo> notifySignal = container->property->getNotifySignal();
|
||||
if(notifySignal == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return new NetSignalInfoContainer{notifySignal};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,18 +9,21 @@ public:
|
|||
QString name,
|
||||
QSharedPointer<NetTypeInfo> returnType,
|
||||
bool canRead,
|
||||
bool canWrite);
|
||||
bool canWrite,
|
||||
QSharedPointer<NetSignalInfo> notifySignal);
|
||||
QSharedPointer<NetTypeInfo> getParentType();
|
||||
QString getPropertyName();
|
||||
QSharedPointer<NetTypeInfo> getReturnType();
|
||||
bool canRead();
|
||||
bool canWrite();
|
||||
QSharedPointer<NetSignalInfo> getNotifySignal();
|
||||
private:
|
||||
QSharedPointer<NetTypeInfo> _parentType;
|
||||
QString _name;
|
||||
QSharedPointer<NetTypeInfo> _returnType;
|
||||
bool _canRead;
|
||||
bool _canWrite;
|
||||
QSharedPointer<NetSignalInfo> _notifySignal;
|
||||
};
|
||||
|
||||
struct NetPropertyInfoContainer {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,27 @@ NetVariantTypeEnum NetSignalInfo::getParameter(uint index) {
|
|||
return _parameters.at(index);
|
||||
}
|
||||
|
||||
QString NetSignalInfo::getSignature() {
|
||||
QString signature = _name;
|
||||
|
||||
signature.append("(");
|
||||
|
||||
if(_parameters.size() > 0) {
|
||||
for(int parameterIndex = 0; parameterIndex <= _parameters.size() - 1; parameterIndex++)
|
||||
{
|
||||
if(parameterIndex > 0) {
|
||||
signature.append(",");
|
||||
}
|
||||
signature.append("QVariant");
|
||||
}
|
||||
}
|
||||
|
||||
signature.append(")");
|
||||
|
||||
return signature;
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Q_DECL_EXPORT NetSignalInfoContainer* signal_info_create(NetTypeInfoContainer* parentTypeContainer, LPWSTR name) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public:
|
|||
void addParameter(NetVariantTypeEnum type);
|
||||
uint getParameterCount();
|
||||
NetVariantTypeEnum getParameter(uint index);
|
||||
QString getSignature();
|
||||
private:
|
||||
QSharedPointer<NetTypeInfo> _parentType;
|
||||
QString _name;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using FluentAssertions;
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Qt.NetCore.Types;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -128,6 +129,7 @@ namespace Qt.NetCore.Tests.Types
|
|||
property.CanWrite.Should().BeTrue();
|
||||
property.ReturnType.ClassName.Should().Be("String");
|
||||
property.ParentType.ClassName.Should().Be("TestType6");
|
||||
property.NotifySignal.Should().BeNull();
|
||||
}
|
||||
|
||||
[Signal("testSignal", NetVariantType.DateTime, NetVariantType.Object)]
|
||||
|
|
@ -149,6 +151,58 @@ namespace Qt.NetCore.Tests.Types
|
|||
signal.GetParameter(1).Should().Be(NetVariantType.Object);
|
||||
}
|
||||
|
||||
[Signal("signalName")]
|
||||
public class TestType8
|
||||
{
|
||||
[NotifySignal("signalName")]
|
||||
public string Property { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_get_notifiy_signal_for_property()
|
||||
{
|
||||
var type = NetTypeManager.GetTypeInfo<TestType8>();
|
||||
type.SignalCount.Should().Be(1);
|
||||
type.PropertyCount.Should().Be(1);
|
||||
type.GetProperty(0).Name.Should().Be("Property");
|
||||
type.GetProperty(0).NotifySignal.Should().NotBeNull();
|
||||
type.GetProperty(0).NotifySignal.Name.Should().Be("signalName");
|
||||
}
|
||||
|
||||
public class TestType9
|
||||
{
|
||||
[NotifySignal("signalName")]
|
||||
public string Property { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_auto_add_signal_for_property_notification()
|
||||
{
|
||||
var type = NetTypeManager.GetTypeInfo<TestType9>();
|
||||
type.SignalCount.Should().Be(1);
|
||||
type.PropertyCount.Should().Be(1);
|
||||
type.GetProperty(0).Name.Should().Be("Property");
|
||||
type.GetProperty(0).NotifySignal.Should().NotBeNull();
|
||||
type.GetProperty(0).NotifySignal.Name.Should().Be("signalName");
|
||||
}
|
||||
|
||||
public class TestType10
|
||||
{
|
||||
[NotifySignal]
|
||||
public string Property { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_auto_create_signal_with_property_name_if_no_name_given()
|
||||
{
|
||||
var type = NetTypeManager.GetTypeInfo<TestType10>();
|
||||
type.SignalCount.Should().Be(1);
|
||||
type.PropertyCount.Should().Be(1);
|
||||
type.GetProperty(0).Name.Should().Be("Property");
|
||||
type.GetProperty(0).NotifySignal.Should().NotBeNull();
|
||||
type.GetProperty(0).NotifySignal.Name.Should().Be("PropertyChanged");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_type_returned_for_invalid_type()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,32 +68,61 @@ namespace Qt.NetCore.Internal
|
|||
type.AddMethod(method);
|
||||
}
|
||||
|
||||
var signals = new Dictionary<string, NetSignalInfo>();
|
||||
|
||||
foreach (var signalAttribute in typeInfo.GetCustomAttributes().OfType<SignalAttribute>())
|
||||
{
|
||||
var signal = new NetSignalInfo(type, signalAttribute.Name);
|
||||
foreach (var parameter in signalAttribute.Parameters)
|
||||
{
|
||||
signal.AddParameter(parameter);
|
||||
}
|
||||
type.AddSignal(signal);
|
||||
signals.Add(signal.Name, signal);
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in typeInfo.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
if (Helpers.IsPrimitive(propertyInfo.DeclaringType)) continue;
|
||||
|
||||
NetSignalInfo notifySignal = null;
|
||||
var notifySignalAttribute = propertyInfo.GetCustomAttribute<NotifySignalAttribute>();
|
||||
if (notifySignalAttribute != null)
|
||||
{
|
||||
var name = notifySignalAttribute.Name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
name = $"{propertyInfo.Name}Changed";
|
||||
}
|
||||
|
||||
if (signals.ContainsKey(name))
|
||||
{
|
||||
notifySignal = signals[name];
|
||||
// Make sure the signal we are referencing has no parameters.
|
||||
if (notifySignal.ParameterCount != 0)
|
||||
{
|
||||
// TODO: They can actually of parameters, but not implemented yet.
|
||||
throw new Exception("Notify signals must have no parameters.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
notifySignal = new NetSignalInfo(type, name);
|
||||
type.AddSignal(notifySignal);
|
||||
}
|
||||
}
|
||||
|
||||
using (var property = new NetPropertyInfo(
|
||||
type,
|
||||
propertyInfo.Name,
|
||||
NetTypeManager.GetTypeInfo(propertyInfo.PropertyType.AssemblyQualifiedName),
|
||||
propertyInfo.CanRead,
|
||||
propertyInfo.CanWrite))
|
||||
propertyInfo.CanWrite,
|
||||
notifySignal))
|
||||
{
|
||||
type.AddProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var signalAttribute in typeInfo.GetCustomAttributes().OfType<SignalAttribute>())
|
||||
{
|
||||
using (var signal = new NetSignalInfo(type, signalAttribute.Name))
|
||||
{
|
||||
foreach (var parameter in signalAttribute.Parameters)
|
||||
{
|
||||
signal.AddParameter(parameter);
|
||||
}
|
||||
type.AddSignal(signal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
20
src/net/Qt.NetCore/NotifySignalAttribute.cs
Normal file
20
src/net/Qt.NetCore/NotifySignalAttribute.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace Qt.NetCore
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class NotifySignalAttribute : Attribute
|
||||
{
|
||||
public NotifySignalAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NotifySignalAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,14 @@ namespace Qt.NetCore.Types
|
|||
string name,
|
||||
NetTypeInfo returnType,
|
||||
bool canRead,
|
||||
bool canWrite)
|
||||
bool canWrite,
|
||||
NetSignalInfo notifySignal)
|
||||
: this(Create(parentType,
|
||||
name,
|
||||
returnType,
|
||||
canRead,
|
||||
canWrite))
|
||||
canWrite,
|
||||
notifySignal))
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -31,13 +33,15 @@ namespace Qt.NetCore.Types
|
|||
string name,
|
||||
NetTypeInfo returnType,
|
||||
bool canRead,
|
||||
bool canWrite)
|
||||
bool canWrite,
|
||||
NetSignalInfo notifySignal)
|
||||
{
|
||||
return Interop.NetPropertyInfo.Create(parentType?.Handle ?? IntPtr.Zero,
|
||||
name,
|
||||
returnType?.Handle ?? IntPtr.Zero,
|
||||
canRead,
|
||||
canWrite);
|
||||
canWrite,
|
||||
notifySignal?.Handle ?? IntPtr.Zero);
|
||||
}
|
||||
|
||||
public NetTypeInfo ParentType => new NetTypeInfo(Interop.NetPropertyInfo.GetParentType(Handle));
|
||||
|
|
@ -49,6 +53,15 @@ namespace Qt.NetCore.Types
|
|||
public bool CanRead => Interop.NetPropertyInfo.GetCanRead(Handle);
|
||||
|
||||
public bool CanWrite => Interop.NetPropertyInfo.GetCanWrite(Handle);
|
||||
|
||||
public NetSignalInfo NotifySignal
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Interop.NetPropertyInfo.GetNotifySignal(Handle);
|
||||
return result == IntPtr.Zero ? null : new NetSignalInfo(result);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisposeUnmanaged(IntPtr ptr)
|
||||
{
|
||||
|
|
@ -63,7 +76,8 @@ namespace Qt.NetCore.Types
|
|||
[MarshalAs(UnmanagedType.LPWStr)]string methodName,
|
||||
IntPtr returnType,
|
||||
bool canRead,
|
||||
bool canWrite);
|
||||
bool canWrite,
|
||||
IntPtr notifySignal);
|
||||
[NativeSymbol(Entrypoint = "property_info_destroy")]
|
||||
void Destroy(IntPtr property);
|
||||
|
||||
|
|
@ -81,5 +95,8 @@ namespace Qt.NetCore.Types
|
|||
|
||||
[NativeSymbol(Entrypoint = "property_info_canWrite")]
|
||||
bool GetCanWrite(IntPtr property);
|
||||
|
||||
[NativeSymbol(Entrypoint = "property_info_getNotifySignal")]
|
||||
IntPtr GetNotifySignal(IntPtr property);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue