Refactoring and bug fixing
This commit is contained in:
parent
e5457adc85
commit
23f795298d
|
@ -8,6 +8,7 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QMetaMethod>
|
||||
// DOtherSide
|
||||
#include "DOtherSide/DOtherSideTypesCpp.h"
|
||||
|
||||
|
@ -20,9 +21,10 @@ class IDosQMetaObject
|
|||
public:
|
||||
virtual ~IDosQMetaObject() = default;
|
||||
virtual const QMetaObject* metaObject() const = 0;
|
||||
virtual int signalSlotIndex(const QString& signalName) const = 0;
|
||||
virtual int readSlotIndex(const char* propertyName) const = 0;
|
||||
virtual int writeSlotIndex(const char* propertyName) const = 0;
|
||||
virtual QMetaMethod signal(const QString& signalName) const = 0;
|
||||
virtual QMetaMethod readSlot(const char* propertyName) const = 0;
|
||||
virtual QMetaMethod writeSlot(const char* propertyName) const = 0;
|
||||
virtual const IDosQMetaObject* superClassDosMetaObject() const = 0;
|
||||
};
|
||||
|
||||
/// Base class for any IDosQMetaObject
|
||||
|
@ -33,9 +35,10 @@ public:
|
|||
: m_metaObject(metaObject)
|
||||
{}
|
||||
const QMetaObject *metaObject() const override { return m_metaObject; }
|
||||
int signalSlotIndex(const QString &signalName) const override { return -1; }
|
||||
int readSlotIndex(const char *propertyName) const override { return -1; }
|
||||
int writeSlotIndex(const char *propertyName) const override { return -1; }
|
||||
QMetaMethod signal(const QString &signalName) const override { return QMetaMethod(); }
|
||||
QMetaMethod readSlot(const char *propertyName) const override { return QMetaMethod(); }
|
||||
QMetaMethod writeSlot(const char *propertyName) const override { return QMetaMethod(); }
|
||||
const IDosQMetaObject* superClassDosMetaObject() const { return nullptr; }
|
||||
|
||||
private:
|
||||
SafeQMetaObjectPtr m_metaObject;
|
||||
|
@ -59,27 +62,28 @@ public:
|
|||
class DosQMetaObject : public IDosQMetaObject
|
||||
{
|
||||
public:
|
||||
DosQMetaObject(const IDosQMetaObject& superClassMetaObject,
|
||||
DosQMetaObject(std::shared_ptr<const IDosQMetaObject> superClassDosMetaObject,
|
||||
const QString& className,
|
||||
const SignalDefinitions &signalDefinitions,
|
||||
const SlotDefinitions &slotDefinitions,
|
||||
const PropertyDefinitions &propertyDefinitions);
|
||||
|
||||
int signalSlotIndex(const QString& signalName) const override;
|
||||
int readSlotIndex(const char* propertyName) const override;
|
||||
int writeSlotIndex(const char* propertyName) const override;
|
||||
QMetaMethod signal(const QString& signalName) const override;
|
||||
QMetaMethod readSlot(const char* propertyName) const override;
|
||||
QMetaMethod writeSlot(const char* propertyName) const override;
|
||||
const QMetaObject *metaObject() const override;
|
||||
const IDosQMetaObject *superClassDosMetaObject() const override;
|
||||
|
||||
private:
|
||||
QMetaObject *createMetaObject(const IDosQMetaObject &superClassMetaObject,
|
||||
const QString& className,
|
||||
QMetaObject *createMetaObject(const QString& className,
|
||||
const SignalDefinitions &signalDefinitions,
|
||||
const SlotDefinitions &slotDefinitions,
|
||||
const PropertyDefinitions &propertyDefinitions);
|
||||
|
||||
std::shared_ptr<const IDosQMetaObject> m_superClassDosMetaObject;
|
||||
QHash<QString, int> m_signalIndexByName;
|
||||
QHash<QString, QPair<int,int>> m_propertySlots;
|
||||
SafeQMetaObjectPtr m_metaObject;
|
||||
std::unordered_map<std::string, int> m_signalIndexByName;
|
||||
std::unordered_map<std::string, std::pair<int,int>> m_propertySlots;
|
||||
};
|
||||
|
||||
/// This class simply holds a ptr to a IDosQMetaObject
|
||||
|
|
|
@ -24,7 +24,8 @@ public:
|
|||
int qt_metacall(QMetaObject::Call callType, int index, void**args) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const DOS::IDosQMetaObject> factory() const;
|
||||
std::shared_ptr<const DOS::IDosQMetaObject> dosMetaObject() const;
|
||||
bool executeSlot(const QMetaMethod& method, void** args);
|
||||
bool executeSlot(int index, void** args);
|
||||
bool readProperty(int index, void** args);
|
||||
bool writeProperty(int index, void** args);
|
||||
|
|
|
@ -542,7 +542,7 @@ void dos_qmetaobject_create(void **vptr,
|
|||
auto data = superClassHolder->data();
|
||||
Q_ASSERT(data);
|
||||
|
||||
auto metaObject = std::make_shared<DosQMetaObject>(*data,
|
||||
auto metaObject = std::make_shared<DosQMetaObject>(data,
|
||||
QString::fromUtf8(className),
|
||||
toVector(signalDefinitions),
|
||||
toVector(slotDefinitions),
|
||||
|
|
|
@ -33,7 +33,7 @@ Value valueOrDefault(std::unordered_map<Key,Value> const& map, const Key& k, Val
|
|||
QMetaObject* createDynamicQObjectMetaObject()
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setClassName("DynamicQObject");
|
||||
builder.setClassName("DosQObject");
|
||||
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
builder.setSuperClass(&QObject::staticMetaObject);
|
||||
return builder.toMetaObject();
|
||||
|
@ -43,7 +43,7 @@ QMetaObject* createDynamicQAbstractListModelMetaObject()
|
|||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
builder.setClassName("DynamicQAbstractListModel");
|
||||
builder.setClassName("DosQAbstractListModel");
|
||||
builder.setSuperClass(&QAbstractListModel::staticMetaObject);
|
||||
return builder.toMetaObject();
|
||||
}
|
||||
|
@ -61,18 +61,17 @@ DosQAbstractListModelMetaObject::DosQAbstractListModelMetaObject()
|
|||
: BaseDosQMetaObject(::createDynamicQAbstractListModelMetaObject())
|
||||
{}
|
||||
|
||||
DosQMetaObject::DosQMetaObject(const IDosQMetaObject &superClassMetaObject,
|
||||
DosQMetaObject::DosQMetaObject(std::shared_ptr<const IDosQMetaObject> superClassMetaObject,
|
||||
const QString &className,
|
||||
const SignalDefinitions& signalDefinitions,
|
||||
const SlotDefinitions& slotDefinitions,
|
||||
const PropertyDefinitions& propertyDefinitions)
|
||||
: m_metaObject(nullptr)
|
||||
: m_superClassDosMetaObject(std::move(superClassMetaObject))
|
||||
, m_metaObject(createMetaObject(className, signalDefinitions, slotDefinitions, propertyDefinitions))
|
||||
{
|
||||
m_metaObject.reset(createMetaObject(superClassMetaObject, className, signalDefinitions, slotDefinitions, propertyDefinitions));
|
||||
}
|
||||
|
||||
QMetaObject *DosQMetaObject::createMetaObject(const IDosQMetaObject &superClassMetaObject,
|
||||
const QString &className,
|
||||
QMetaObject *DosQMetaObject::createMetaObject(const QString &className,
|
||||
const SignalDefinitions& signalDefinitions,
|
||||
const SlotDefinitions& slotDefinitions,
|
||||
const PropertyDefinitions& propertyDefinitions)
|
||||
|
@ -80,53 +79,68 @@ QMetaObject *DosQMetaObject::createMetaObject(const IDosQMetaObject &superClassM
|
|||
QMetaObjectBuilder builder;
|
||||
builder.setClassName(className.toUtf8());
|
||||
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
builder.setSuperClass(superClassMetaObject.metaObject());
|
||||
builder.setSuperClass(m_superClassDosMetaObject->metaObject());
|
||||
|
||||
for (const SignalDefinition& signal : signalDefinitions)
|
||||
{
|
||||
QMetaMethodBuilder signalBuilder = builder.addSignal(::createSignature(signal));
|
||||
signalBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
|
||||
signalBuilder.setAccess(QMetaMethod::Public);
|
||||
m_signalIndexByName[signal.name.toStdString()] = signalBuilder.index();
|
||||
m_signalIndexByName[signal.name] = signalBuilder.index();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, int> methodIndexByName;
|
||||
QHash<QString, int> methodIndexByName;
|
||||
for (const SlotDefinition& slot : slotDefinitions)
|
||||
{
|
||||
QMetaMethodBuilder methodBuilder = builder.addSlot(::createSignature(slot));
|
||||
methodBuilder.setReturnType(QMetaType::typeName(slot.returnType));
|
||||
methodBuilder.setAttributes(QMetaMethod::Scriptable);
|
||||
methodIndexByName[slot.name.toStdString()] = methodBuilder.index();
|
||||
methodIndexByName[slot.name] = methodBuilder.index();
|
||||
}
|
||||
|
||||
for (const PropertyDefinition& property : propertyDefinitions)
|
||||
{
|
||||
const int notifier = ::valueOrDefault(m_signalIndexByName, property.notifySignal.toStdString(), -1);
|
||||
const int notifier = m_signalIndexByName.value(property.notifySignal, -1);
|
||||
const QByteArray name = property.name.toUtf8();
|
||||
const QByteArray typeName = QMetaObject::normalizedType(QMetaType::typeName(property.type));
|
||||
QMetaPropertyBuilder propertyBuilder = builder.addProperty(name, typeName, notifier);
|
||||
if (notifier == -1)
|
||||
propertyBuilder.setConstant(true);
|
||||
m_propertySlots[propertyBuilder.name().toStdString()] = std::make_pair(::valueOrDefault(methodIndexByName, property.readSlot.toStdString(), -1),
|
||||
::valueOrDefault(methodIndexByName, property.writeSlot.toStdString(), -1));
|
||||
m_propertySlots[property.name] = qMakePair(methodIndexByName.value(property.readSlot, -1),
|
||||
methodIndexByName.value(property.writeSlot, -1));
|
||||
}
|
||||
|
||||
return builder.toMetaObject();
|
||||
}
|
||||
|
||||
int DosQMetaObject::signalSlotIndex(const QString &signalName) const
|
||||
{
|
||||
return metaObject()->methodOffset() + ::valueOrDefault(m_signalIndexByName, signalName.toStdString(), -1);
|
||||
QMetaMethod DosQMetaObject::signal(const QString &signalName) const
|
||||
{
|
||||
const int index = m_signalIndexByName.value(signalName, -1);
|
||||
if (index != -1)
|
||||
return metaObject()->method(metaObject()->methodOffset() + index);
|
||||
if (auto superMetaObject = superClassDosMetaObject())
|
||||
return superMetaObject->signal(signalName);
|
||||
return QMetaMethod();
|
||||
}
|
||||
|
||||
int DosQMetaObject::readSlotIndex(const char *propertyName) const
|
||||
QMetaMethod DosQMetaObject::readSlot(const char *propertyName) const
|
||||
{
|
||||
return metaObject()->methodOffset() + ::valueOrDefault(m_propertySlots, std::string(propertyName), std::make_pair(-1,-1)).first;
|
||||
const auto index = m_propertySlots.value(QString::fromUtf8(propertyName), qMakePair(-1,-1)).first;
|
||||
if (index != -1)
|
||||
return metaObject()->method(metaObject()->methodOffset() + index);
|
||||
if (auto superMetaObject = superClassDosMetaObject())
|
||||
return superMetaObject->readSlot(propertyName);
|
||||
return QMetaMethod();
|
||||
}
|
||||
|
||||
int DosQMetaObject::writeSlotIndex(const char *propertyName) const
|
||||
QMetaMethod DosQMetaObject::writeSlot(const char *propertyName) const
|
||||
{
|
||||
return metaObject()->methodOffset() + valueOrDefault(m_propertySlots, std::string(propertyName), std::make_pair(-1,-1)).second;
|
||||
const auto index = m_propertySlots.value(QString::fromUtf8(propertyName), qMakePair(-1,-1)).second;
|
||||
if (index != -1)
|
||||
return metaObject()->method(metaObject()->methodOffset() + index);
|
||||
if (auto superMetaObject = superClassDosMetaObject())
|
||||
return superMetaObject->writeSlot(propertyName);
|
||||
return QMetaMethod();
|
||||
}
|
||||
|
||||
const QMetaObject *DosQMetaObject::metaObject() const
|
||||
|
@ -134,4 +148,9 @@ const QMetaObject *DosQMetaObject::metaObject() const
|
|||
return m_metaObject;
|
||||
}
|
||||
|
||||
const IDosQMetaObject *DosQMetaObject::superClassDosMetaObject() const
|
||||
{
|
||||
return m_superClassDosMetaObject.get();
|
||||
}
|
||||
|
||||
} // namespace DOS
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "DOtherSide/DosQMetaObject.h"
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QMetaMethod>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
namespace DOS
|
||||
{
|
||||
|
@ -17,23 +18,23 @@ DynamicQObjectImpl::DynamicQObjectImpl(QObject* parent,
|
|||
|
||||
bool DynamicQObjectImpl::emitSignal(const QString &name, const std::vector<QVariant> &args)
|
||||
{
|
||||
const int index = factory()->signalSlotIndex(name);
|
||||
const QMetaMethod method = metaObject()->method(index);
|
||||
const QMetaMethod method = dosMetaObject()->signal(name);
|
||||
if (!method.isValid())
|
||||
return false;
|
||||
|
||||
Q_ASSERT(name.toUtf8() == method.name());
|
||||
|
||||
std::vector<void*> arguments(args.size() + 1, nullptr);
|
||||
arguments.front() = nullptr;
|
||||
auto func = [](const QVariant& arg) -> void* { return (void*)(&arg); };
|
||||
std::transform(args.begin(), args.end(), arguments.begin() + 1, func);
|
||||
QMetaObject::activate(m_parent, index, arguments.data());
|
||||
QMetaObject::activate(m_parent, method.methodIndex(), arguments.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
const QMetaObject *DynamicQObjectImpl::metaObject() const
|
||||
{
|
||||
return factory()->metaObject();
|
||||
return dosMetaObject()->metaObject();
|
||||
}
|
||||
|
||||
int DynamicQObjectImpl::qt_metacall(QMetaObject::Call callType, int index, void **args)
|
||||
|
@ -55,7 +56,7 @@ int DynamicQObjectImpl::qt_metacall(QMetaObject::Call callType, int index, void
|
|||
return -1;
|
||||
}
|
||||
|
||||
std::shared_ptr<const IDosQMetaObject> DynamicQObjectImpl::factory() const
|
||||
std::shared_ptr<const IDosQMetaObject> DynamicQObjectImpl::dosMetaObject() const
|
||||
{
|
||||
static std::shared_ptr<const IDosQMetaObject> result = m_onMetaObject()->data();
|
||||
return result;
|
||||
|
@ -64,8 +65,16 @@ std::shared_ptr<const IDosQMetaObject> DynamicQObjectImpl::factory() const
|
|||
bool DynamicQObjectImpl::executeSlot(int index, void **args)
|
||||
{
|
||||
const QMetaMethod method = metaObject()->method(index);
|
||||
if (!method.isValid())
|
||||
if (!method.isValid()) {
|
||||
qDebug() << "C++: executeSlot: invalid method";
|
||||
return false;
|
||||
}
|
||||
executeSlot(method, args);
|
||||
}
|
||||
|
||||
bool DynamicQObjectImpl::executeSlot(const QMetaMethod &method, void **args)
|
||||
{
|
||||
Q_ASSERT(method.isValid());
|
||||
|
||||
const bool hasReturnType = method.returnType() != QMetaType::Void;
|
||||
|
||||
|
@ -90,7 +99,12 @@ bool DynamicQObjectImpl::readProperty(int index, void **args)
|
|||
const QMetaProperty property = metaObject()->property(index);
|
||||
if (!property.isValid() || !property.isReadable())
|
||||
return false;
|
||||
return executeSlot(factory()->readSlotIndex(property.name()), args);
|
||||
QMetaMethod method = dosMetaObject()->readSlot(property.name());
|
||||
if (!method.isValid()) {
|
||||
qDebug() << "C++: readProperty: invalid read method for property " << property.name();
|
||||
return false;
|
||||
}
|
||||
return executeSlot(method, args);
|
||||
}
|
||||
|
||||
bool DynamicQObjectImpl::writeProperty(int index, void **args)
|
||||
|
@ -98,7 +112,12 @@ bool DynamicQObjectImpl::writeProperty(int index, void **args)
|
|||
const QMetaProperty property = metaObject()->property(index);
|
||||
if (!property.isValid() || !property.isWritable())
|
||||
return false;
|
||||
return executeSlot(factory()->writeSlotIndex(property.name()), args);
|
||||
QMetaMethod method = dosMetaObject()->writeSlot(property.name());
|
||||
if (!method.isValid()) {
|
||||
qDebug() << "C++: writeProperty: invalid write method for property " << property.name();
|
||||
return false;
|
||||
}
|
||||
return executeSlot(method, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue