Skip to content

Commit

Permalink
Implement Qt property access
Browse files Browse the repository at this point in the history
  • Loading branch information
beckdave committed Mar 29, 2024
1 parent 0e1d2d3 commit cb9ae04
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 68 deletions.
238 changes: 174 additions & 64 deletions inc/finalmq/Qt/qt.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ class FillObjectTree : public IObjectVisitor
{
QLayout* layout = (QLayout*)&object;
QRect rect = layout->geometry();
objectData->properties.push_back({ "x", std::to_string(rect.x()) });
objectData->properties.push_back({ "y", std::to_string(rect.y()) });
objectData->properties.push_back({ "width", std::to_string(rect.width()) });
objectData->properties.push_back({ "height", std::to_string(rect.height()) });
objectData->properties.push_back({ "left", std::to_string(rect.left()) });
objectData->properties.push_back({ "top", std::to_string(rect.top()) });
objectData->properties.push_back({ "right", std::to_string(rect.right()) });
objectData->properties.push_back({ "bottom", std::to_string(rect.bottom()) });
objectData->properties.push_back({ "enabled", std::to_string(layout->isEnabled()) });

}
Expand Down Expand Up @@ -197,7 +197,7 @@ class FillObjectTree : public IObjectVisitor
if (value.canConvert<QRect>())
{
QRect rect = value.toRect();
v = "{\"x\":" + QString::number(rect.x()) + ",\"y\":" + QString::number(rect.y()) + ",\"width\":" + QString::number(rect.width()) + ",\"height\":" + QString::number(rect.height()) + "}";
v = "{\"left\":" + QString::number(rect.left()) + ",\"top\":" + QString::number(rect.top()) + ",\"right\":" + QString::number(rect.right()) + ",\"bottom\":" + QString::number(rect.bottom()) + "}";
}
else if (value.canConvert<QSize>())
{
Expand Down Expand Up @@ -311,66 +311,128 @@ class QtInvoker : public RemoteEntity
const std::string* methodName = requestContext->getMetainfo("PATH_method");
if (objId && methodName)
{
ZeroCopyBuffer buffer;
SerializerQt serializerQt(buffer, SerializerQt::Mode::WRAPPED_BY_QVARIANTLIST);
ParserProto parserProto(serializerQt, request->data.data(), request->data.size());
parserProto.parseStruct(request->type);

QByteArray bufferByteArray;
bufferByteArray.reserve(static_cast<int>(buffer.size()));
const std::list<std::string>& chunks = buffer.chunks();
for (const auto& chunk : chunks)
QObject* obj;
QMetaMethod metaMethod;
QMetaProperty metaProperty;
bool propertySet = false;
const std::string& typeName = getTypeName(*objId, *methodName, obj, metaMethod, metaProperty, propertySet);
if ((obj != nullptr) && (typeName == request->type))
{
bufferByteArray.append(chunk.data(), static_cast<int>(chunk.size()));
}
if (metaMethod.isValid())
{
found = true;

QVariantList parameters;
QDataStream s(bufferByteArray);
s >> parameters;
ZeroCopyBuffer buffer;
SerializerQt serializerQt(buffer, SerializerQt::Mode::WRAPPED_BY_QVARIANTLIST);
ParserProto parserProto(serializerQt, request->data.data(), request->data.size());
parserProto.parseStruct(request->type);

std::array<QGenericArgument, 10> genericArguments;
for (int i = 0; i < parameters.length(); ++i)
{
const QVariant& parameter = parameters[i];
genericArguments[i] = QGenericArgument(parameter.typeName(), parameter.constData());
}
QByteArray bufferByteArray;
bufferByteArray.reserve(static_cast<int>(buffer.size()));
const std::list<std::string>& chunks = buffer.chunks();
for (const auto& chunk : chunks)
{
bufferByteArray.append(chunk.data(), static_cast<int>(chunk.size()));
}

QObject* obj;
QMetaMethod metaMethod;
const std::string& typeName = getTypeName(*objId, *methodName, obj, metaMethod);
if ((obj != nullptr) && metaMethod.isValid() && (typeName == request->type))
{
found = true;
QVariant returnValue(QMetaType::type(metaMethod.typeName()),
static_cast<void*>(NULL));

QGenericReturnArgument returnArgument(
metaMethod.typeName(),
const_cast<void*>(returnValue.constData())
);
metaMethod.invoke(obj, returnArgument,
genericArguments[0], genericArguments[1], genericArguments[2],
genericArguments[3], genericArguments[4], genericArguments[5],
genericArguments[6], genericArguments[7], genericArguments[8], genericArguments[9]);

QByteArray retQtBuffer;
QDataStream s(&retQtBuffer, QIODevice::WriteOnly);
s << returnValue;

std::string retTypeName = getReturnTypeName(metaMethod.typeName());

GeneralMessage replyMessage;
if (!retTypeName.empty())
QVariantList parameters;
QDataStream streamInParams(bufferByteArray);
streamInParams >> parameters;

std::array<QGenericArgument, 10> genericArguments;
for (int i = 0; i < parameters.length(); ++i)
{
const QVariant& parameter = parameters[i];
genericArguments[i] = QGenericArgument(parameter.typeName(), parameter.constData());
}

QVariant returnValue(QMetaType::type(metaMethod.typeName()),
static_cast<void*>(NULL));

QGenericReturnArgument returnArgument(
metaMethod.typeName(),
const_cast<void*>(returnValue.constData())
);
metaMethod.invoke(obj, returnArgument,
genericArguments[0], genericArguments[1], genericArguments[2],
genericArguments[3], genericArguments[4], genericArguments[5],
genericArguments[6], genericArguments[7], genericArguments[8], genericArguments[9]);

QByteArray retQtBuffer;
QDataStream streamRetParam(&retQtBuffer, QIODevice::WriteOnly);
streamRetParam << returnValue;

std::string retTypeName = getReturnTypeName(metaMethod.typeName());

GeneralMessage replyMessage;
if (!retTypeName.empty())
{
ZeroCopyBuffer bufferRet;
SerializerProto serializerProto(bufferRet);
ParserQt parserQt(serializerProto, retQtBuffer.data(), retQtBuffer.size(), ParserQt::Mode::WRAPPED_BY_QVARIANT);
parserQt.parseStruct(retTypeName);

replyMessage.type = retTypeName;
bufferRet.copyData(replyMessage.data);
}
requestContext->reply(replyMessage);
}
else if (metaProperty.isValid())
{
ZeroCopyBuffer bufferRet;
SerializerProto serializerProto(bufferRet);
ParserQt parserQt(serializerProto, retQtBuffer.data(), retQtBuffer.size(), ParserQt::Mode::WRAPPED_BY_QVARIANT);
parserQt.parseStruct(retTypeName);
found = true;
if (propertySet)
{
ZeroCopyBuffer buffer;
SerializerQt serializerQt(buffer, SerializerQt::Mode::WRAPPED_BY_QVARIANT);
ParserProto parserProto(serializerQt, request->data.data(), request->data.size());
parserProto.parseStruct(request->type);

QByteArray bufferByteArray;
bufferByteArray.reserve(static_cast<int>(buffer.size()));
const std::list<std::string>& chunks = buffer.chunks();
for (const auto& chunk : chunks)
{
bufferByteArray.append(chunk.data(), static_cast<int>(chunk.size()));
}

replyMessage.type = retTypeName;
bufferRet.copyData(replyMessage.data);
QVariant value;
QDataStream streamInParam(bufferByteArray);
streamInParam >> value;

const bool result = metaProperty.write(obj, value);
if (result)
{
GeneralMessage replyMessage;
requestContext->reply(replyMessage);
}
else
{
requestContext->reply(finalmq::Status::STATUS_REQUEST_PROCESSING_ERROR);
}
}
else
{
QVariant value = metaProperty.read(obj);

QByteArray retQtBuffer;
QDataStream streamRetParam(&retQtBuffer, QIODevice::WriteOnly);
streamRetParam << value;

std::string retTypeName = getReturnTypeName(metaProperty.typeName());

GeneralMessage replyMessage;

ZeroCopyBuffer bufferRet;
SerializerProto serializerProto(bufferRet);
ParserQt parserQt(serializerProto, retQtBuffer.data(), retQtBuffer.size(), ParserQt::Mode::WRAPPED_BY_QVARIANT);
parserQt.parseStruct(retTypeName);

replyMessage.type = retTypeName;
bufferRet.copyData(replyMessage.data);

requestContext->reply(replyMessage);
}
}
requestContext->reply(replyMessage);
}
}
if (!found)
Expand Down Expand Up @@ -491,20 +553,22 @@ class QtInvoker : public RemoteEntity
{
QObject* obj;
QMetaMethod metaMethod;
return getTypeName(objId, methodName, obj, metaMethod);
QMetaProperty metaProperty;
bool propertySet = false;
return getTypeName(objId, methodName, obj, metaMethod, metaProperty, propertySet);
}

std::string getReturnTypeName(const std::string& type)
{
std::string typeName = "ret_" + type;
std::string typeName = type + "_v";
const MetaStruct* struFound = MetaDataGlobal::instance().getStruct(typeName);
if (struFound == nullptr)
{
MetaStruct stru{ typeName, "", {}, 0, {} };
const auto it = m_typesToField.find(type);
if (it != m_typesToField.end())
{
static const std::string& name = "ret";
static const std::string& name = "v";
const MetaField& field = it->second;
stru.addField(MetaField(field.typeId, field.typeName, name, field.description, field.flags, field.attrs));
MetaDataGlobal::instance().addStruct(stru);
Expand All @@ -517,14 +581,14 @@ class QtInvoker : public RemoteEntity
return typeName;
}

std::string getTypeName(const std::string& objId, const std::string& methodName, QObject*& obj, QMetaMethod& metaMethod)
std::string getTypeName(const std::string& objId, const std::string& methodName, QObject*& obj, QMetaMethod& metaMethod, QMetaProperty& metaProperty, bool& propertySet)
{
propertySet = false;
std::string typeOfGeneralMessage{};
obj = findObject(QString::fromUtf8(objId.c_str()));
if (obj)
{
const QMetaObject* metaObject = obj->metaObject();
QMetaProperty metaProperty;
if (metaObject)
{
int ix = metaObject->indexOfMethod(methodName.c_str());
Expand All @@ -544,7 +608,15 @@ class QtInvoker : public RemoteEntity

if (!metaMethod.isValid())
{
ix = metaObject->indexOfProperty(methodName.c_str());
if (methodName.substr(0, 4) == "set_")
{
propertySet = true;
ix = metaObject->indexOfProperty(methodName.substr(4).c_str());
}
else
{
ix = metaObject->indexOfProperty(methodName.c_str());
}
if (ix != -1)
{
metaProperty = metaObject->property(ix);
Expand Down Expand Up @@ -627,6 +699,44 @@ class QtInvoker : public RemoteEntity
}
}
}
else if (metaProperty.isValid())
{
std::string typeName = metaProperty.typeName();
typeName += "_v";

// no parameters?
if (!propertySet)
{
typeName = '_';
}

bool ok = true;
const MetaStruct* struFound = MetaDataGlobal::instance().getStruct(typeName);
if (struFound == nullptr)
{
MetaStruct stru{ typeName, "", {}, 0, {} };
const std::string& type = metaProperty.typeName();
const auto it = m_typesToField.find(type);
if (it != m_typesToField.end())
{
static const std::string name = "v";
const MetaField& field = it->second;
stru.addField(MetaField(field.typeId, field.typeName, name, field.description, field.flags, field.attrs));
}
else
{
ok = false;
}
if (ok)
{
MetaDataGlobal::instance().addStruct(stru);
}
}
if (ok)
{
typeOfGeneralMessage = typeName;
}
}
}
}
return typeOfGeneralMessage;
Expand Down
8 changes: 4 additions & 4 deletions inc/finalmq/Qt/qtdata.fmq
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@
{"tid":"int32", "type":"","name":"height","desc":"","flags":[]}
]},
{"type":"FmqQRect","attrs":["qttype:QRect"],"desc":"","fields":[
{"tid":"int32", "type":"","name":"x","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"y","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"width","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"height","desc":"","flags":[]}
{"tid":"int32", "type":"","name":"left","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"top","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"right","desc":"","flags":[]},
{"tid":"int32", "type":"","name":"bottom","desc":"","flags":[]}
]},
{"type":"FmqQColor","attrs":["qttype:QColor"],"desc":"","fields":[
{"tid":"enum", "type":"FmqQColorSpec","name":"cspec","desc":"","flags":[]},
Expand Down

0 comments on commit cb9ae04

Please sign in to comment.