Merge branch 'feature/DynamicQObjectAsPolicy' into feature/QAbstractItemModels
This commit is contained in:
commit
6e6e0c1a57
|
@ -1,3 +1,3 @@
|
|||
add_subdirectory(DOtherSide)
|
||||
add_subdirectory(DynamicQObject)
|
||||
add_subdirectory(IntegrationTest)
|
||||
#add_subdirectory(DynamicQObject)
|
||||
#add_subdirectory(IntegrationTest)
|
|
@ -1,82 +0,0 @@
|
|||
#include "BaseQAbstractListModel.h"
|
||||
|
||||
BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject,
|
||||
RowCountCallback rowCountCallback,
|
||||
DataCallback dataCallback,
|
||||
RoleNamesCallback roleNamesCallback)
|
||||
: m_modelObject(modelObject)
|
||||
, m_rowCountCallback(rowCountCallback)
|
||||
, m_dataCallback(dataCallback)
|
||||
, m_roleNamesCallback(roleNamesCallback)
|
||||
{
|
||||
}
|
||||
|
||||
int BaseQAbstractListModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
auto newIndex = new QModelIndex();
|
||||
*newIndex = index;
|
||||
int result;
|
||||
m_rowCountCallback(m_modelObject, newIndex, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
auto newIndex = new QModelIndex();
|
||||
*newIndex = index;
|
||||
QVariant result;
|
||||
m_dataCallback(m_modelObject, newIndex, role, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void* BaseQAbstractListModel::modelObject()
|
||||
{
|
||||
return m_modelObject;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> BaseQAbstractListModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> result;
|
||||
m_roleNamesCallback(m_modelObject, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginInsertRows(const QModelIndex& index, int first, int last)
|
||||
{
|
||||
beginInsertRows(index, first, last);
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndInsertRows()
|
||||
{
|
||||
return endInsertRows();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginRemoveRows(const QModelIndex& index, int first, int last)
|
||||
{
|
||||
beginRemoveRows(index, first, last);
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndRemoveRows()
|
||||
{
|
||||
return endRemoveRows();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginResetModel()
|
||||
{
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndResetModel()
|
||||
{
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicDataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles)
|
||||
{
|
||||
emit dataChanged(topLeft, bottomRight, roles);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
#ifndef BASEQABSTRACTLISTMODEL_H
|
||||
#define BASEQABSTRACTLISTMODEL_H
|
||||
|
||||
#include "DOtherSideTypes.h"
|
||||
#include "DynamicQObject.h"
|
||||
#include <QAbstractListModel>
|
||||
|
||||
/// This class act as a base class for D and Nim QAbstractListModel
|
||||
class BaseQAbstractListModel : public QAbstractListModel
|
||||
class BaseQAbstractListModel : public DynamicQObject<QAbstractListModel>
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
|
@ -27,30 +29,110 @@ public:
|
|||
|
||||
/// Expose beginInsertRows
|
||||
void publicBeginInsertRows(const QModelIndex& index, int first, int last);
|
||||
|
||||
|
||||
/// Expose endInsertRows
|
||||
void publicEndInsertRows();
|
||||
|
||||
|
||||
/// Expose beginRemoveRows
|
||||
void publicBeginRemoveRows(const QModelIndex& index, int first, int last);
|
||||
|
||||
|
||||
/// Expose endInsertRows
|
||||
void publicEndRemoveRows();
|
||||
|
||||
|
||||
/// Expose beginResetModel
|
||||
void publicBeginResetModel();
|
||||
|
||||
|
||||
/// Expose endResetModel
|
||||
void publicEndResetModel();
|
||||
|
||||
|
||||
/// Expose dataChanged
|
||||
void publicDataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
void publicDataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles = QVector<int>());
|
||||
|
||||
|
||||
private:
|
||||
void* m_modelObject;
|
||||
RowCountCallback m_rowCountCallback;
|
||||
DataCallback m_dataCallback;
|
||||
RoleNamesCallback m_roleNamesCallback;
|
||||
};
|
||||
|
||||
BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject,
|
||||
RowCountCallback rowCountCallback,
|
||||
DataCallback dataCallback,
|
||||
RoleNamesCallback roleNamesCallback)
|
||||
: m_modelObject(modelObject)
|
||||
, m_rowCountCallback(rowCountCallback)
|
||||
, m_dataCallback(dataCallback)
|
||||
, m_roleNamesCallback(roleNamesCallback)
|
||||
{
|
||||
}
|
||||
|
||||
int BaseQAbstractListModel::rowCount(const QModelIndex& index) const
|
||||
{
|
||||
auto newIndex = new QModelIndex();
|
||||
*newIndex = index;
|
||||
int result;
|
||||
m_rowCountCallback(m_modelObject, newIndex, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
auto newIndex = new QModelIndex();
|
||||
*newIndex = index;
|
||||
QVariant result;
|
||||
m_dataCallback(m_modelObject, newIndex, role, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void* BaseQAbstractListModel::modelObject()
|
||||
{
|
||||
return m_modelObject;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> BaseQAbstractListModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> result;
|
||||
m_roleNamesCallback(m_modelObject, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginInsertRows(const QModelIndex& index, int first, int last)
|
||||
{
|
||||
beginInsertRows(index, first, last);
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndInsertRows()
|
||||
{
|
||||
return endInsertRows();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginRemoveRows(const QModelIndex& index, int first, int last)
|
||||
{
|
||||
beginRemoveRows(index, first, last);
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndRemoveRows()
|
||||
{
|
||||
return endRemoveRows();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicBeginResetModel()
|
||||
{
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicEndResetModel()
|
||||
{
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void BaseQAbstractListModel::publicDataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles)
|
||||
{
|
||||
emit dataChanged(topLeft, bottomRight, roles);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BASEQOBJECT_H
|
||||
#define BASEQOBJECT_H
|
||||
|
||||
#include "DynamicQObject.h"
|
||||
|
||||
class BaseQObject : public DynamicQObject<QObject> {};
|
||||
|
||||
#endif
|
|
@ -12,14 +12,15 @@ find_package(Qt5Widgets)
|
|||
|
||||
set(HEADERS_LIST
|
||||
DOtherSide.h
|
||||
DOtherSideTypes.h
|
||||
BaseQAbstractListModel.h
|
||||
BaseQObject.h
|
||||
)
|
||||
|
||||
set(SRC_LIST
|
||||
DOtherSide.cpp
|
||||
BaseQAbstractListModel.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_LIST} ${HEADERS_LIST})
|
||||
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick DynamicQObject)
|
||||
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../DynamicQObject)
|
|
@ -1,5 +1,7 @@
|
|||
#include "DOtherSide.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QModelIndex>
|
||||
|
@ -8,10 +10,10 @@
|
|||
#include <QtQml/QQmlApplicationEngine>
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <iostream>
|
||||
|
||||
#include "DynamicQObject.h"
|
||||
#include "BaseQAbstractListModel.h"
|
||||
#include "BaseQObject.h"
|
||||
|
||||
void convert_to_cstring(const QString& source, char** destination, int* length)
|
||||
{
|
||||
|
@ -307,7 +309,7 @@ void dos_qvariant_setQAbstractListModel(void* vptr, void* value)
|
|||
|
||||
void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback)
|
||||
{
|
||||
auto dynamicQObject = new DynamicQObject();
|
||||
auto dynamicQObject = new BaseQObject();
|
||||
QQmlEngine::setObjectOwnership(dynamicQObject, QQmlEngine::CppOwnership);
|
||||
dynamicQObject->setDObjectPointer(dObjectPointer);
|
||||
dynamicQObject->setDObjectCallback(dObjectCallback);
|
||||
|
@ -316,7 +318,7 @@ void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObje
|
|||
|
||||
void dos_qobject_delete(void* vptr)
|
||||
{
|
||||
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
|
||||
auto dynamicQObject = reinterpret_cast<BaseQObject*>(vptr);
|
||||
dynamicQObject->disconnect();
|
||||
delete dynamicQObject;
|
||||
}
|
||||
|
@ -326,7 +328,8 @@ void dos_qobject_slot_create(void* vptr, const char* name, int parametersCount,
|
|||
if (parametersCount <= 0)
|
||||
return;
|
||||
|
||||
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
|
||||
auto qobject = reinterpret_cast<QObject*>(vptr);
|
||||
auto dynamicQObject = dynamic_cast<IDynamicQObject*>(qobject);
|
||||
|
||||
QMetaType::Type returnType = static_cast<QMetaType::Type>(parametersMetaTypes[0]);
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
|
@ -341,7 +344,8 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount
|
|||
if (parametersCount <= 0)
|
||||
return;
|
||||
|
||||
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
|
||||
auto qobject = reinterpret_cast<QObject*>(vptr);
|
||||
auto dynamicQObject = dynamic_cast<IDynamicQObject*>(qobject);
|
||||
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
for (int i = 0; i < parametersCount; ++i)
|
||||
|
@ -352,10 +356,13 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount
|
|||
|
||||
void dos_qobject_signal_emit(void* vptr, const char* name, int parametersCount, void** parameters)
|
||||
{
|
||||
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
|
||||
auto qobject = reinterpret_cast<QObject*>(vptr);
|
||||
auto dynamicQObject = dynamic_cast<IDynamicQObject*>(qobject);
|
||||
|
||||
QVariantList arguments;
|
||||
for (int i = 0; i < parametersCount; ++i)
|
||||
arguments << *(reinterpret_cast<QVariant*>(parameters[i]));
|
||||
|
||||
dynamicQObject->emitSignal(QString::fromStdString(name), arguments);
|
||||
}
|
||||
|
||||
|
@ -366,7 +373,8 @@ void dos_qobject_property_create(void* vptr,
|
|||
const char* writeSlot,
|
||||
const char* notifySignal)
|
||||
{
|
||||
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
|
||||
auto qobject = reinterpret_cast<QObject*>(vptr);
|
||||
auto dynamicQObject = dynamic_cast<IDynamicQObject*>(qobject);
|
||||
dynamicQObject->registerProperty(QString(name),
|
||||
QMetaType::Type(type),
|
||||
QString(readSlot),
|
||||
|
@ -434,6 +442,7 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling)
|
|||
|
||||
void dos_qabstractlistmodel_create(void** vptr,
|
||||
void* modelObject,
|
||||
DObjectCallback dObjectCallback,
|
||||
RowCountCallback rowCountCallback,
|
||||
DataCallback dataCallback,
|
||||
RoleNamesCallback roleNamesCallaback)
|
||||
|
@ -442,6 +451,8 @@ void dos_qabstractlistmodel_create(void** vptr,
|
|||
rowCountCallback,
|
||||
dataCallback,
|
||||
roleNamesCallaback);
|
||||
model->setDObjectPointer(modelObject);
|
||||
model->setDObjectCallback(dObjectCallback);
|
||||
*vptr = model;
|
||||
}
|
||||
|
||||
|
@ -489,8 +500,8 @@ void dos_qabstractlistmodel_endResetModel(void* vptr)
|
|||
model->publicEndResetModel();
|
||||
}
|
||||
|
||||
void dos_qabstractlistmodel_dataChanged(void* vptr,
|
||||
QModelIndexVoidPtr topLeftIndex,
|
||||
void dos_qabstractlistmodel_dataChanged(void* vptr,
|
||||
QModelIndexVoidPtr topLeftIndex,
|
||||
QModelIndexVoidPtr bottomRightIndex,
|
||||
int* rolesArrayPtr,
|
||||
int rolesArrayLength)
|
||||
|
|
|
@ -122,22 +122,23 @@ void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, cha
|
|||
// QAbstractListModel
|
||||
void dos_qabstractlistmodel_create(void** vptr,
|
||||
void* callbackObject,
|
||||
DObjectCallback dObjectCallback,
|
||||
RowCountCallback rowCountCallback,
|
||||
DataCallback dataCallback,
|
||||
RoleNamesCallback roleNamesCallback);
|
||||
void dos_qabstractlistmodel_beginInsertRows(void* vptr,
|
||||
QModelIndexVoidPtr parentIndex,
|
||||
int first,
|
||||
int last);
|
||||
void dos_qabstractlistmodel_beginInsertRows(void* vptr,
|
||||
QModelIndexVoidPtr parentIndex,
|
||||
int first,
|
||||
int last);
|
||||
void dos_qabstractlistmodel_endInsertRows(void* vptr);
|
||||
void dos_qabstractlistmodel_beginRemoveRows(void* vptr,
|
||||
QModelIndexVoidPtr parentIndex,
|
||||
int first,
|
||||
int last);
|
||||
void dos_qabstractlistmodel_beginRemoveRows(void* vptr,
|
||||
QModelIndexVoidPtr parentIndex,
|
||||
int first,
|
||||
int last);
|
||||
void dos_qabstractlistmodel_endRemoveRows(void* vptr);
|
||||
void dos_qabstractlistmodel_beginResetModel(void* vptr);
|
||||
void dos_qabstractlistmodel_endResetModel(void* vptr);
|
||||
void dos_qabstractlistmodel_dataChanged(void* vptr,
|
||||
void dos_qabstractlistmodel_dataChanged(void* vptr,
|
||||
QModelIndexVoidPtr topLeftIndex,
|
||||
QModelIndexVoidPtr bottomRightIndex,
|
||||
int* rolesArrayPtr,
|
||||
|
|
|
@ -15,7 +15,6 @@ set(HEADERS_LIST
|
|||
|
||||
set(SRC_LIST
|
||||
DynamicProperty.cpp
|
||||
DynamicQObject.cpp
|
||||
DynamicSignal.cpp
|
||||
DynamicSlot.cpp
|
||||
)
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
#include "DynamicProperty.h"
|
||||
#include <QtCore/QString>
|
||||
|
||||
struct PropertyData
|
||||
{
|
||||
PropertyData(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName,
|
||||
const QString& notifySignalName)
|
||||
: name(name)
|
||||
, type(type)
|
||||
, readSlotName(readSlotName)
|
||||
, writeSlotName(writeSlotName)
|
||||
, notifySignalName(notifySignalName)
|
||||
{}
|
||||
|
||||
PropertyData(const PropertyData& other)
|
||||
: name(other.name)
|
||||
, type(other.type)
|
||||
, readSlotName(other.readSlotName)
|
||||
, writeSlotName(other.writeSlotName)
|
||||
, notifySignalName(other.notifySignalName)
|
||||
{}
|
||||
|
||||
PropertyData& operator=(const PropertyData& other)
|
||||
{
|
||||
name = other.name;
|
||||
type = other.type;
|
||||
readSlotName = other.readSlotName;
|
||||
writeSlotName = other.writeSlotName;
|
||||
notifySignalName = other.notifySignalName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString name;
|
||||
QMetaType::Type type;
|
||||
QString readSlotName;
|
||||
QString writeSlotName;
|
||||
QString notifySignalName;
|
||||
};
|
||||
|
||||
DynamicProperty::DynamicProperty()
|
||||
: d(nullptr)
|
||||
{}
|
||||
|
||||
DynamicProperty::DynamicProperty(const QString& name, QMetaType::Type type, const QString& readSlotName, const QString& writeSlotName, const QString& notifySignalName)
|
||||
: d(new PropertyData(name, type, readSlotName, writeSlotName, notifySignalName))
|
||||
{
|
||||
}
|
||||
|
||||
DynamicProperty::DynamicProperty(const DynamicProperty& other)
|
||||
: d(nullptr)
|
||||
{
|
||||
if (other.d)
|
||||
d.reset(new PropertyData(*other.d));
|
||||
}
|
||||
|
||||
DynamicProperty& DynamicProperty::operator=(const DynamicProperty& other)
|
||||
{
|
||||
if (!other.d && d)
|
||||
d.reset();
|
||||
else if (other.d && !d)
|
||||
d.reset(new PropertyData(*other.d));
|
||||
else if (other.d && d)
|
||||
*d = *other.d;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicProperty::~DynamicProperty()
|
||||
{}
|
||||
|
||||
QString DynamicProperty::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicProperty::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
bool DynamicProperty::isReadable() const
|
||||
{
|
||||
return !d->readSlotName.isEmpty();
|
||||
}
|
||||
|
||||
bool DynamicProperty::isWriteable() const
|
||||
{
|
||||
return !d->writeSlotName.isEmpty();
|
||||
}
|
||||
|
||||
bool DynamicProperty::hasNotifySignal() const
|
||||
{
|
||||
return !d->notifySignalName.isEmpty();
|
||||
}
|
||||
|
||||
QString DynamicProperty::readSlot() const
|
||||
{
|
||||
return d->readSlotName;
|
||||
}
|
||||
|
||||
QString DynamicProperty::writeSlot() const
|
||||
{
|
||||
return d->writeSlotName;
|
||||
}
|
||||
|
||||
QString DynamicProperty::notifySignal() const
|
||||
{
|
||||
return d->notifySignalName;
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
#ifndef DYNAMICPROPERTY_H
|
||||
#define DYNAMICPROPERTY_H
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <memory>
|
||||
|
||||
class QString;
|
||||
class PropertyData;
|
||||
|
||||
class DynamicProperty
|
||||
|
@ -38,3 +38,115 @@ public:
|
|||
private:
|
||||
std::unique_ptr<PropertyData> d;
|
||||
};
|
||||
|
||||
struct PropertyData
|
||||
{
|
||||
PropertyData(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName,
|
||||
const QString& notifySignalName)
|
||||
: name(name)
|
||||
, type(type)
|
||||
, readSlotName(readSlotName)
|
||||
, writeSlotName(writeSlotName)
|
||||
, notifySignalName(notifySignalName)
|
||||
{}
|
||||
|
||||
PropertyData(const PropertyData& other)
|
||||
: name(other.name)
|
||||
, type(other.type)
|
||||
, readSlotName(other.readSlotName)
|
||||
, writeSlotName(other.writeSlotName)
|
||||
, notifySignalName(other.notifySignalName)
|
||||
{}
|
||||
|
||||
PropertyData& operator=(const PropertyData& other)
|
||||
{
|
||||
name = other.name;
|
||||
type = other.type;
|
||||
readSlotName = other.readSlotName;
|
||||
writeSlotName = other.writeSlotName;
|
||||
notifySignalName = other.notifySignalName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString name;
|
||||
QMetaType::Type type;
|
||||
QString readSlotName;
|
||||
QString writeSlotName;
|
||||
QString notifySignalName;
|
||||
};
|
||||
|
||||
DynamicProperty::DynamicProperty()
|
||||
: d(nullptr)
|
||||
{}
|
||||
|
||||
DynamicProperty::DynamicProperty(const QString& name, QMetaType::Type type, const QString& readSlotName, const QString& writeSlotName, const QString& notifySignalName)
|
||||
: d(new PropertyData(name, type, readSlotName, writeSlotName, notifySignalName))
|
||||
{
|
||||
}
|
||||
|
||||
DynamicProperty::DynamicProperty(const DynamicProperty& other)
|
||||
: d(nullptr)
|
||||
{
|
||||
if (other.d)
|
||||
d.reset(new PropertyData(*other.d));
|
||||
}
|
||||
|
||||
DynamicProperty& DynamicProperty::operator=(const DynamicProperty& other)
|
||||
{
|
||||
if (!other.d && d)
|
||||
d.reset();
|
||||
else if (other.d && !d)
|
||||
d.reset(new PropertyData(*other.d));
|
||||
else if (other.d && d)
|
||||
*d = *other.d;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicProperty::~DynamicProperty()
|
||||
{}
|
||||
|
||||
QString DynamicProperty::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicProperty::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
bool DynamicProperty::isReadable() const
|
||||
{
|
||||
return !d->readSlotName.isEmpty();
|
||||
}
|
||||
|
||||
bool DynamicProperty::isWriteable() const
|
||||
{
|
||||
return !d->writeSlotName.isEmpty();
|
||||
}
|
||||
|
||||
bool DynamicProperty::hasNotifySignal() const
|
||||
{
|
||||
return !d->notifySignalName.isEmpty();
|
||||
}
|
||||
|
||||
QString DynamicProperty::readSlot() const
|
||||
{
|
||||
return d->readSlotName;
|
||||
}
|
||||
|
||||
QString DynamicProperty::writeSlot() const
|
||||
{
|
||||
return d->writeSlotName;
|
||||
}
|
||||
|
||||
QString DynamicProperty::notifySignal() const
|
||||
{
|
||||
return d->notifySignalName;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,347 +0,0 @@
|
|||
#include "DynamicQObject.h"
|
||||
#include <QDebug>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include "private/qmetaobjectbuilder_p.h"
|
||||
|
||||
DynamicQObject::DynamicQObject()
|
||||
: m_dObjectPointer(nullptr)
|
||||
, m_dObjectCallback(nullptr)
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
builder.setClassName("DynamicQObject");
|
||||
builder.setSuperClass(&QObject::staticMetaObject);
|
||||
m_metaObject.reset(builder.toMetaObject());
|
||||
}
|
||||
|
||||
DynamicQObject::~DynamicQObject() = default;
|
||||
|
||||
bool DynamicQObject::registerSlot(const QString& name,
|
||||
const QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& slotIndex)
|
||||
{
|
||||
DynamicSlot slot(name, returnType, argumentsTypes);
|
||||
|
||||
if (m_slotsBySignature.contains(slot.signature()))
|
||||
return false;
|
||||
|
||||
m_slotsByName.insertMulti(slot.name(), slot);
|
||||
m_slotsBySignature[slot.signature()] = slot;
|
||||
|
||||
auto afterSignalAdded = [](QMetaObjectBuilder&) {};
|
||||
auto afterPropertyAdded = afterSignalAdded;
|
||||
|
||||
auto afterSlotAdded = [&slot, returnType](QMetaObjectBuilder & metaObjectBuilder) {
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.addSlot(slot.signature());
|
||||
methodBuilder.setReturnType(QMetaType::typeName(returnType));
|
||||
methodBuilder.setAttributes(QMetaMethod::Scriptable);
|
||||
};
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data()
|
||||
, afterSignalAdded
|
||||
, afterSlotAdded
|
||||
, afterPropertyAdded);
|
||||
|
||||
m_metaObject.reset(newMetaObject);
|
||||
|
||||
slotIndex = m_metaObject->indexOfSlot(QMetaObject::normalizedSignature(slot.signature()));
|
||||
|
||||
return slotIndex != -1;
|
||||
}
|
||||
|
||||
bool DynamicQObject::registerSignal(const QString& name, const QList<QMetaType::Type>& arguments, int& signalIndex)
|
||||
{
|
||||
DynamicSignal signal(name, arguments);
|
||||
|
||||
if (m_signalsBySignature.contains(signal.signature()))
|
||||
return false;
|
||||
|
||||
m_signalsByName.insertMulti(signal.name(), signal);
|
||||
m_signalsBySignature[signal.signature()] = signal;
|
||||
|
||||
auto afterSignalAdded = [&signal](QMetaObjectBuilder & metaObjectBuilder) {
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.addSignal(signal.signature());
|
||||
methodBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
|
||||
methodBuilder.setAccess(QMetaMethod::Public);
|
||||
};
|
||||
|
||||
auto afterSlotAdded = [](QMetaObjectBuilder&) { };
|
||||
auto afterPropertyAdded = afterSlotAdded;
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data()
|
||||
, afterSignalAdded
|
||||
, afterSlotAdded
|
||||
, afterPropertyAdded);
|
||||
|
||||
m_metaObject.reset(newMetaObject);
|
||||
|
||||
signalIndex = m_metaObject->indexOfSignal(QMetaObject::normalizedSignature(signal.signature()));
|
||||
|
||||
return signalIndex != -1;
|
||||
}
|
||||
|
||||
bool DynamicQObject::registerProperty(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName,
|
||||
const QString& notifySignalName)
|
||||
{
|
||||
DynamicProperty property(name, type, readSlotName, writeSlotName, notifySignalName);
|
||||
|
||||
DynamicSignal notifySignal;
|
||||
|
||||
if (!notifySignalName.isEmpty())
|
||||
{
|
||||
notifySignal = m_signalsByName.value(notifySignalName, DynamicSignal());
|
||||
if (!notifySignal.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
m_propertiesByName.insert(name.toUtf8(), property);
|
||||
|
||||
auto afterSignalAdded = [](QMetaObjectBuilder & metaObjectBuilder) {};
|
||||
auto afterSlotAdded = [](QMetaObjectBuilder & metaObjectBuilder) {};
|
||||
auto afterPropertyAdded = [name, type, notifySignal](QMetaObjectBuilder & metaObjectBuilder)
|
||||
{
|
||||
int signalIndex = -1;
|
||||
if (notifySignal.isValid())
|
||||
{
|
||||
for (int i = 0; i < metaObjectBuilder.methodCount(); ++i)
|
||||
{
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.method(i);
|
||||
if (methodBuilder.methodType() == QMetaMethod::Signal)
|
||||
{
|
||||
if (methodBuilder.signature() == QMetaObject::normalizedSignature(notifySignal.signature()));
|
||||
{
|
||||
signalIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto typeName = QMetaType::typeName(type);
|
||||
auto builder = metaObjectBuilder.addProperty(name.toUtf8(),
|
||||
QMetaObject::normalizedType(typeName),
|
||||
signalIndex);
|
||||
if (signalIndex == -1)
|
||||
builder.setConstant(true);
|
||||
};
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data()
|
||||
, afterSignalAdded
|
||||
, afterSlotAdded
|
||||
, afterPropertyAdded);
|
||||
m_metaObject.reset(newMetaObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicQObject::emitSignal(const QString& name, const QList<QVariant>& args)
|
||||
{
|
||||
DynamicSignal signal;
|
||||
|
||||
for (DynamicSignal currentSignal : m_signalsByName.values(name))
|
||||
{
|
||||
if (currentSignal.validate(args))
|
||||
{
|
||||
signal = currentSignal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!signal.isValid())
|
||||
return false;
|
||||
|
||||
int index = m_metaObject->indexOfSignal(QMetaObject::normalizedSignature(signal.signature()));
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
QVariantList argsCopy = args;
|
||||
|
||||
QVector<void*> arguments(argsCopy.size() + 1 , 0);
|
||||
arguments[0] = 0;
|
||||
for (int i = 0; i < argsCopy.size(); ++i)
|
||||
arguments[i + 1] = &argsCopy[i];
|
||||
|
||||
QMetaObject::activate(this, index, arguments.data());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const QMetaObject* DynamicQObject::metaObject() const
|
||||
{
|
||||
return m_metaObject.data();
|
||||
}
|
||||
|
||||
bool DynamicQObject::executeSlot(const DynamicSlot& slot, void** args)
|
||||
{
|
||||
if (!slot.isValid())
|
||||
return false;
|
||||
|
||||
QList<QVariant> arguments;
|
||||
for (int i = 0; i < slot.argumentsTypes().count(); ++i)
|
||||
arguments << QVariant(slot.argumentTypeAt(i), args[i + 1]);
|
||||
|
||||
QVariant result = executeSlot(slot, arguments);
|
||||
|
||||
if (slot.returnType() != QMetaType::Void && result.isValid())
|
||||
{
|
||||
QMetaType metatype(slot.returnType());
|
||||
metatype.construct(args[0], result.constData());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant DynamicQObject::executeSlot(const DynamicSlot& slot, const QList<QVariant>& args)
|
||||
{
|
||||
QVariant slotName(slot.name());
|
||||
|
||||
const int numParametersPlusReturn = slot.argumentsTypes().count() + 1;
|
||||
std::vector<QVariant> argumentsAsVariants(numParametersPlusReturn);
|
||||
std::vector<void*> argumentsAsVoidPointers(numParametersPlusReturn);
|
||||
|
||||
for (int i = 0; i < numParametersPlusReturn; ++i) {
|
||||
argumentsAsVariants[i] = i == 0 ? QVariant() : args[i - 1];
|
||||
argumentsAsVoidPointers[i] = &argumentsAsVariants[i];
|
||||
}
|
||||
|
||||
if (m_dObjectCallback && m_dObjectPointer)
|
||||
m_dObjectCallback(m_dObjectPointer, &slotName, numParametersPlusReturn, &argumentsAsVoidPointers[0]);
|
||||
|
||||
return argumentsAsVariants[0];
|
||||
}
|
||||
|
||||
bool DynamicQObject::readProperty(const DynamicProperty& property, void** args)
|
||||
{
|
||||
if (!property.isValid())
|
||||
return false;
|
||||
|
||||
if (!property.isReadable())
|
||||
return false;
|
||||
|
||||
DynamicSlot readSlot = m_slotsByName.value(property.readSlot(), DynamicSlot());
|
||||
|
||||
if (!readSlot.isValid())
|
||||
return false;
|
||||
|
||||
if (readSlot.argumentsTypes().count() > 0)
|
||||
return false;
|
||||
|
||||
if (readSlot.returnType() != property.type())
|
||||
return false;
|
||||
|
||||
return executeSlot(readSlot, args);
|
||||
}
|
||||
|
||||
bool DynamicQObject::writeProperty(const DynamicProperty& property, void** args)
|
||||
{
|
||||
if (!property.isValid())
|
||||
return false;
|
||||
|
||||
if (!property.isWriteable())
|
||||
return false;
|
||||
|
||||
DynamicSlot writeSlot = m_slotsByName.value(property.writeSlot(), DynamicSlot());
|
||||
|
||||
if (!writeSlot.isValid())
|
||||
return false;
|
||||
|
||||
if (writeSlot.argumentsTypes().count() != 1)
|
||||
return false;
|
||||
|
||||
if (writeSlot.returnType() != QMetaType::Void)
|
||||
return false;
|
||||
|
||||
QVariant newValue(writeSlot.argumentTypeAt(0), args[0]);
|
||||
executeSlot(writeSlot, {newValue});
|
||||
}
|
||||
|
||||
int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** args)
|
||||
{
|
||||
if (callType == QMetaObject::InvokeMetaMethod)
|
||||
{
|
||||
QMetaMethod method = m_metaObject->method(index);
|
||||
|
||||
if (!method.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicSlot slot = m_slotsBySignature[method.methodSignature()];
|
||||
return executeSlot(slot, args) ? 1 : -1;
|
||||
}
|
||||
else if (callType == QMetaObject::ReadProperty)
|
||||
{
|
||||
QMetaProperty metaProperty = m_metaObject->property(index);
|
||||
|
||||
if (!metaProperty.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicProperty dynamicProperty = m_propertiesByName.value(metaProperty.name(), DynamicProperty());
|
||||
return readProperty(dynamicProperty, args) ? 1 : -1;
|
||||
}
|
||||
else if (callType == QMetaObject::WriteProperty)
|
||||
{
|
||||
QMetaProperty metaProperty = m_metaObject->property(index);
|
||||
|
||||
if (!metaProperty.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicProperty dynamicProperty = m_propertiesByName.value(metaProperty.name(), DynamicProperty());
|
||||
return writeProperty(dynamicProperty, args) ? 1 : -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMetaObject,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterSignalAdded,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterSlotAdded,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterPropertyAdded)
|
||||
{
|
||||
// Collect the current methods and signals
|
||||
QList<QMetaMethod> signalsList;
|
||||
QList<QMetaMethod> methodsList;
|
||||
QList<QMetaProperty> propertiesList;
|
||||
|
||||
for (int i = currentMetaObject->methodOffset(); i < currentMetaObject->methodCount(); ++i)
|
||||
{
|
||||
QMetaMethod method = currentMetaObject->method(i);
|
||||
if (method.methodType() == QMetaMethod::Signal)
|
||||
signalsList.append(method);
|
||||
else
|
||||
methodsList.append(method);
|
||||
}
|
||||
|
||||
for (int i = currentMetaObject->propertyOffset(); i < currentMetaObject->propertyCount(); ++i)
|
||||
{
|
||||
QMetaProperty property = currentMetaObject->property(i);
|
||||
propertiesList.append(property);
|
||||
}
|
||||
|
||||
QMetaObjectBuilder metaObjectBuilder;
|
||||
metaObjectBuilder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
metaObjectBuilder.setClassName(currentMetaObject->className());
|
||||
metaObjectBuilder.setSuperClass(currentMetaObject->superClass());
|
||||
|
||||
foreach (auto& method, signalsList)
|
||||
metaObjectBuilder.addMethod(method);
|
||||
|
||||
// Call custom code to be executed after signal have been added
|
||||
afterSignalAdded(metaObjectBuilder);
|
||||
|
||||
foreach (auto& method, methodsList)
|
||||
metaObjectBuilder.addMethod(method);
|
||||
|
||||
// Call custom code to be executed after slots have been added
|
||||
afterSlotAdded(metaObjectBuilder);
|
||||
|
||||
foreach (auto& property, propertiesList)
|
||||
metaObjectBuilder.addProperty(property);
|
||||
|
||||
afterPropertyAdded(metaObjectBuilder);
|
||||
|
||||
return metaObjectBuilder.toMetaObject();
|
||||
}
|
|
@ -1,19 +1,22 @@
|
|||
#pragma once
|
||||
#ifndef DYNAMICQOBJECT_H
|
||||
#define DYNAMICQOBJECT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include "private/qmetaobjectbuilder_p.h"
|
||||
#include "DynamicSignal.h"
|
||||
#include "DynamicSlot.h"
|
||||
#include "DynamicProperty.h"
|
||||
|
||||
class QMetaObjectBuilder;
|
||||
#include "IDynamicQObject.h"
|
||||
|
||||
/// This class implements a QObject to which signals, slots and properties can be added dynamically
|
||||
class DynamicQObject : public QObject
|
||||
template <class T>
|
||||
class DynamicQObject : public T, public IDynamicQObject
|
||||
{
|
||||
typedef void (*Callback)(void*, void*, int, void**);
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
DynamicQObject();
|
||||
|
@ -22,35 +25,31 @@ public:
|
|||
virtual ~DynamicQObject();
|
||||
|
||||
/// Sets the function to be called from C++ to D or Nimrod
|
||||
void setDObjectCallback(Callback callback) {
|
||||
m_dObjectCallback = callback;
|
||||
}
|
||||
virtual void setDObjectCallback(IDynamicQObject::Callback callback) override;
|
||||
|
||||
/// Sets the D or Nimrod object that owns this DynamicQObject
|
||||
void setDObjectPointer(void* dObjectPointer) {
|
||||
m_dObjectPointer = dObjectPointer;
|
||||
}
|
||||
virtual void setDObjectPointer(void* dObjectPointer) override;
|
||||
|
||||
/// Register a new signal
|
||||
bool registerSignal(const QString& name,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& signalIndex);
|
||||
virtual bool registerSignal(const QString& name,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& signalIndex) override;
|
||||
|
||||
/// Register a new slot
|
||||
bool registerSlot(const QString& name,
|
||||
const QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& slotIndex);
|
||||
virtual bool registerSlot(const QString& name,
|
||||
const QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& slotIndex) override;
|
||||
|
||||
/// Register a new property
|
||||
bool registerProperty(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName = "",
|
||||
const QString& notifySignalName = "");
|
||||
virtual bool registerProperty(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName = "",
|
||||
const QString& notifySignalName = "") override;
|
||||
|
||||
/// Emit the signal with the given name and arguments
|
||||
bool emitSignal(const QString& name, const QList<QVariant>& argumentsValues);
|
||||
virtual bool emitSignal(const QString& name, const QList<QVariant>& argumentsValues) override;
|
||||
|
||||
/// Return the QMetaObject for this DynamicQObject
|
||||
virtual const QMetaObject* metaObject() const;
|
||||
|
@ -82,5 +81,380 @@ private:
|
|||
QHash<QByteArray, DynamicProperty> m_propertiesByName;
|
||||
QScopedPointer<QMetaObject> m_metaObject;
|
||||
void* m_dObjectPointer;
|
||||
Callback m_dObjectCallback;
|
||||
IDynamicQObject::Callback m_dObjectCallback;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
DynamicQObject<T>::DynamicQObject()
|
||||
: T()
|
||||
, m_dObjectPointer(nullptr)
|
||||
, m_dObjectCallback(nullptr)
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
builder.setClassName("DynamicQObject");
|
||||
builder.setSuperClass(&T::staticMetaObject);
|
||||
m_metaObject.reset(builder.toMetaObject());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DynamicQObject<T>::setDObjectCallback(IDynamicQObject::Callback callback)
|
||||
{
|
||||
m_dObjectCallback = callback;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DynamicQObject<T>::setDObjectPointer(void* dObjectPointer)
|
||||
{
|
||||
m_dObjectPointer = dObjectPointer;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DynamicQObject<T>::~DynamicQObject() = default;
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::registerSlot(const QString& name,
|
||||
const QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& slotIndex)
|
||||
{
|
||||
DynamicSlot slot(name, returnType, argumentsTypes);
|
||||
|
||||
if (m_slotsBySignature.contains(slot.signature()))
|
||||
return false;
|
||||
|
||||
m_slotsByName.insertMulti(slot.name(), slot);
|
||||
m_slotsBySignature[slot.signature()] = slot;
|
||||
|
||||
auto afterSignalAdded = [](QMetaObjectBuilder&) {};
|
||||
auto afterPropertyAdded = afterSignalAdded;
|
||||
|
||||
auto afterSlotAdded = [&slot, returnType](QMetaObjectBuilder & metaObjectBuilder) {
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.addSlot(slot.signature());
|
||||
methodBuilder.setReturnType(QMetaType::typeName(returnType));
|
||||
methodBuilder.setAttributes(QMetaMethod::Scriptable);
|
||||
};
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data(),
|
||||
afterSignalAdded,
|
||||
afterSlotAdded,
|
||||
afterPropertyAdded);
|
||||
|
||||
m_metaObject.reset(newMetaObject);
|
||||
|
||||
slotIndex = m_metaObject->indexOfSlot(QMetaObject::normalizedSignature(slot.signature()));
|
||||
|
||||
return slotIndex != -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::registerSignal(const QString& name, const QList<QMetaType::Type>& arguments, int& signalIndex)
|
||||
{
|
||||
DynamicSignal signal(name, arguments);
|
||||
|
||||
if (m_signalsBySignature.contains(signal.signature()))
|
||||
return false;
|
||||
|
||||
m_signalsByName.insertMulti(signal.name(), signal);
|
||||
m_signalsBySignature[signal.signature()] = signal;
|
||||
|
||||
auto afterSignalAdded = [&signal](QMetaObjectBuilder & metaObjectBuilder) {
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.addSignal(signal.signature());
|
||||
methodBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
|
||||
methodBuilder.setAccess(QMetaMethod::Public);
|
||||
};
|
||||
|
||||
auto afterSlotAdded = [](QMetaObjectBuilder&) {};
|
||||
auto afterPropertyAdded = afterSlotAdded;
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data(),
|
||||
afterSignalAdded,
|
||||
afterSlotAdded,
|
||||
afterPropertyAdded);
|
||||
|
||||
m_metaObject.reset(newMetaObject);
|
||||
|
||||
signalIndex = m_metaObject->indexOfSignal(QMetaObject::normalizedSignature(signal.signature()));
|
||||
|
||||
return signalIndex != -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::registerProperty(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName,
|
||||
const QString& notifySignalName)
|
||||
{
|
||||
DynamicProperty property(name, type, readSlotName, writeSlotName, notifySignalName);
|
||||
|
||||
DynamicSignal notifySignal;
|
||||
|
||||
if (!notifySignalName.isEmpty())
|
||||
{
|
||||
notifySignal = m_signalsByName.value(notifySignalName, DynamicSignal());
|
||||
if (!notifySignal.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
m_propertiesByName.insert(name.toUtf8(), property);
|
||||
|
||||
auto afterSignalAdded = [](QMetaObjectBuilder & metaObjectBuilder) {};
|
||||
auto afterSlotAdded = [](QMetaObjectBuilder & metaObjectBuilder) {};
|
||||
auto afterPropertyAdded = [name, type, notifySignal](QMetaObjectBuilder & metaObjectBuilder)
|
||||
{
|
||||
int signalIndex = -1;
|
||||
if (notifySignal.isValid())
|
||||
{
|
||||
for (int i = 0; i < metaObjectBuilder.methodCount(); ++i)
|
||||
{
|
||||
QMetaMethodBuilder methodBuilder = metaObjectBuilder.method(i);
|
||||
if (methodBuilder.methodType() == QMetaMethod::Signal)
|
||||
{
|
||||
if (methodBuilder.signature() == QMetaObject::normalizedSignature(notifySignal.signature()));
|
||||
{
|
||||
signalIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto typeName = QMetaType::typeName(type);
|
||||
auto builder = metaObjectBuilder.addProperty(name.toUtf8(),
|
||||
QMetaObject::normalizedType(typeName),
|
||||
signalIndex);
|
||||
if (signalIndex == -1)
|
||||
builder.setConstant(true);
|
||||
};
|
||||
|
||||
auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data()
|
||||
, afterSignalAdded
|
||||
, afterSlotAdded
|
||||
, afterPropertyAdded);
|
||||
m_metaObject.reset(newMetaObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::emitSignal(const QString& name, const QList<QVariant>& args)
|
||||
{
|
||||
DynamicSignal signal;
|
||||
|
||||
for (DynamicSignal currentSignal : m_signalsByName.values(name))
|
||||
{
|
||||
if (currentSignal.validate(args))
|
||||
{
|
||||
signal = currentSignal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!signal.isValid())
|
||||
return false;
|
||||
|
||||
int index = m_metaObject->indexOfSignal(QMetaObject::normalizedSignature(signal.signature()));
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
QVariantList argsCopy = args;
|
||||
|
||||
QVector<void*> arguments(argsCopy.size() + 1 , 0);
|
||||
arguments[0] = 0;
|
||||
for (int i = 0; i < argsCopy.size(); ++i)
|
||||
arguments[i + 1] = &argsCopy[i];
|
||||
|
||||
QMetaObject::activate(this, index, arguments.data());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const QMetaObject* DynamicQObject<T>::metaObject() const
|
||||
{
|
||||
return m_metaObject.data();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::executeSlot(const DynamicSlot& slot, void** args)
|
||||
{
|
||||
if (!slot.isValid())
|
||||
return false;
|
||||
|
||||
QList<QVariant> arguments;
|
||||
for (int i = 0; i < slot.argumentsTypes().count(); ++i)
|
||||
arguments << QVariant(slot.argumentTypeAt(i), args[i + 1]);
|
||||
|
||||
QVariant result = executeSlot(slot, arguments);
|
||||
|
||||
if (slot.returnType() != QMetaType::Void && result.isValid())
|
||||
{
|
||||
QMetaType metatype(slot.returnType());
|
||||
metatype.construct(args[0], result.constData());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QVariant DynamicQObject<T>::executeSlot(const DynamicSlot& slot, const QList<QVariant>& args)
|
||||
{
|
||||
QVariant slotName(slot.name());
|
||||
|
||||
const int numParametersPlusReturn = slot.argumentsTypes().count() + 1;
|
||||
std::vector<QVariant> argumentsAsVariants(numParametersPlusReturn);
|
||||
std::vector<void*> argumentsAsVoidPointers(numParametersPlusReturn);
|
||||
|
||||
for (int i = 0; i < numParametersPlusReturn; ++i) {
|
||||
argumentsAsVariants[i] = i == 0 ? QVariant() : args[i - 1];
|
||||
argumentsAsVoidPointers[i] = &argumentsAsVariants[i];
|
||||
}
|
||||
|
||||
if (m_dObjectCallback && m_dObjectPointer)
|
||||
m_dObjectCallback(m_dObjectPointer, &slotName, numParametersPlusReturn, &argumentsAsVoidPointers[0]);
|
||||
|
||||
return argumentsAsVariants[0];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::readProperty(const DynamicProperty& property, void** args)
|
||||
{
|
||||
if (!property.isValid())
|
||||
return false;
|
||||
|
||||
if (!property.isReadable())
|
||||
return false;
|
||||
|
||||
DynamicSlot readSlot = m_slotsByName.value(property.readSlot(), DynamicSlot());
|
||||
|
||||
if (!readSlot.isValid())
|
||||
return false;
|
||||
|
||||
if (readSlot.argumentsTypes().count() > 0)
|
||||
return false;
|
||||
|
||||
if (readSlot.returnType() != property.type())
|
||||
return false;
|
||||
|
||||
return executeSlot(readSlot, args);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DynamicQObject<T>::writeProperty(const DynamicProperty& property, void** args)
|
||||
{
|
||||
if (!property.isValid())
|
||||
return false;
|
||||
|
||||
if (!property.isWriteable())
|
||||
return false;
|
||||
|
||||
DynamicSlot writeSlot = m_slotsByName.value(property.writeSlot(), DynamicSlot());
|
||||
|
||||
if (!writeSlot.isValid())
|
||||
return false;
|
||||
|
||||
if (writeSlot.argumentsTypes().count() != 1)
|
||||
return false;
|
||||
|
||||
if (writeSlot.returnType() != QMetaType::Void)
|
||||
return false;
|
||||
|
||||
QVariant newValue(writeSlot.argumentTypeAt(0), args[0]);
|
||||
executeSlot(writeSlot, {newValue});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int DynamicQObject<T>::qt_metacall(QMetaObject::Call callType, int index, void** args)
|
||||
{
|
||||
switch (callType)
|
||||
{
|
||||
case QMetaObject::InvokeMetaMethod: {
|
||||
QMetaMethod method = m_metaObject->method(index);
|
||||
|
||||
if (!method.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicSlot slot = m_slotsBySignature[method.methodSignature()];
|
||||
return executeSlot(slot, args) ? 1 : -1;
|
||||
}
|
||||
|
||||
case QMetaObject::ReadProperty: {
|
||||
QMetaProperty metaProperty = m_metaObject->property(index);
|
||||
|
||||
if (!metaProperty.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicProperty dynamicProperty = m_propertiesByName.value(metaProperty.name(), DynamicProperty());
|
||||
return readProperty(dynamicProperty, args) ? 1 : -1;
|
||||
}
|
||||
|
||||
case QMetaObject::WriteProperty: {
|
||||
QMetaProperty metaProperty = m_metaObject->property(index);
|
||||
|
||||
if (!metaProperty.isValid())
|
||||
return -1;
|
||||
|
||||
DynamicProperty dynamicProperty = m_propertiesByName.value(metaProperty.name(), DynamicProperty());
|
||||
return writeProperty(dynamicProperty, args) ? 1 : -1;
|
||||
}
|
||||
|
||||
default:
|
||||
return T::qt_metacall(callType, index, args);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QMetaObject* DynamicQObject<T>::recreateMetaObjectBuilder(QMetaObject* currentMetaObject,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterSignalAdded,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterSlotAdded,
|
||||
const std::function<void(QMetaObjectBuilder&)>& afterPropertyAdded)
|
||||
{
|
||||
// Collect the current methods and signals
|
||||
QList<QMetaMethod> signalsList;
|
||||
QList<QMetaMethod> methodsList;
|
||||
QList<QMetaProperty> propertiesList;
|
||||
|
||||
for (int i = currentMetaObject->methodOffset(); i < currentMetaObject->methodCount(); ++i)
|
||||
{
|
||||
QMetaMethod method = currentMetaObject->method(i);
|
||||
if (method.methodType() == QMetaMethod::Signal)
|
||||
signalsList.append(method);
|
||||
else
|
||||
methodsList.append(method);
|
||||
}
|
||||
|
||||
for (int i = currentMetaObject->propertyOffset(); i < currentMetaObject->propertyCount(); ++i)
|
||||
{
|
||||
QMetaProperty property = currentMetaObject->property(i);
|
||||
propertiesList.append(property);
|
||||
}
|
||||
|
||||
QMetaObjectBuilder metaObjectBuilder;
|
||||
metaObjectBuilder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
|
||||
metaObjectBuilder.setClassName(currentMetaObject->className());
|
||||
metaObjectBuilder.setSuperClass(currentMetaObject->superClass());
|
||||
|
||||
for (auto& method : signalsList)
|
||||
metaObjectBuilder.addMethod(method);
|
||||
|
||||
// Call custom code to be executed after signal have been added
|
||||
afterSignalAdded(metaObjectBuilder);
|
||||
|
||||
for (auto& method : methodsList)
|
||||
metaObjectBuilder.addMethod(method);
|
||||
|
||||
// Call custom code to be executed after slots have been added
|
||||
afterSlotAdded(metaObjectBuilder);
|
||||
|
||||
for (auto& property : propertiesList)
|
||||
metaObjectBuilder.addProperty(property);
|
||||
|
||||
afterPropertyAdded(metaObjectBuilder);
|
||||
|
||||
return metaObjectBuilder.toMetaObject();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
#include "DynamicSignal.h"
|
||||
#include "DynamicQObject.h"
|
||||
|
||||
struct SignalData
|
||||
{
|
||||
QString name;
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
QByteArray signature;
|
||||
};
|
||||
|
||||
DynamicSignal::DynamicSignal()
|
||||
: d(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DynamicSignal::DynamicSignal(const QString& name, const QList<QMetaType::Type>& arguments)
|
||||
: d(new SignalData())
|
||||
{
|
||||
d->name = name;
|
||||
d->signature = QByteArray();
|
||||
d->argumentsTypes = arguments;
|
||||
_initSignature();
|
||||
}
|
||||
|
||||
DynamicSignal::DynamicSignal(const DynamicSignal& signal)
|
||||
{
|
||||
if (signal.isValid())
|
||||
{
|
||||
d.reset(new SignalData());
|
||||
*d = *signal.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
}
|
||||
|
||||
DynamicSignal& DynamicSignal::operator=(const DynamicSignal& signal)
|
||||
{
|
||||
if (signal.isValid())
|
||||
{
|
||||
d.reset(new SignalData());
|
||||
*d = *signal.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSignal::~DynamicSignal()
|
||||
{
|
||||
}
|
||||
|
||||
bool DynamicSignal::isValid() const
|
||||
{
|
||||
return d != nullptr;
|
||||
}
|
||||
|
||||
QString DynamicSignal::name() const
|
||||
{
|
||||
return isValid() ? d->name : QString();
|
||||
}
|
||||
|
||||
QByteArray DynamicSignal::signature() const
|
||||
{
|
||||
return isValid() ? d->signature : QByteArray();
|
||||
}
|
||||
|
||||
bool DynamicSignal::validate(const QVariantList& arguments)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicSignal::validate(const QList<QMetaType::Type>& argumentsTypes, const QVariantList& argumentsValues)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicSignal::_initSignature()
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments;
|
||||
for (int i = 0; i < d->argumentsTypes.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
arguments += ',';
|
||||
arguments += QMetaType::typeName(d->argumentsTypes[i]);
|
||||
}
|
||||
|
||||
d->signature = signature.arg(d->name, arguments).toUtf8();
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
#pragma once
|
||||
#ifndef DYNAMICSIGNAL_H
|
||||
#define DYNAMICSIGNAL_H
|
||||
|
||||
#include <QtCore/QMetaType>
|
||||
#include <memory>
|
||||
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QList>
|
||||
|
||||
class SignalData;
|
||||
class DynamicQObject;
|
||||
|
||||
class DynamicSignal
|
||||
{
|
||||
|
@ -28,3 +32,93 @@ private:
|
|||
|
||||
std::unique_ptr<SignalData> d;
|
||||
};
|
||||
|
||||
struct SignalData
|
||||
{
|
||||
QString name;
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
QByteArray signature;
|
||||
};
|
||||
|
||||
DynamicSignal::DynamicSignal()
|
||||
: d(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DynamicSignal::DynamicSignal(const QString& name, const QList<QMetaType::Type>& arguments)
|
||||
: d(new SignalData())
|
||||
{
|
||||
d->name = name;
|
||||
d->signature = QByteArray();
|
||||
d->argumentsTypes = arguments;
|
||||
_initSignature();
|
||||
}
|
||||
|
||||
DynamicSignal::DynamicSignal(const DynamicSignal& signal)
|
||||
{
|
||||
if (signal.isValid())
|
||||
{
|
||||
d.reset(new SignalData());
|
||||
*d = *signal.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
}
|
||||
|
||||
DynamicSignal& DynamicSignal::operator=(const DynamicSignal& signal)
|
||||
{
|
||||
if (signal.isValid())
|
||||
{
|
||||
d.reset(new SignalData());
|
||||
*d = *signal.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSignal::~DynamicSignal()
|
||||
{
|
||||
}
|
||||
|
||||
bool DynamicSignal::isValid() const
|
||||
{
|
||||
return d != nullptr;
|
||||
}
|
||||
|
||||
QString DynamicSignal::name() const
|
||||
{
|
||||
return isValid() ? d->name : QString();
|
||||
}
|
||||
|
||||
QByteArray DynamicSignal::signature() const
|
||||
{
|
||||
return isValid() ? d->signature : QByteArray();
|
||||
}
|
||||
|
||||
bool DynamicSignal::validate(const QVariantList& arguments)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicSignal::validate(const QList<QMetaType::Type>& argumentsTypes, const QVariantList& argumentsValues)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicSignal::_initSignature()
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments;
|
||||
for (int i = 0; i < d->argumentsTypes.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
arguments += ',';
|
||||
arguments += QMetaType::typeName(d->argumentsTypes[i]);
|
||||
}
|
||||
|
||||
d->signature = signature.arg(d->name, arguments).toUtf8();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,109 +0,0 @@
|
|||
#include "DynamicSlot.h"
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <functional>
|
||||
#include "private/qmetaobjectbuilder_p.h"
|
||||
|
||||
struct SlotData
|
||||
{
|
||||
QString name;
|
||||
QMetaType::Type returnType;
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
QByteArray signature;
|
||||
};
|
||||
|
||||
DynamicSlot::DynamicSlot()
|
||||
: d(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DynamicSlot::DynamicSlot(const QString& name,
|
||||
QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes)
|
||||
: d(new SlotData())
|
||||
{
|
||||
d->name = name;
|
||||
d->returnType = returnType;
|
||||
d->argumentsTypes = argumentsTypes;
|
||||
_initSignature();
|
||||
}
|
||||
|
||||
DynamicSlot::DynamicSlot(const DynamicSlot& slot)
|
||||
{
|
||||
if (slot.isValid())
|
||||
{
|
||||
d.reset(new SlotData());
|
||||
*d = *slot.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
}
|
||||
|
||||
DynamicSlot& DynamicSlot::operator=(const DynamicSlot& slot)
|
||||
{
|
||||
if (slot.isValid())
|
||||
{
|
||||
d.reset(new SlotData());
|
||||
*d = *slot.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSlot::~DynamicSlot()
|
||||
{
|
||||
}
|
||||
|
||||
QString DynamicSlot::name() const
|
||||
{
|
||||
return isValid() ? d->name : QString();
|
||||
}
|
||||
|
||||
bool DynamicSlot::isValid() const
|
||||
{
|
||||
return d != nullptr;
|
||||
}
|
||||
|
||||
QByteArray DynamicSlot::signature() const
|
||||
{
|
||||
return isValid() ? d->signature : QByteArray();
|
||||
}
|
||||
|
||||
bool DynamicSlot::validate(const QVariantList& argumentsValues)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicSlot::returnType() const
|
||||
{
|
||||
return isValid() ? d->returnType : QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
QList<QMetaType::Type> DynamicSlot::argumentsTypes() const
|
||||
{
|
||||
return isValid() ? d->argumentsTypes : QList<QMetaType::Type>();
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicSlot::argumentTypeAt(int i) const
|
||||
{
|
||||
return isValid() ? d->argumentsTypes.at(i) : QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
void DynamicSlot::_initSignature()
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments = "";
|
||||
for (int i = 0; i < d->argumentsTypes.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
arguments += ',';
|
||||
arguments += QMetaType::typeName(d->argumentsTypes[i]);
|
||||
}
|
||||
|
||||
d->signature = signature.arg(d->name, arguments).toUtf8();
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#ifndef DYNAMICSLOT_H
|
||||
#define DYNAMICSLOT_H
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
@ -6,6 +7,12 @@
|
|||
#include <QtCore/QList>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QMetaType>
|
||||
|
||||
#include "private/qmetaobjectbuilder_p.h"
|
||||
|
||||
class SlotData;
|
||||
class QString;
|
||||
|
@ -34,3 +41,107 @@ private:
|
|||
|
||||
std::unique_ptr<SlotData> d;
|
||||
};
|
||||
|
||||
struct SlotData
|
||||
{
|
||||
QString name;
|
||||
QMetaType::Type returnType;
|
||||
QList<QMetaType::Type> argumentsTypes;
|
||||
QByteArray signature;
|
||||
};
|
||||
|
||||
DynamicSlot::DynamicSlot()
|
||||
: d(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DynamicSlot::DynamicSlot(const QString& name,
|
||||
QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes)
|
||||
: d(new SlotData())
|
||||
{
|
||||
d->name = name;
|
||||
d->returnType = returnType;
|
||||
d->argumentsTypes = argumentsTypes;
|
||||
_initSignature();
|
||||
}
|
||||
|
||||
DynamicSlot::DynamicSlot(const DynamicSlot& slot)
|
||||
{
|
||||
if (slot.isValid())
|
||||
{
|
||||
d.reset(new SlotData());
|
||||
*d = *slot.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
}
|
||||
|
||||
DynamicSlot& DynamicSlot::operator=(const DynamicSlot& slot)
|
||||
{
|
||||
if (slot.isValid())
|
||||
{
|
||||
d.reset(new SlotData());
|
||||
*d = *slot.d;
|
||||
}
|
||||
else
|
||||
d.reset(nullptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSlot::~DynamicSlot()
|
||||
{
|
||||
}
|
||||
|
||||
QString DynamicSlot::name() const
|
||||
{
|
||||
return isValid() ? d->name : QString();
|
||||
}
|
||||
|
||||
bool DynamicSlot::isValid() const
|
||||
{
|
||||
return d != nullptr;
|
||||
}
|
||||
|
||||
QByteArray DynamicSlot::signature() const
|
||||
{
|
||||
return isValid() ? d->signature : QByteArray();
|
||||
}
|
||||
|
||||
bool DynamicSlot::validate(const QVariantList& argumentsValues)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicSlot::returnType() const
|
||||
{
|
||||
return isValid() ? d->returnType : QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
QList<QMetaType::Type> DynamicSlot::argumentsTypes() const
|
||||
{
|
||||
return isValid() ? d->argumentsTypes : QList<QMetaType::Type>();
|
||||
}
|
||||
|
||||
QMetaType::Type DynamicSlot::argumentTypeAt(int i) const
|
||||
{
|
||||
return isValid() ? d->argumentsTypes.at(i) : QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
void DynamicSlot::_initSignature()
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments = "";
|
||||
for (int i = 0; i < d->argumentsTypes.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
arguments += ',';
|
||||
arguments += QMetaType::typeName(d->argumentsTypes[i]);
|
||||
}
|
||||
|
||||
d->signature = signature.arg(d->name, arguments).toUtf8();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef IDYNAMICQOBJECT_H
|
||||
#define IDYNAMICQOBJECT_H
|
||||
|
||||
class IDynamicQObject
|
||||
{
|
||||
public:
|
||||
typedef void (*Callback)(void*, void*, int, void**);
|
||||
|
||||
/// Destructor
|
||||
virtual ~IDynamicQObject() = default;
|
||||
|
||||
/// Sets the function to be called from C++ to D or Nimrod
|
||||
virtual void setDObjectCallback(Callback callback) = 0;
|
||||
|
||||
/// Sets the D or Nimrod object that owns this DynamicQObject
|
||||
virtual void setDObjectPointer(void* dObjectPointer) = 0;
|
||||
|
||||
/// Register a new signal
|
||||
virtual bool registerSignal(const QString& name,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& signalIndex) = 0;
|
||||
|
||||
/// Register a new slot
|
||||
virtual bool registerSlot(const QString& name,
|
||||
const QMetaType::Type returnType,
|
||||
const QList<QMetaType::Type>& argumentsTypes,
|
||||
int& slotIndex) = 0;
|
||||
|
||||
/// Register a new property
|
||||
virtual bool registerProperty(const QString& name,
|
||||
QMetaType::Type type,
|
||||
const QString& readSlotName,
|
||||
const QString& writeSlotName = "",
|
||||
const QString& notifySignalName = "") = 0;
|
||||
|
||||
/// Emit the signal with the given name and arguments
|
||||
virtual bool emitSignal(const QString& name, const QList<QVariant>& argumentsValues) = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -114,7 +114,7 @@ enum MetaDataFlags {
|
|||
TypeNameIndexMask = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
extern int qMetaTypeTypeInternal(const char *);
|
||||
extern int qMetaTypeTypeInternal(const char*);
|
||||
|
||||
class QArgumentType
|
||||
{
|
||||
|
@ -122,21 +122,23 @@ public:
|
|||
QArgumentType(int type)
|
||||
: _type(type)
|
||||
{}
|
||||
QArgumentType(const QByteArray &name)
|
||||
QArgumentType(const QByteArray& name)
|
||||
: _type(qMetaTypeTypeInternal(name.constData())), _name(name)
|
||||
{}
|
||||
QArgumentType()
|
||||
: _type(0)
|
||||
{}
|
||||
int type() const
|
||||
{ return _type; }
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
QByteArray name() const
|
||||
{
|
||||
if (_type && _name.isEmpty())
|
||||
const_cast<QArgumentType *>(this)->_name = QMetaType::typeName(_type);
|
||||
const_cast<QArgumentType*>(this)->_name = QMetaType::typeName(_type);
|
||||
return _name;
|
||||
}
|
||||
bool operator==(const QArgumentType &other) const
|
||||
bool operator==(const QArgumentType& other) const
|
||||
{
|
||||
if (_type)
|
||||
return _type == other._type;
|
||||
|
@ -145,7 +147,7 @@ public:
|
|||
else
|
||||
return _name == other._name;
|
||||
}
|
||||
bool operator!=(const QArgumentType &other) const
|
||||
bool operator!=(const QArgumentType& other) const
|
||||
{
|
||||
if (_type)
|
||||
return _type != other._type;
|
||||
|
@ -182,55 +184,57 @@ struct QMetaObjectPrivate
|
|||
// revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
|
||||
// revision 7 is Qt 5
|
||||
|
||||
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
|
||||
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
|
||||
static inline const QMetaObjectPrivate* get(const QMetaObject* metaobject)
|
||||
{
|
||||
return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data);
|
||||
}
|
||||
|
||||
static int originalClone(const QMetaObject *obj, int local_method_index);
|
||||
static int originalClone(const QMetaObject* obj, int local_method_index);
|
||||
|
||||
static QByteArray decodeMethodSignature(const char *signature,
|
||||
QArgumentTypeArray &types);
|
||||
static int indexOfSignalRelative(const QMetaObject **baseObject,
|
||||
const QByteArray &name, int argc,
|
||||
const QArgumentType *types);
|
||||
static int indexOfSlotRelative(const QMetaObject **m,
|
||||
const QByteArray &name, int argc,
|
||||
const QArgumentType *types);
|
||||
static int indexOfSignal(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfSlot(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfMethod(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index);
|
||||
Q_CORE_EXPORT static int signalOffset(const QMetaObject *m);
|
||||
Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m);
|
||||
Q_CORE_EXPORT static int signalIndex(const QMetaMethod &m);
|
||||
static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
|
||||
int methodArgc, const QArgumentType *methodTypes);
|
||||
static bool checkConnectArgs(const QMetaMethodPrivate *signal,
|
||||
const QMetaMethodPrivate *method);
|
||||
static QByteArray decodeMethodSignature(const char* signature,
|
||||
QArgumentTypeArray& types);
|
||||
static int indexOfSignalRelative(const QMetaObject** baseObject,
|
||||
const QByteArray& name, int argc,
|
||||
const QArgumentType* types);
|
||||
static int indexOfSlotRelative(const QMetaObject** m,
|
||||
const QByteArray& name, int argc,
|
||||
const QArgumentType* types);
|
||||
static int indexOfSignal(const QMetaObject* m, const QByteArray& name,
|
||||
int argc, const QArgumentType* types);
|
||||
static int indexOfSlot(const QMetaObject* m, const QByteArray& name,
|
||||
int argc, const QArgumentType* types);
|
||||
static int indexOfMethod(const QMetaObject* m, const QByteArray& name,
|
||||
int argc, const QArgumentType* types);
|
||||
static int indexOfConstructor(const QMetaObject* m, const QByteArray& name,
|
||||
int argc, const QArgumentType* types);
|
||||
Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject* m, int signal_index);
|
||||
Q_CORE_EXPORT static int signalOffset(const QMetaObject* m);
|
||||
Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject* m);
|
||||
Q_CORE_EXPORT static int signalIndex(const QMetaMethod& m);
|
||||
static bool checkConnectArgs(int signalArgc, const QArgumentType* signalTypes,
|
||||
int methodArgc, const QArgumentType* methodTypes);
|
||||
static bool checkConnectArgs(const QMetaMethodPrivate* signal,
|
||||
const QMetaMethodPrivate* method);
|
||||
|
||||
static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
|
||||
static QList<QByteArray> parameterTypeNamesFromSignature(const char* signature);
|
||||
|
||||
#ifndef QT_NO_QOBJECT
|
||||
//defined in qobject.cpp
|
||||
enum DisconnectType { DisconnectAll, DisconnectOne };
|
||||
static void memberIndexes(const QObject *obj, const QMetaMethod &member,
|
||||
int *signalIndex, int *methodIndex);
|
||||
static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index,
|
||||
const QMetaObject *smeta,
|
||||
const QObject *receiver, int method_index_relative,
|
||||
const QMetaObject *rmeta = 0,
|
||||
int type = 0, int *types = 0);
|
||||
static bool disconnect(const QObject *sender, int signal_index,
|
||||
const QMetaObject *smeta,
|
||||
const QObject *receiver, int method_index, void **slot,
|
||||
static void memberIndexes(const QObject* obj, const QMetaMethod& member,
|
||||
int* signalIndex, int* methodIndex);
|
||||
static QObjectPrivate::Connection* connect(const QObject* sender, int signal_index,
|
||||
const QMetaObject* smeta,
|
||||
const QObject* receiver, int method_index_relative,
|
||||
const QMetaObject* rmeta = 0,
|
||||
int type = 0, int* types = 0);
|
||||
static bool disconnect(const QObject* sender, int signal_index,
|
||||
const QMetaObject* smeta,
|
||||
const QObject* receiver, int method_index, void** slot,
|
||||
DisconnectType = DisconnectAll);
|
||||
static inline bool disconnectHelper(QObjectPrivate::Connection *c,
|
||||
const QObject *receiver, int method_index, void **slot,
|
||||
QMutex *senderMutex, DisconnectType = DisconnectAll);
|
||||
static inline bool disconnectHelper(QObjectPrivate::Connection* c,
|
||||
const QObject* receiver, int method_index, void** slot,
|
||||
QMutex* senderMutex, DisconnectType = DisconnectAll);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -246,7 +250,7 @@ static inline bool is_ident_char(char s)
|
|||
|| (s >= 'A' && s <= 'Z')
|
||||
|| (s >= '0' && s <= '9')
|
||||
|| s == '_'
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
static inline bool is_space(char s)
|
||||
|
|
|
@ -100,14 +100,14 @@ public:
|
|||
Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
|
||||
|
||||
QMetaObjectBuilder();
|
||||
explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
|
||||
explicit QMetaObjectBuilder(const QMetaObject* prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
|
||||
virtual ~QMetaObjectBuilder();
|
||||
|
||||
QByteArray className() const;
|
||||
void setClassName(const QByteArray& name);
|
||||
|
||||
const QMetaObject *superClass() const;
|
||||
void setSuperClass(const QMetaObject *meta);
|
||||
const QMetaObject* superClass() const;
|
||||
void setSuperClass(const QMetaObject* meta);
|
||||
|
||||
MetaObjectFlags flags() const;
|
||||
void setFlags(MetaObjectFlags);
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
QMetaMethodBuilder addConstructor(const QByteArray& signature);
|
||||
QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
|
||||
|
||||
QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
|
||||
QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId = -1);
|
||||
QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
|
||||
|
||||
QMetaEnumBuilder addEnumerator(const QByteArray& name);
|
||||
|
@ -137,15 +137,15 @@ public:
|
|||
|
||||
int addClassInfo(const QByteArray& name, const QByteArray& value);
|
||||
|
||||
int addRelatedMetaObject(const QMetaObject *meta);
|
||||
int addRelatedMetaObject(const QMetaObject* meta);
|
||||
|
||||
void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
|
||||
void addMetaObject(const QMetaObject* prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
|
||||
|
||||
QMetaMethodBuilder method(int index) const;
|
||||
QMetaMethodBuilder constructor(int index) const;
|
||||
QMetaPropertyBuilder property(int index) const;
|
||||
QMetaEnumBuilder enumerator(int index) const;
|
||||
const QMetaObject *relatedMetaObject(int index) const;
|
||||
const QMetaObject* relatedMetaObject(int index) const;
|
||||
|
||||
QByteArray classInfoName(int index) const;
|
||||
QByteArray classInfoValue(int index) const;
|
||||
|
@ -165,26 +165,26 @@ public:
|
|||
int indexOfEnumerator(const QByteArray& name);
|
||||
int indexOfClassInfo(const QByteArray& name);
|
||||
|
||||
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
|
||||
typedef void (*StaticMetacallFunction)(QObject*, QMetaObject::Call, int, void**);
|
||||
|
||||
QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
|
||||
void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
|
||||
|
||||
QMetaObject *toMetaObject() const;
|
||||
QByteArray toRelocatableData(bool * = 0) const;
|
||||
static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
|
||||
QMetaObject* toMetaObject() const;
|
||||
QByteArray toRelocatableData(bool* = 0) const;
|
||||
static void fromRelocatableData(QMetaObject*, const QMetaObject*, const QByteArray&);
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
void serialize(QDataStream& stream) const;
|
||||
void deserialize
|
||||
(QDataStream& stream,
|
||||
const QMap<QByteArray, const QMetaObject *>& references);
|
||||
(QDataStream& stream,
|
||||
const QMap<QByteArray, const QMetaObject*>& references);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QMetaObjectBuilder)
|
||||
|
||||
QMetaObjectBuilderPrivate *d;
|
||||
QMetaObjectBuilderPrivate* d;
|
||||
|
||||
friend class QMetaMethodBuilder;
|
||||
friend class QMetaPropertyBuilder;
|
||||
|
@ -221,16 +221,16 @@ public:
|
|||
void setRevision(int revision);
|
||||
|
||||
private:
|
||||
const QMetaObjectBuilder *_mobj;
|
||||
const QMetaObjectBuilder* _mobj;
|
||||
int _index;
|
||||
|
||||
friend class QMetaObjectBuilder;
|
||||
friend class QMetaPropertyBuilder;
|
||||
|
||||
QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
|
||||
QMetaMethodBuilder(const QMetaObjectBuilder* mobj, int index)
|
||||
: _mobj(mobj), _index(index) {}
|
||||
|
||||
QMetaMethodBuilderPrivate *d_func() const;
|
||||
QMetaMethodBuilderPrivate* d_func() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMetaPropertyBuilder
|
||||
|
@ -238,7 +238,9 @@ class Q_CORE_EXPORT QMetaPropertyBuilder
|
|||
public:
|
||||
QMetaPropertyBuilder() : _mobj(0), _index(0) {}
|
||||
|
||||
int index() const { return _index; }
|
||||
int index() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
QByteArray name() const;
|
||||
QByteArray type() const;
|
||||
|
@ -278,15 +280,15 @@ public:
|
|||
void setRevision(int revision);
|
||||
|
||||
private:
|
||||
const QMetaObjectBuilder *_mobj;
|
||||
const QMetaObjectBuilder* _mobj;
|
||||
int _index;
|
||||
|
||||
friend class QMetaObjectBuilder;
|
||||
|
||||
QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
|
||||
QMetaPropertyBuilder(const QMetaObjectBuilder* mobj, int index)
|
||||
: _mobj(mobj), _index(index) {}
|
||||
|
||||
QMetaPropertyBuilderPrivate *d_func() const;
|
||||
QMetaPropertyBuilderPrivate* d_func() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMetaEnumBuilder
|
||||
|
@ -294,7 +296,9 @@ class Q_CORE_EXPORT QMetaEnumBuilder
|
|||
public:
|
||||
QMetaEnumBuilder() : _mobj(0), _index(0) {}
|
||||
|
||||
int index() const { return _index; }
|
||||
int index() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
QByteArray name() const;
|
||||
|
||||
|
@ -309,27 +313,27 @@ public:
|
|||
void removeKey(int index);
|
||||
|
||||
private:
|
||||
const QMetaObjectBuilder *_mobj;
|
||||
const QMetaObjectBuilder* _mobj;
|
||||
int _index;
|
||||
|
||||
friend class QMetaObjectBuilder;
|
||||
|
||||
QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
|
||||
QMetaEnumBuilder(const QMetaObjectBuilder* mobj, int index)
|
||||
: _mobj(mobj), _index(index) {}
|
||||
|
||||
QMetaEnumBuilderPrivate *d_func() const;
|
||||
QMetaEnumBuilderPrivate* d_func() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMetaStringTable
|
||||
{
|
||||
public:
|
||||
explicit QMetaStringTable(const QByteArray &className);
|
||||
explicit QMetaStringTable(const QByteArray& className);
|
||||
|
||||
int enter(const QByteArray &value);
|
||||
int enter(const QByteArray& value);
|
||||
|
||||
static int preferredAlignment();
|
||||
int blobSize() const;
|
||||
void writeBlob(char *out) const;
|
||||
void writeBlob(char* out) const;
|
||||
|
||||
private:
|
||||
typedef QHash<QByteArray, int> Entries; // string --> index mapping
|
||||
|
|
|
@ -68,19 +68,21 @@ QT_BEGIN_NAMESPACE
|
|||
class QVariant;
|
||||
class QThreadData;
|
||||
class QObjectConnectionListVector;
|
||||
namespace QtSharedPointer { struct ExternalRefCountData; }
|
||||
namespace QtSharedPointer {
|
||||
struct ExternalRefCountData;
|
||||
}
|
||||
|
||||
/* for Qt Test */
|
||||
struct QSignalSpyCallbackSet
|
||||
{
|
||||
typedef void (*BeginCallback)(QObject *caller, int signal_or_method_index, void **argv);
|
||||
typedef void (*EndCallback)(QObject *caller, int signal_or_method_index);
|
||||
typedef void (*BeginCallback)(QObject* caller, int signal_or_method_index, void** argv);
|
||||
typedef void (*EndCallback)(QObject* caller, int signal_or_method_index);
|
||||
BeginCallback signal_begin_callback,
|
||||
slot_begin_callback;
|
||||
slot_begin_callback;
|
||||
EndCallback signal_end_callback,
|
||||
slot_end_callback;
|
||||
};
|
||||
void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
|
||||
void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet& callback_set);
|
||||
|
||||
extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
|
||||
|
||||
|
@ -89,19 +91,19 @@ enum { QObjectPrivateVersion = QT_VERSION };
|
|||
class Q_CORE_EXPORT QAbstractDeclarativeData
|
||||
{
|
||||
public:
|
||||
static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
|
||||
static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *);
|
||||
static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
|
||||
static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **);
|
||||
static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int);
|
||||
static bool (*isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int);
|
||||
static void (*destroyed)(QAbstractDeclarativeData*, QObject*);
|
||||
static void (*destroyed_qml1)(QAbstractDeclarativeData*, QObject*);
|
||||
static void (*parentChanged)(QAbstractDeclarativeData*, QObject*, QObject*);
|
||||
static void (*signalEmitted)(QAbstractDeclarativeData*, QObject*, int, void**);
|
||||
static int (*receivers)(QAbstractDeclarativeData*, const QObject*, int);
|
||||
static bool (*isSignalConnected)(QAbstractDeclarativeData*, const QObject*, int);
|
||||
};
|
||||
|
||||
// This is an implementation of QAbstractDeclarativeData that is identical with
|
||||
// the implementation in QtDeclarative and QtQml for the first bit
|
||||
struct QAbstractDeclarativeDataImpl : public QAbstractDeclarativeData
|
||||
{
|
||||
quint32 ownedByQml1:1;
|
||||
quint32 ownedByQml1: 1;
|
||||
quint32 unused: 31;
|
||||
};
|
||||
|
||||
|
@ -113,9 +115,9 @@ public:
|
|||
struct ExtraData
|
||||
{
|
||||
ExtraData() {}
|
||||
#ifndef QT_NO_USERDATA
|
||||
QVector<QObjectUserData *> userData;
|
||||
#endif
|
||||
#ifndef QT_NO_USERDATA
|
||||
QVector<QObjectUserData*> userData;
|
||||
#endif
|
||||
QList<QByteArray> propertyNames;
|
||||
QList<QVariant> propertyValues;
|
||||
QVector<int> runningTimers;
|
||||
|
@ -123,20 +125,20 @@ public:
|
|||
QString objectName;
|
||||
};
|
||||
|
||||
typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
|
||||
typedef void (*StaticMetaCallFunction)(QObject*, QMetaObject::Call, int, void**);
|
||||
struct Connection
|
||||
{
|
||||
QObject *sender;
|
||||
QObject *receiver;
|
||||
QObject* sender;
|
||||
QObject* receiver;
|
||||
union {
|
||||
StaticMetaCallFunction callFunction;
|
||||
QtPrivate::QSlotObjectBase *slotObj;
|
||||
QtPrivate::QSlotObjectBase* slotObj;
|
||||
};
|
||||
// The next pointer for the singly-linked ConnectionList
|
||||
Connection *nextConnectionList;
|
||||
Connection* nextConnectionList;
|
||||
//senders linked list
|
||||
Connection *next;
|
||||
Connection **prev;
|
||||
Connection* next;
|
||||
Connection** prev;
|
||||
QAtomicPointer<const int> argumentTypes;
|
||||
QAtomicInt ref_;
|
||||
ushort method_offset;
|
||||
|
@ -149,8 +151,12 @@ public:
|
|||
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
|
||||
}
|
||||
~Connection();
|
||||
int method() const { return method_offset + method_relative; }
|
||||
void ref() { ref_.ref(); }
|
||||
int method() const {
|
||||
return method_offset + method_relative;
|
||||
}
|
||||
void ref() {
|
||||
ref_.ref();
|
||||
}
|
||||
void deref() {
|
||||
if (!ref_.deref()) {
|
||||
Q_ASSERT(!receiver);
|
||||
|
@ -161,13 +167,13 @@ public:
|
|||
// ConnectionList is a singly-linked list
|
||||
struct ConnectionList {
|
||||
ConnectionList() : first(0), last(0) {}
|
||||
Connection *first;
|
||||
Connection *last;
|
||||
Connection* first;
|
||||
Connection* last;
|
||||
};
|
||||
|
||||
struct Sender
|
||||
{
|
||||
QObject *sender;
|
||||
QObject* sender;
|
||||
int signal;
|
||||
int ref;
|
||||
};
|
||||
|
@ -177,64 +183,64 @@ public:
|
|||
virtual ~QObjectPrivate();
|
||||
void deleteChildren();
|
||||
|
||||
void setParent_helper(QObject *);
|
||||
void setParent_helper(QObject*);
|
||||
void moveToThread_helper();
|
||||
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
|
||||
void _q_reregisterTimers(void *pointer);
|
||||
void setThreadData_helper(QThreadData* currentData, QThreadData* targetData);
|
||||
void _q_reregisterTimers(void* pointer);
|
||||
|
||||
bool isSender(const QObject *receiver, const char *signal) const;
|
||||
QObjectList receiverList(const char *signal) const;
|
||||
bool isSender(const QObject* receiver, const char* signal) const;
|
||||
QObjectList receiverList(const char* signal) const;
|
||||
QObjectList senderList() const;
|
||||
|
||||
void addConnection(int signal, Connection *c);
|
||||
void addConnection(int signal, Connection* c);
|
||||
void cleanConnectionLists();
|
||||
|
||||
static inline Sender *setCurrentSender(QObject *receiver,
|
||||
Sender *sender);
|
||||
static inline void resetCurrentSender(QObject *receiver,
|
||||
Sender *currentSender,
|
||||
Sender *previousSender);
|
||||
static inline Sender* setCurrentSender(QObject* receiver,
|
||||
Sender* sender);
|
||||
static inline void resetCurrentSender(QObject* receiver,
|
||||
Sender* currentSender,
|
||||
Sender* previousSender);
|
||||
|
||||
static QObjectPrivate *get(QObject *o) {
|
||||
static QObjectPrivate* get(QObject* o) {
|
||||
return o->d_func();
|
||||
}
|
||||
|
||||
int signalIndex(const char *signalName, const QMetaObject **meta = 0) const;
|
||||
int signalIndex(const char* signalName, const QMetaObject** meta = 0) const;
|
||||
inline bool isSignalConnected(uint signalIdx) const;
|
||||
|
||||
// To allow abitrary objects to call connectNotify()/disconnectNotify() without making
|
||||
// the API public in QObject. This is used by QQmlNotifierEndpoint.
|
||||
inline void connectNotify(const QMetaMethod &signal);
|
||||
inline void disconnectNotify(const QMetaMethod &signal);
|
||||
inline void connectNotify(const QMetaMethod& signal);
|
||||
inline void disconnectNotify(const QMetaMethod& signal);
|
||||
|
||||
template <typename Func1, typename Func2>
|
||||
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
|
||||
Qt::ConnectionType type = Qt::AutoConnection);
|
||||
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object* receiverPrivate, Func2 slot,
|
||||
Qt::ConnectionType type = Qt::AutoConnection);
|
||||
|
||||
template <typename Func1, typename Func2>
|
||||
static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
|
||||
static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object* receiverPrivate, Func2 slot);
|
||||
|
||||
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
|
||||
const QObject *receiver, void **slot,
|
||||
QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
|
||||
const int *types, const QMetaObject *senderMetaObject);
|
||||
static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
|
||||
static bool disconnect(const QObject *sender, int signal_index, void **slot);
|
||||
static QMetaObject::Connection connectImpl(const QObject* sender, int signal_index,
|
||||
const QObject* receiver, void** slot,
|
||||
QtPrivate::QSlotObjectBase* slotObj, Qt::ConnectionType type,
|
||||
const int* types, const QMetaObject* senderMetaObject);
|
||||
static QMetaObject::Connection connect(const QObject* sender, int signal_index, QtPrivate::QSlotObjectBase* slotObj, Qt::ConnectionType type);
|
||||
static bool disconnect(const QObject* sender, int signal_index, void** slot);
|
||||
public:
|
||||
ExtraData *extraData; // extra data set by the user
|
||||
QThreadData *threadData; // id of the thread that owns the object
|
||||
ExtraData* extraData; // extra data set by the user
|
||||
QThreadData* threadData; // id of the thread that owns the object
|
||||
|
||||
QObjectConnectionListVector *connectionLists;
|
||||
QObjectConnectionListVector* connectionLists;
|
||||
|
||||
Connection *senders; // linked list of connections connected to this object
|
||||
Sender *currentSender; // object currently activating the object
|
||||
Connection* senders; // linked list of connections connected to this object
|
||||
Sender* currentSender; // object currently activating the object
|
||||
mutable quint32 connectedSignals[2];
|
||||
|
||||
union {
|
||||
QObject *currentChildBeingDeleted;
|
||||
QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
|
||||
QObject* currentChildBeingDeleted;
|
||||
QAbstractDeclarativeData* declarativeData; //extra data used by the declarative module
|
||||
};
|
||||
|
||||
// these objects are all used to indicate that a QObject was deleted
|
||||
|
@ -254,22 +260,22 @@ public:
|
|||
inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
|
||||
{
|
||||
return signal_index >= sizeof(connectedSignals) * 8
|
||||
|| (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
|
||||
|| (declarativeData && QAbstractDeclarativeData::isSignalConnected
|
||||
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index)));
|
||||
|| (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
|
||||
|| (declarativeData && QAbstractDeclarativeData::isSignalConnected
|
||||
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index)));
|
||||
}
|
||||
|
||||
inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
|
||||
Sender *sender)
|
||||
inline QObjectPrivate::Sender* QObjectPrivate::setCurrentSender(QObject* receiver,
|
||||
Sender* sender)
|
||||
{
|
||||
Sender *previousSender = receiver->d_func()->currentSender;
|
||||
Sender* previousSender = receiver->d_func()->currentSender;
|
||||
receiver->d_func()->currentSender = sender;
|
||||
return previousSender;
|
||||
}
|
||||
|
||||
inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
|
||||
Sender *currentSender,
|
||||
Sender *previousSender)
|
||||
inline void QObjectPrivate::resetCurrentSender(QObject* receiver,
|
||||
Sender* currentSender,
|
||||
Sender* previousSender)
|
||||
{
|
||||
// ref is set to zero when this object is deleted during the metacall
|
||||
if (currentSender->ref == 1)
|
||||
|
@ -279,46 +285,47 @@ inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
|
|||
previousSender->ref = currentSender->ref;
|
||||
}
|
||||
|
||||
inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
|
||||
inline void QObjectPrivate::connectNotify(const QMetaMethod& signal)
|
||||
{
|
||||
q_ptr->connectNotify(signal);
|
||||
}
|
||||
|
||||
inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
|
||||
inline void QObjectPrivate::disconnectNotify(const QMetaMethod& signal)
|
||||
{
|
||||
q_ptr->disconnectNotify(signal);
|
||||
}
|
||||
|
||||
namespace QtPrivate {
|
||||
template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase
|
||||
{
|
||||
typedef QtPrivate::FunctionPointer<Func> FuncType;
|
||||
Func function;
|
||||
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
|
||||
template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase
|
||||
{
|
||||
switch (which) {
|
||||
typedef QtPrivate::FunctionPointer<Func> FuncType;
|
||||
Func function;
|
||||
static void impl(int which, QSlotObjectBase* this_, QObject* r, void** a, bool* ret)
|
||||
{
|
||||
switch (which) {
|
||||
case Destroy:
|
||||
delete static_cast<QPrivateSlotObject*>(this_);
|
||||
break;
|
||||
case Call:
|
||||
FuncType::template call<Args, R>(static_cast<QPrivateSlotObject*>(this_)->function,
|
||||
static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
|
||||
static_cast<typename FuncType::Object*>(QObjectPrivate::get(r)), a);
|
||||
break;
|
||||
case Compare:
|
||||
*ret = *reinterpret_cast<Func *>(a) == static_cast<QPrivateSlotObject*>(this_)->function;
|
||||
*ret = *reinterpret_cast<Func*>(a) == static_cast<QPrivateSlotObject*>(this_)->function;
|
||||
break;
|
||||
case NumOperations: ;
|
||||
case NumOperations:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
|
||||
};
|
||||
public:
|
||||
explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
|
||||
};
|
||||
} //namespace QtPrivate
|
||||
|
||||
template <typename Func1, typename Func2>
|
||||
inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
|
||||
Qt::ConnectionType type)
|
||||
inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object* receiverPrivate, Func2 slot,
|
||||
Qt::ConnectionType type)
|
||||
{
|
||||
typedef QtPrivate::FunctionPointer<Func1> SignalType;
|
||||
typedef QtPrivate::FunctionPointer<Func2> SlotType;
|
||||
|
@ -333,15 +340,15 @@ inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate:
|
|||
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
|
||||
"Return type of the slot is not compatible with the return type of the signal.");
|
||||
|
||||
const int *types = 0;
|
||||
const int* types = 0;
|
||||
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
|
||||
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
|
||||
|
||||
return QObject::connectImpl(sender, reinterpret_cast<void **>(&signal),
|
||||
receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
|
||||
new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
||||
typename SignalType::ReturnType>(slot),
|
||||
type, types, &SignalType::Object::staticMetaObject);
|
||||
return QObject::connectImpl(sender, reinterpret_cast<void**>(&signal),
|
||||
receiverPrivate->q_ptr, reinterpret_cast<void**>(&slot),
|
||||
new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
||||
typename SignalType::ReturnType>(slot),
|
||||
type, types, &SignalType::Object::staticMetaObject);
|
||||
}
|
||||
|
||||
template <typename Func1, typename Func2>
|
||||
|
@ -355,9 +362,9 @@ bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1
|
|||
//compilation error if the arguments does not match.
|
||||
Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
|
||||
"Signal and slot arguments are not compatible.");
|
||||
return QObject::disconnectImpl(sender, reinterpret_cast<void **>(&signal),
|
||||
receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
|
||||
&SignalType::Object::staticMetaObject);
|
||||
return QObject::disconnectImpl(sender, reinterpret_cast<void**>(&signal),
|
||||
receiverPrivate->q_ptr, reinterpret_cast<void**>(&slot),
|
||||
&SignalType::Object::staticMetaObject);
|
||||
}
|
||||
|
||||
Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
|
||||
|
@ -367,31 +374,39 @@ class QSemaphore;
|
|||
class Q_CORE_EXPORT QMetaCallEvent : public QEvent
|
||||
{
|
||||
public:
|
||||
QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
|
||||
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
|
||||
QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject* sender, int signalId,
|
||||
int nargs = 0, int* types = 0, void** args = 0, QSemaphore* semaphore = 0);
|
||||
/*! \internal
|
||||
\a signalId is in the signal index range (see QObjectPrivate::signalIndex()).
|
||||
*/
|
||||
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId,
|
||||
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
|
||||
QMetaCallEvent(QtPrivate::QSlotObjectBase* slotObj, const QObject* sender, int signalId,
|
||||
int nargs = 0, int* types = 0, void** args = 0, QSemaphore* semaphore = 0);
|
||||
|
||||
~QMetaCallEvent();
|
||||
|
||||
inline int id() const { return method_offset_ + method_relative_; }
|
||||
inline const QObject *sender() const { return sender_; }
|
||||
inline int signalId() const { return signalId_; }
|
||||
inline void **args() const { return args_; }
|
||||
inline int id() const {
|
||||
return method_offset_ + method_relative_;
|
||||
}
|
||||
inline const QObject* sender() const {
|
||||
return sender_;
|
||||
}
|
||||
inline int signalId() const {
|
||||
return signalId_;
|
||||
}
|
||||
inline void** args() const {
|
||||
return args_;
|
||||
}
|
||||
|
||||
virtual void placeMetaCall(QObject *object);
|
||||
virtual void placeMetaCall(QObject* object);
|
||||
|
||||
private:
|
||||
QtPrivate::QSlotObjectBase *slotObj_;
|
||||
const QObject *sender_;
|
||||
QtPrivate::QSlotObjectBase* slotObj_;
|
||||
const QObject* sender_;
|
||||
int signalId_;
|
||||
int nargs_;
|
||||
int *types_;
|
||||
void **args_;
|
||||
QSemaphore *semaphore_;
|
||||
int* types_;
|
||||
void** args_;
|
||||
QSemaphore* semaphore_;
|
||||
QObjectPrivate::StaticMetaCallFunction callFunction_;
|
||||
ushort method_offset_;
|
||||
ushort method_relative_;
|
||||
|
@ -401,32 +416,46 @@ class QBoolBlocker
|
|||
{
|
||||
Q_DISABLE_COPY(QBoolBlocker)
|
||||
public:
|
||||
explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
|
||||
inline ~QBoolBlocker(){block = reset; }
|
||||
explicit inline QBoolBlocker(bool& b, bool value = true): block(b), reset(b) {
|
||||
block = value;
|
||||
}
|
||||
inline ~QBoolBlocker() {
|
||||
block = reset;
|
||||
}
|
||||
private:
|
||||
bool █
|
||||
bool& block;
|
||||
bool reset;
|
||||
};
|
||||
|
||||
void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
|
||||
void Q_CORE_EXPORT qDeleteInEventHandler(QObject* o);
|
||||
|
||||
struct QAbstractDynamicMetaObject;
|
||||
struct Q_CORE_EXPORT QDynamicMetaObjectData
|
||||
{
|
||||
virtual ~QDynamicMetaObjectData() {}
|
||||
virtual void objectDestroyed(QObject *) { delete this; }
|
||||
virtual void objectDestroyed(QObject*) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0;
|
||||
virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;
|
||||
virtual QAbstractDynamicMetaObject* toDynamicMetaObject(QObject*) = 0;
|
||||
virtual int metaCall(QObject*, QMetaObject::Call, int _id, void**) = 0;
|
||||
};
|
||||
|
||||
struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject
|
||||
{
|
||||
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) { return this; }
|
||||
virtual int createProperty(const char *, const char *) { return -1; }
|
||||
virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a)
|
||||
{ return metaCall(c, _id, a); }
|
||||
virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
|
||||
virtual QAbstractDynamicMetaObject* toDynamicMetaObject(QObject*) {
|
||||
return this;
|
||||
}
|
||||
virtual int createProperty(const char*, const char*) {
|
||||
return -1;
|
||||
}
|
||||
virtual int metaCall(QObject*, QMetaObject::Call c, int _id, void** a)
|
||||
{
|
||||
return metaCall(c, _id, a);
|
||||
}
|
||||
virtual int metaCall(QMetaObject::Call, int _id, void**) {
|
||||
return _id; // Compat overload
|
||||
}
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -29,11 +29,5 @@ QtObject:
|
|||
method onExitTriggered(self: ApplicationLogic) {.slot.} =
|
||||
self.app.quit
|
||||
|
||||
method addContact(self: ApplicationLogic, name: string, surname: string) {.slot.} =
|
||||
self.contactList.add(name, surname)
|
||||
|
||||
method delContact(self: ApplicationLogic, index: int) {.slot.} =
|
||||
self.contactList.del(index)
|
||||
|
||||
QtProperty[QVariant] contactList:
|
||||
read = getContactList
|
||||
|
|
|
@ -1,73 +1,62 @@
|
|||
import NimQml, NimQmlMacros, Contact, Tables
|
||||
|
||||
type
|
||||
ContactList* = ref object of QAbstractListModel
|
||||
contacts*: seq[Contact]
|
||||
ContactRoles = enum
|
||||
FirstNameRole = 0
|
||||
SurnameRole = 1
|
||||
QtObject:
|
||||
type
|
||||
ContactList* = ref object of QAbstractListModel
|
||||
contacts*: seq[Contact]
|
||||
ContactRoles = enum
|
||||
FirstNameRole = 0
|
||||
SurnameRole = 1
|
||||
|
||||
converter toCInt(value: ContactRoles): cint = return value.cint
|
||||
converter toCInt(value: int): cint = return value.cint
|
||||
converter toInt(value: ContactRoles): int = return value.int
|
||||
converter toInt(value: cint): int = return value.int
|
||||
converter toQVariant(value: string): QVariant = return value.newQVariant
|
||||
converter toCInt(value: ContactRoles): cint = return value.cint
|
||||
converter toCInt(value: int): cint = return value.cint
|
||||
converter toInt(value: ContactRoles): int = return value.int
|
||||
converter toInt(value: cint): int = return value.int
|
||||
converter toQVariant(value: string): QVariant = return value.newQVariant
|
||||
|
||||
proc create(self: ContactList) =
|
||||
var model = self.QAbstractListModel
|
||||
model.create
|
||||
self.contacts = @[]
|
||||
|
||||
proc delete(self: ContactList) =
|
||||
let model = self.QAbstractListModel
|
||||
model.delete
|
||||
for contact in self.contacts:
|
||||
contact.delete
|
||||
self.contacts = @[]
|
||||
proc delete(self: ContactList) =
|
||||
let model = self.QAbstractListModel
|
||||
model.delete
|
||||
for contact in self.contacts:
|
||||
contact.delete
|
||||
self.contacts = @[]
|
||||
|
||||
proc newContactList*(): ContactList =
|
||||
new(result, delete)
|
||||
result.create()
|
||||
proc newContactList*(): ContactList =
|
||||
new(result, delete)
|
||||
result.contacts = @[]
|
||||
result.create
|
||||
|
||||
proc isRowValid(self: ContactList, row: cint): bool =
|
||||
return row >= 0 and row < self.contacts.len
|
||||
|
||||
method rowCount(self: ContactList, index: QModelIndex = nil): cint =
|
||||
return self.contacts.len
|
||||
method rowCount(self: ContactList, index: QModelIndex = nil): cint =
|
||||
return self.contacts.len
|
||||
|
||||
method data(self: ContactList, index: QModelIndex, role: cint): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if not self.isRowValid(index.row):
|
||||
return
|
||||
if role == FirstNameRole:
|
||||
return self.contacts[index.row].firstName
|
||||
elif role == SurnameRole:
|
||||
return self.contacts[index.row].surname
|
||||
else:
|
||||
return
|
||||
method data(self: ContactList, index: QModelIndex, role: cint): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.contacts.len:
|
||||
return
|
||||
if role == FirstNameRole:
|
||||
return self.contacts[index.row].firstName
|
||||
elif role == SurnameRole:
|
||||
return self.contacts[index.row].surname
|
||||
else:
|
||||
return
|
||||
|
||||
method roleNames(self: ContactList): Table[cint, cstring] =
|
||||
result = initTable[cint, cstring]()
|
||||
result[FirstNameRole] = "firstName"
|
||||
result[SurnameRole] = "surname"
|
||||
method roleNames(self: ContactList): Table[cint, cstring] =
|
||||
result = initTable[cint, cstring]()
|
||||
result[FirstNameRole] = "firstName"
|
||||
result[SurnameRole] = "surname"
|
||||
|
||||
method add*(self: ContactList, name: string, surname: string) =
|
||||
let contact = newContact()
|
||||
contact.firstName = name
|
||||
contact.surname = surname
|
||||
self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len)
|
||||
self.contacts.add(contact)
|
||||
self.endInsertRows()
|
||||
method add*(self: ContactList, name: string, surname: string) {.slot.} =
|
||||
let contact = newContact()
|
||||
contact.firstName = name
|
||||
contact.surname = surname
|
||||
self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len)
|
||||
self.contacts.add(contact)
|
||||
self.endInsertRows()
|
||||
|
||||
method get*(self: ContactList, pos: int): QObject =
|
||||
if not self.isRowValid(pos):
|
||||
return nil
|
||||
result = self.contacts[pos].QObject
|
||||
|
||||
method del*(self: ContactList, pos: int) =
|
||||
if not self.isRowValid(pos):
|
||||
return
|
||||
self.beginRemoveRows(newQModelIndex(), pos, pos)
|
||||
self.contacts.del(pos)
|
||||
self.endRemoveRows
|
||||
method del*(self: ContactList, pos: int) {.slot.} =
|
||||
if pos < 0 or pos >= self.contacts.len:
|
||||
return
|
||||
self.beginRemoveRows(newQModelIndex(), pos, pos)
|
||||
self.contacts.del(pos)
|
||||
self.endRemoveRows
|
||||
|
|
|
@ -3,16 +3,15 @@ import QtQuick.Controls 1.2
|
|||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.1
|
||||
|
||||
ApplicationWindow
|
||||
{
|
||||
ApplicationWindow {
|
||||
|
||||
width: 400
|
||||
height: 300
|
||||
title: "ContactApp"
|
||||
visible: true
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu
|
||||
{
|
||||
Menu {
|
||||
title: "&File"
|
||||
MenuItem { text: "&Load"; onTriggered: logic.onLoadTriggered() }
|
||||
MenuItem { text: "&Save"; onTriggered: logic.onSaveTriggered() }
|
||||
|
@ -20,35 +19,31 @@ ApplicationWindow
|
|||
}
|
||||
}
|
||||
|
||||
ColumnLayout
|
||||
{
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ScrollView
|
||||
{
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ListView
|
||||
{
|
||||
ListView {
|
||||
model: logic.contactList
|
||||
spacing: 5
|
||||
delegate: RowLayout {
|
||||
width: ListView.view.width
|
||||
TextField { Layout.fillWidth: true; text: firstName }
|
||||
TextField { Layout.fillWidth: true; text: surname }
|
||||
Button { text: "Delete"; onClicked: logic.delContact(index) }
|
||||
Button { text: "Delete"; onClicked: logic.contactList.del(index) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout
|
||||
{
|
||||
RowLayout {
|
||||
Label { text: "Name" }
|
||||
TextField { id: nameTextField; Layout.fillWidth: true; text: "" }
|
||||
Label { text: "Surname" }
|
||||
TextField { id: surnameTextField; Layout.fillWidth: true; text: "" }
|
||||
Button { text: "Add"; onClicked: logic.addContact(nameTextField.text, surnameTextField.text) }
|
||||
Button { text: "Add"; onClicked: logic.contactList.add(nameTextField.text, surnameTextField.text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {.
|
|||
proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_create_float(variant: var RawQVariant, value: cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_create_double(variant: var RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_create_qabstractlistmodel(variant: var RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
@ -93,7 +92,6 @@ proc dos_qvariant_setFloat(variant: RawQVariant, value: float) {.cdecl, dynlib:
|
|||
proc dos_qvariant_toDouble(variant: RawQVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_setDouble(variant: RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_setQObject(variant: RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qvariant_setQAbstractListModel(variant: RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc create*(variant: QVariant) =
|
||||
|
@ -118,14 +116,9 @@ proc create*(variant: QVariant, value: string) =
|
|||
|
||||
proc create*(variant: QVariant, value: QObject) =
|
||||
## Create a new QVariant given a QObject
|
||||
dos_qvariant_create_qobject(variant.data, value.data)
|
||||
dos_qvariant_create_qobject(variant.data, value.data.RawQObject)
|
||||
variant.deleted = false
|
||||
|
||||
proc create*(variant: QVariant, value: QAbstractListModel) =
|
||||
## Create a new QVariant given a QAbstractListModel
|
||||
dos_qvariant_create_qabstractlistmodel(variant.data, value.data)
|
||||
variant.deleted = false
|
||||
|
||||
proc create*(variant: QVariant, value: RawQVariant) =
|
||||
## Create a new QVariant given another QVariant.
|
||||
## The inner value of the QVariant is copied
|
||||
|
@ -175,11 +168,6 @@ proc newQVariant*(value: QObject): QVariant =
|
|||
newWithCondFinalizer(result, delete)
|
||||
result.create(value)
|
||||
|
||||
proc newQVariant*(value: QAbstractListModel): QVariant =
|
||||
## Return a new QVariant given a QAbstractListModel
|
||||
newWithCondFinalizer(result, delete)
|
||||
result.create(value)
|
||||
|
||||
proc newQVariant*(value: RawQVariant): QVariant =
|
||||
## Return a new QVariant given a raw QVariant pointer
|
||||
newWithCondFinalizer(result, delete)
|
||||
|
@ -252,11 +240,7 @@ proc `stringVal=`*(variant: QVariant, value: string) =
|
|||
|
||||
proc `qobjectVal=`*(variant: QVariant, value: QObject) =
|
||||
## Sets the QVariant qobject value
|
||||
dos_qvariant_setQObject(variant.data, value.data)
|
||||
|
||||
proc `qabstractListModelVal=`*(variant: QVariant, value: QAbstractListModel) =
|
||||
## Sets the QVariant qabstractlistmodel value
|
||||
dos_qvariant_setQAbstractListModel(variant.data, value.data)
|
||||
dos_qvariant_setQObject(variant.data, value.data.RawQObject)
|
||||
|
||||
proc assign*(leftValue: QVariant, rightValue: QVariant) =
|
||||
## Assign a QVariant with another. The inner value of the QVariant is copied
|
||||
|
@ -636,6 +620,7 @@ type RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: Ra
|
|||
|
||||
proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel,
|
||||
modelPtr: ptr QAbstractListModelObj,
|
||||
qobjectCallback: QObjectCallBack,
|
||||
rowCountCallback: RowCountCallback,
|
||||
dataCallback: DataCallback,
|
||||
roleNamesCallback: RoleNamesCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
@ -691,18 +676,24 @@ proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashInt
|
|||
proc create*(model: var QAbstractListModel) =
|
||||
## Create a new QAbstractListModel
|
||||
debugMsg("QAbstractListModel", "create")
|
||||
let modelPtr = addr(model[])
|
||||
dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback, dataCallback, roleNamesCallback)
|
||||
model.slots = initTable[string,cint]()
|
||||
model.signals = initTable[string, cint]()
|
||||
model.properties = initTable[string, cint]()
|
||||
model.deleted = false
|
||||
let modelPtr = addr(model[])
|
||||
dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, dataCallback, roleNamesCallback)
|
||||
qobjectRegistry[modelPtr] = true
|
||||
|
||||
proc delete*(model: QAbstractListModel) =
|
||||
## Delete the given QAbstractListModel
|
||||
if not model.deleted:
|
||||
debugMsg("QAbstractListModel", "delete")
|
||||
dos_qabstractlistmodel_delete(model.data)
|
||||
model.data = nil.RawQAbstractListModel
|
||||
let modelPtr = addr(model[])
|
||||
qobjectRegistry.del modelPtr
|
||||
dos_qabstractlistmodel_delete(model.data.RawQAbstractListModel)
|
||||
model.data = nil.RawQObject
|
||||
model.deleted = true
|
||||
|
||||
|
||||
proc newQAbstractListModel*(): QAbstractListModel =
|
||||
## Return a new QAbstractListModel
|
||||
newWithCondFinalizer(result, delete)
|
||||
|
@ -710,32 +701,32 @@ proc newQAbstractListModel*(): QAbstractListModel =
|
|||
|
||||
proc beginInsertRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) =
|
||||
## Notify the view that the model is about to inserting the given number of rows
|
||||
dos_qabstractlistmodel_beginInsertRows(model.data, parentIndex.data, first.cint, last.cint)
|
||||
dos_qabstractlistmodel_beginInsertRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint)
|
||||
|
||||
proc endInsertRows*(model: QAbstractListModel) =
|
||||
## Notify the view that the rows have been inserted
|
||||
dos_qabstractlistmodel_endInsertRows(model.data)
|
||||
dos_qabstractlistmodel_endInsertRows(model.data.RawQAbstractListModel)
|
||||
|
||||
proc beginRemoveRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) =
|
||||
## Notify the view that the model is about to remove the given number of rows
|
||||
dos_qabstractlistmodel_beginRemoveRows(model.data, parentIndex.data, first.cint, last.cint)
|
||||
dos_qabstractlistmodel_beginRemoveRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint)
|
||||
|
||||
proc endRemoveRows*(model: QAbstractListModel) =
|
||||
## Notify the view that the rows have been removed
|
||||
dos_qabstractlistmodel_endRemoveRows(model.data)
|
||||
dos_qabstractlistmodel_endRemoveRows(model.data.RawQAbstractListModel)
|
||||
|
||||
proc beginResetModel*(model: QAbstractListModel) =
|
||||
## Notify the view that the model is about to resetting
|
||||
dos_qabstractlistmodel_beginResetModel(model.data)
|
||||
dos_qabstractlistmodel_beginResetModel(model.data.RawQAbstractListModel)
|
||||
|
||||
proc endResetModel*(model: QAbstractListModel) =
|
||||
## Notify the view that model has finished resetting
|
||||
dos_qabstractlistmodel_endResetModel(model.data)
|
||||
dos_qabstractlistmodel_endResetModel(model.data.RawQAbstractListModel)
|
||||
|
||||
proc dataChanged*(model: QAbstractListModel,
|
||||
topLeft: QModelIndex,
|
||||
bottomRight: QModelIndex,
|
||||
roles: seq[cint]) =
|
||||
roles: var seq[cint]) =
|
||||
## Notify the view that the model data changed
|
||||
var temp = roles
|
||||
dos_qabstractlistmodel_dataChanged(model.data, topLeft.data, bottomRight.data, temp[0].addr, temp.len.cint)
|
||||
dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, roles[0].addr, roles.len.cint)
|
||||
|
||||
|
|
|
@ -24,8 +24,16 @@ type
|
|||
signals: Table[string, cint]
|
||||
properties: Table[string, cint]
|
||||
deleted: bool
|
||||
QObject* = ref QObjectObj ## A QObject
|
||||
QObject* = ref QObjectObj
|
||||
|
||||
RawBaseQObjectObj = distinct pointer
|
||||
BaseQObjectObj = object of QObjectObj
|
||||
BaseQObject* = ref BaseQObjectObj ## A QObject
|
||||
|
||||
RawQAbstractListModel = distinct pointer
|
||||
QAbstractListModelObj = object of QObjectObj
|
||||
QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel
|
||||
|
||||
RawQQuickView = distinct pointer
|
||||
QQuickView = ref object of RootObj ## A QQuickView
|
||||
data: RawQQuickView
|
||||
|
@ -38,12 +46,6 @@ type
|
|||
data: RawQModelIndex
|
||||
deleted: bool
|
||||
|
||||
RawQAbstractListModel = distinct pointer
|
||||
QAbstractListModelObj = object of RootObj
|
||||
data: RawQAbstractListModel
|
||||
deleted: bool
|
||||
QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel
|
||||
|
||||
RawQHashIntByteArray = distinct pointer
|
||||
QHashIntByteArrayObj = object of RootObj
|
||||
data: RawQHashIntByteArray
|
||||
|
|
Loading…
Reference in New Issue