Merge remote-tracking branch 'origin/feature/QAbstractItemModels' into develop

This commit is contained in:
Filippo Cucchetto 2015-02-15 14:16:15 +01:00
commit a91b4f59e7
30 changed files with 2183 additions and 1115 deletions

3
.gitignore vendored
View File

@ -4,4 +4,5 @@ build
*.o
.directory
#*#
nimcache
nimcache
*.kdev4

View File

@ -1,3 +1,3 @@
add_subdirectory(DOtherSide)
add_subdirectory(DynamicQObject)
add_subdirectory(IntegrationTest)
#add_subdirectory(DynamicQObject)
#add_subdirectory(IntegrationTest)

View File

@ -0,0 +1,202 @@
#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 DynamicQObject<QAbstractListModel>
{
public:
/// Constructor
BaseQAbstractListModel(void* modelObject,
RowCountCallback rowCountCallback,
ColumnCountCallback columnCountCallback,
DataCallback dataCallback,
SetDataCallback setDataCallback,
RoleNamesCallback roleNamesCallback,
FlagsCallback flagsCallback,
HeaderDataCallback headerDataCallback);
/// Return the model's row count
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
/// Return the model's column count
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
/// Return the QVariant at the given index
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
/// Sets the QVariant value at the given index and role
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
/// Return the item flags for the given index
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
/// Return the data for the given role and section in the header with the specified orientation
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
/// Return the dModelPointer
void* modelObject();
/// Return the roleNames
virtual QHash<int, QByteArray> roleNames() const override;
/// 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,
const QVector<int>& roles = QVector<int>());
private:
void* m_modelObject;
RowCountCallback m_rowCountCallback;
ColumnCountCallback m_columnCountCallback;
DataCallback m_dataCallback;
SetDataCallback m_setDataCallback;
RoleNamesCallback m_roleNamesCallback;
FlagsCallback m_flagsCallback;
HeaderDataCallback m_headerDataCallback;
};
BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject,
RowCountCallback rowCountCallback,
ColumnCountCallback columnCountCallback,
DataCallback dataCallback,
SetDataCallback setDataCallback,
RoleNamesCallback roleNamesCallback,
FlagsCallback flagsCallback,
HeaderDataCallback headerDataCallback)
: m_modelObject(modelObject)
, m_rowCountCallback(rowCountCallback)
, m_columnCountCallback(columnCountCallback)
, m_dataCallback(dataCallback)
, m_setDataCallback(setDataCallback)
, m_roleNamesCallback(roleNamesCallback)
, m_flagsCallback(flagsCallback)
, m_headerDataCallback(headerDataCallback)
{
}
int BaseQAbstractListModel::rowCount(const QModelIndex& parent) const
{
auto parentIndex = new QModelIndex();
*parentIndex = parent;
int result;
m_rowCountCallback(m_modelObject, parentIndex, &result);
return result;
}
int BaseQAbstractListModel::columnCount(const QModelIndex& parent) const
{
auto parentIndex = new QModelIndex();
*parentIndex = parent;
int result;
m_columnCountCallback(m_modelObject, parentIndex, &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;
}
bool BaseQAbstractListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
auto newIndex = new QModelIndex(index);
*newIndex = index;
auto newValue = new QVariant();
*newValue = value;
bool result = false;
m_setDataCallback(m_modelObject, newIndex, newValue, role, &result);
return result;
}
Qt::ItemFlags BaseQAbstractListModel::flags(const QModelIndex& index) const
{
auto newIndex = new QModelIndex(index);
*newIndex = index;
int result;
m_flagsCallback(m_modelObject, newIndex, &result);
return Qt::ItemFlags(result);
}
QVariant BaseQAbstractListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant result;
m_headerDataCallback(m_modelObject, section, orientation, 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

View File

@ -0,0 +1,8 @@
#ifndef BASEQOBJECT_H
#define BASEQOBJECT_H
#include "DynamicQObject.h"
class BaseQObject : public DynamicQObject<QObject> {};
#endif

View File

@ -12,6 +12,9 @@ find_package(Qt5Widgets)
set(HEADERS_LIST
DOtherSide.h
DOtherSideTypes.h
BaseQAbstractListModel.h
BaseQObject.h
)
set(SRC_LIST
@ -19,5 +22,5 @@ set(SRC_LIST
)
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)

View File

@ -1,20 +1,25 @@
#include "DOtherSide.h"
#include <QtWidgets/QApplication>
#include <QtGui/QGuiApplication>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlContext>
#include <iostream>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QModelIndex>
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlContext>
#include <QtQml/QQmlApplicationEngine>
#include <QtQuick/QQuickView>
#include <QtWidgets/QApplication>
#include "DynamicQObject.h"
#include "BaseQAbstractListModel.h"
#include "BaseQObject.h"
void convert_to_cstring(const QString& source, CharPtr& destination, int& length)
void convert_to_cstring(const QString& source, char** destination, int* length)
{
QByteArray array = source.toUtf8();
destination = qstrdup(array.data());
length = qstrlen(array.data());
*destination = qstrdup(array.data());
*length = qstrlen(array.data());
}
void dos_qguiapplication_create()
@ -63,12 +68,12 @@ void dos_qapplication_quit()
qApp->quit();
}
void dos_qqmlapplicationengine_create(void **vptr)
void dos_qqmlapplicationengine_create(void** vptr)
{
*vptr = new QQmlApplicationEngine();
}
void dos_qqmlapplicationengine_load(void *vptr, const char *filename)
void dos_qqmlapplicationengine_load(void* vptr, const char* filename)
{
QQmlApplicationEngine* engine = reinterpret_cast<QQmlApplicationEngine*>(vptr);
engine->load(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QDir::separator() + QString(filename)));
@ -104,7 +109,7 @@ void dos_qquickview_delete(void* vptr)
delete view;
}
void dos_qquickview_source(void *vptr, CharPtr& result, int& length)
void dos_qquickview_source(void* vptr, char** result, int* length)
{
QQuickView* view = reinterpret_cast<QQuickView*>(vptr);
QUrl url = view->source();
@ -123,25 +128,25 @@ void dos_qquickview_rootContext(void* vptr, void** context)
*context = view->rootContext();
}
void dos_chararray_create(CharPtr& ptr)
void dos_chararray_create(char** ptr)
{
ptr = 0;
*ptr = 0;
}
void dos_chararray_create(CharPtr& ptr, int size)
void dos_chararray_create(char** ptr, int size)
{
if (size > 0)
ptr = new char[size];
*ptr = new char[size];
else
ptr = 0;
*ptr = 0;
}
void dos_chararray_delete(CharPtr ptr)
void dos_chararray_delete(char* ptr)
{
if (ptr) delete[] ptr;
}
void dos_qqmlcontext_baseUrl(void* vptr, CharPtr& result, int& length)
void dos_qqmlcontext_baseUrl(void* vptr, char** result, int* length)
{
QQmlContext* context = reinterpret_cast<QQmlContext*>(vptr);
QUrl url = context->baseUrl();
@ -155,17 +160,17 @@ void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* valu
context->setContextProperty(QString::fromUtf8(name), *variant);
}
void dos_qvariant_create(void **vptr)
void dos_qvariant_create(void** vptr)
{
*vptr = new QVariant();
}
void dos_qvariant_create_int(void **vptr, int value)
void dos_qvariant_create_int(void** vptr, int value)
{
*vptr = new QVariant(value);
}
void dos_qvariant_create_bool(void **vptr, bool value)
void dos_qvariant_create_bool(void** vptr, bool value)
{
*vptr = new QVariant(value);
}
@ -177,13 +182,13 @@ void dos_qvariant_create_string(void** vptr, const char* value)
void dos_qvariant_create_qvariant(void** vptr, void* other)
{
auto newQVariant = new QVariant();
auto otherQVariant = reinterpret_cast<QVariant*>(other);
*newQVariant = *otherQVariant;
*vptr = newQVariant;
auto newQVariant = new QVariant();
auto otherQVariant = reinterpret_cast<QVariant*>(other);
*newQVariant = *otherQVariant;
*vptr = newQVariant;
}
void dos_qvariant_create_qobject(void **vptr, void* value)
void dos_qvariant_create_qobject(void** vptr, void* value)
{
auto qobject = reinterpret_cast<QObject*>(value);
auto variant = new QVariant();
@ -201,13 +206,21 @@ void dos_qvariant_create_double(void** vptr, double value)
*vptr = new QVariant(value);
}
void dos_qvariant_isnull(void* vptr, bool& isNull)
void dos_qvariant_create_qabstractlistmodel(void** vptr, void* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
isNull = variant->isNull();
auto qobject = reinterpret_cast<QObject*>(value);
auto variant = new QVariant();
variant->setValue<QObject*>(qobject);
*vptr = variant;
}
void dos_qvariant_delete(void *vptr)
void dos_qvariant_isnull(void* vptr, bool* isNull)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
*isNull = variant->isNull();
}
void dos_qvariant_delete(void* vptr)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
delete variant;
@ -215,36 +228,36 @@ void dos_qvariant_delete(void *vptr)
void dos_qvariant_assign(void* vptr, void* other)
{
auto leftQVariant = reinterpret_cast<QVariant*>(vptr);
auto rightQVariant = reinterpret_cast<QVariant*>(other);
*leftQVariant = *rightQVariant;
auto leftQVariant = reinterpret_cast<QVariant*>(vptr);
auto rightQVariant = reinterpret_cast<QVariant*>(other);
*leftQVariant = *rightQVariant;
}
void dos_qvariant_toInt(void* vptr, int& value)
void dos_qvariant_toInt(void* vptr, int* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
value = variant->toInt();
*value = variant->toInt();
}
void dos_qvariant_toBool(void* vptr, bool& value)
void dos_qvariant_toBool(void* vptr, bool* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
value = variant->toBool();
*value = variant->toBool();
}
void dos_qvariant_toFloat(void* vptr, float& value)
void dos_qvariant_toFloat(void* vptr, float* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
value = variant->toFloat();
auto variant = reinterpret_cast<QVariant*>(vptr);
*value = variant->toFloat();
}
void dos_qvariant_toDouble(void* vptr, double& value)
void dos_qvariant_toDouble(void* vptr, double* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
value = variant->toDouble();
auto variant = reinterpret_cast<QVariant*>(vptr);
*value = variant->toDouble();
}
void dos_qvariant_toString(void* vptr, CharPtr& ptr, int& size)
void dos_qvariant_toString(void* vptr, char** ptr, int* size)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
convert_to_cstring(variant->toString(), ptr, size);
@ -282,23 +295,30 @@ void dos_qvariant_setString(void* vptr, const char* value)
void dos_qvariant_setQObject(void* vptr, void* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
auto qobject = reinterpret_cast<QObject*>(value);
variant->setValue<QObject*>(qobject);
auto variant = reinterpret_cast<QVariant*>(vptr);
auto qobject = reinterpret_cast<QObject*>(value);
variant->setValue<QObject*>(qobject);
}
void dos_qvariant_setQAbstractListModel(void* vptr, void* value)
{
auto variant = reinterpret_cast<QVariant*>(vptr);
auto qobject = reinterpret_cast<QObject*>(value);
variant->setValue<QObject*>(qobject);
}
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);
*vptr = dynamicQObject;
}
void dos_qobject_delete(void *vptr)
void dos_qobject_delete(void* vptr)
{
auto dynamicQObject = reinterpret_cast<DynamicQObject*>(vptr);
auto dynamicQObject = reinterpret_cast<BaseQObject*>(vptr);
dynamicQObject->disconnect();
delete dynamicQObject;
}
@ -308,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;
@ -323,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)
@ -334,14 +356,16 @@ 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);
}
void dos_qobject_property_create(void* vptr,
const char* name,
int type,
@ -349,10 +373,175 @@ 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),
QString(writeSlot),
QString(notifySignal));
}
void dos_qmodelindex_create(void** vptr)
{
auto index = new QModelIndex();
*vptr = index;
}
void dos_qmodelindex_delete(void* vptr)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
delete index;
}
void dos_qmodelindex_row(void* vptr, int* row)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
*row = index->row();
}
void dos_qmodelindex_column(void* vptr, int* column)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
*column = index->column();
}
void dos_qmodelindex_isValid(void* vptr, bool* isValid)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
*isValid = index->isValid();
}
void dos_qmodelindex_data(void* vptr, int role, void* data)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
auto result = reinterpret_cast<QVariant*>(data);
*result = index->data(role);
}
void dos_qmodelindex_parent(void* vptr, void* parent)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
auto parentIndex = reinterpret_cast<QModelIndex*>(parent);
*parentIndex = index->parent();
}
void dos_qmodelindex_child(void* vptr, int row, int column, void* child)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
auto childIndex = reinterpret_cast<QModelIndex*>(child);
*childIndex = index->child(row, column);
}
void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling)
{
auto index = reinterpret_cast<QModelIndex*>(vptr);
auto siblingIndex = reinterpret_cast<QModelIndex*>(sibling);
*siblingIndex = index->sibling(row, column);
}
void dos_qabstractlistmodel_create(void** vptr,
void* modelObject,
DObjectCallback dObjectCallback,
RowCountCallback rowCountCallback,
ColumnCountCallback columnCountCallback,
DataCallback dataCallback,
SetDataCallback setDataCallback,
RoleNamesCallback roleNamesCallaback,
FlagsCallback flagsCallback,
HeaderDataCallback headerDataCallback)
{
auto model = new BaseQAbstractListModel(modelObject,
rowCountCallback,
columnCountCallback,
dataCallback,
setDataCallback,
roleNamesCallaback,
flagsCallback,
headerDataCallback);
model->setDObjectPointer(modelObject);
model->setDObjectCallback(dObjectCallback);
*vptr = model;
}
void dos_qabstractlistmodel_delete(void* vptr)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
delete model;
}
void dos_qabstractlistmodel_beginInsertRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
auto index = reinterpret_cast<QModelIndex*>(parentIndex);
model->publicBeginInsertRows(*index, first, last);
}
void dos_qabstractlistmodel_endInsertRows(void* vptr)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
model->publicEndInsertRows();
}
void dos_qabstractlistmodel_beginRemoveRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
auto index = reinterpret_cast<QModelIndex*>(parentIndex);
model->publicBeginRemoveRows(*index, first, last);
}
void dos_qabstractlistmodel_endRemoveRows(void* vptr)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
model->publicEndRemoveRows();
}
void dos_qabstractlistmodel_beginResetModel(void* vptr)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
model->publicBeginResetModel();
}
void dos_qabstractlistmodel_endResetModel(void* vptr)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
model->publicEndResetModel();
}
void dos_qabstractlistmodel_dataChanged(void* vptr,
QModelIndexVoidPtr topLeftIndex,
QModelIndexVoidPtr bottomRightIndex,
int* rolesArrayPtr,
int rolesArrayLength)
{
auto model = reinterpret_cast<BaseQAbstractListModel*>(vptr);
auto topLeft = reinterpret_cast<QModelIndex*>(topLeftIndex);
auto bottomRight = reinterpret_cast<QModelIndex*>(bottomRightIndex);
auto roles = QVector<int>::fromStdVector(std::vector<int>(rolesArrayPtr, rolesArrayPtr + rolesArrayLength));
model->publicDataChanged(*topLeft, *bottomRight, roles);
}
void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr)
{
*vptr = new QHash<int, QByteArray>();
}
void dos_qhash_int_qbytearray_delete(QHashIntQByteArrayVoidPtr vptr)
{
auto qHash = reinterpret_cast<QHash<int, QByteArray>*>(vptr);
delete qHash;
}
void dos_qhash_int_qbytearray_insert(QHashIntQByteArrayVoidPtr vptr, int key, const char* value)
{
auto qHash = reinterpret_cast<QHash<int, QByteArray>*>(vptr);
qHash->insert(key, QByteArray(value));
}
void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, char** result)
{
auto qHash = reinterpret_cast<QHash<int, QByteArray>*>(vptr);
QByteArray value = qHash->value(key);
*result = qstrdup(value.data());
}

View File

@ -1,102 +1,154 @@
#ifndef DOTHERSIDE_H
#define DOTHERSIDE_H
#include "DOtherSideTypes.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef char* CharPtr;
typedef void(*Function)(void*);
typedef void(*DObjectCallback)(void*, void*, int, void**);
typedef char* CharPtr;
typedef void(*Function)(void*);
typedef void(*DObjectCallback)(void*, void*, int, void**);
// QGuiApplication
void dos_qguiapplication_create();
void dos_qguiapplication_exec();
void dos_qguiapplication_quit();
void dos_qguiapplication_delete();
// QGuiApplication
void dos_qguiapplication_create();
void dos_qguiapplication_exec();
void dos_qguiapplication_quit();
void dos_qguiapplication_delete();
// QApplication
void dos_qapplication_create();
void dos_qapplication_exec();
void dos_qapplication_quit();
void dos_qapplication_delete();
// QQmlApplicationEngine
void dos_qqmlapplicationengine_create(void** vptr);
void dos_qqmlapplicationengine_load(void* vptr, const char* filename);
void dos_qqmlapplicationengine_context(void* vptr, void** context);
void dos_qqmlapplicationengine_delete(void* vptr);
// QApplication
void dos_qapplication_create();
void dos_qapplication_exec();
void dos_qapplication_quit();
void dos_qapplication_delete();
// QQuickView
void dos_qquickview_create(void** vptr);
void dos_qquickview_show(void* vptr);
void dos_qquickview_source(void* vptr, CharPtr& result, int& length);
void dos_qquickview_set_source(void* vptr, const char* filename);
void dos_qquickview_delete(void* vptr);
void dos_qquickview_rootContext(void* vptr, void** context);
// QQmlApplicationEngine
void dos_qqmlapplicationengine_create(void** vptr);
void dos_qqmlapplicationengine_load(void* vptr, const char* filename);
void dos_qqmlapplicationengine_context(void* vptr, void** context);
void dos_qqmlapplicationengine_delete(void* vptr);
// QQmlContext
void dos_qqmlcontext_baseUrl(void* vptr, CharPtr& result, int& length);
void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* value);
// QQuickView
void dos_qquickview_create(void** vptr);
void dos_qquickview_show(void* vptr);
void dos_qquickview_source(void* vptr, char** result, int* length);
void dos_qquickview_set_source(void* vptr, const char* filename);
void dos_qquickview_delete(void* vptr);
void dos_qquickview_rootContext(void* vptr, void** context);
// CharArray
void dos_chararray_create(CharPtr& ptr, int size);
void dos_chararray_delete(CharPtr ptr);
// QQmlContext
void dos_qqmlcontext_baseUrl(void* vptr, char** result, int* length);
void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* value);
// QVariant
void dos_qvariant_create(void **vptr);
void dos_qvariant_create_int(void **vptr, int value);
void dos_qvariant_create_bool(void **vptr, bool value);
void dos_qvariant_create_string(void **vptr, const char* value);
void dos_qvariant_create_qobject(void **vptr, void* value);
void dos_qvariant_create_qvariant(void **vptr, void* value);
void dos_qvariant_create_float(void **vptr, float value);
void dos_qvariant_create_double(void **vptr, double value);
void dos_qvariant_toInt(void* vptr, int& value);
void dos_qvariant_setInt(void* vptr, int value);
void dos_qvariant_toBool(void* vptr, bool& value);
void dos_qvariant_setBool(void* vptr, bool value);
void dos_qvariant_toFloat(void* vptr, float& value);
void dos_qvariant_setFloat(void* vptr, float value);
void dos_qvariant_toDouble(void* vptr, double& value);
void dos_qvariant_setDouble(void* vptr, double value);
void dos_qvariant_toString(void* vptr, CharPtr& ptr, int& size);
void dos_qvariant_setString(void* vptr, const char* value);
void dos_qvariant_setQObject(void* vptr, void* value);
void dos_qvariant_isnull(void *vptr, bool& isNull);
void dos_qvariant_delete(void *vptr);
void dos_qvariant_assign(void* vptr, void* other);
// CharArray
void dos_chararray_create(char** ptr, int size);
void dos_chararray_delete(char* ptr);
// QObject
void dos_qobject_create(void **vptr,
void *dObjectPointer,
DObjectCallback dObjectCallback);
// QVariant
void dos_qvariant_create(void** vptr);
void dos_qvariant_create_int(void** vptr, int value);
void dos_qvariant_create_bool(void** vptr, bool value);
void dos_qvariant_create_string(void** vptr, const char* value);
void dos_qvariant_create_qobject(void** vptr, void* value);
void dos_qvariant_create_qvariant(void** vptr, void* value);
void dos_qvariant_create_float(void** vptr, float value);
void dos_qvariant_create_double(void** vptr, double value);
void dos_qvariant_create_qabstractlistmodel(void** vptr, void* value);
void dos_qvariant_toInt(void* vptr, int* value);
void dos_qvariant_setInt(void* vptr, int value);
void dos_qvariant_toBool(void* vptr, bool* value);
void dos_qvariant_setBool(void* vptr, bool value);
void dos_qvariant_toFloat(void* vptr, float* value);
void dos_qvariant_setFloat(void* vptr, float value);
void dos_qvariant_toDouble(void* vptr, double* value);
void dos_qvariant_setDouble(void* vptr, double value);
void dos_qvariant_toString(void* vptr, char** ptr, int* size);
void dos_qvariant_setString(void* vptr, const char* value);
void dos_qvariant_setQObject(void* vptr, void* value);
void dos_qvariant_setQAbstractListModel(void* vptr, void* value);
void dos_qvariant_isnull(void* vptr, bool* isNull);
void dos_qvariant_delete(void* vptr);
void dos_qvariant_assign(void* vptr, void* other);
void dos_qobject_slot_create(void* vptr,
const char* name,
int parametersCount,
int* parametersMetaTypes,
int* slotIndex);
// QObject
void dos_qobject_create(void** vptr,
void* dObjectPointer,
DObjectCallback dObjectCallback);
void dos_qobject_signal_create(void* vptr,
const char* name,
int parametersCount,
int* parametersMetaTypes,
int* signalIndex);
void dos_qobject_slot_create(void* vptr,
const char* name,
int parametersCount,
int* parametersMetaTypes,
int* slotIndex);
void dos_qobject_signal_emit(void* vptr,
const char* name,
int parametersCount,
void** parameters);
void dos_qobject_signal_create(void* vptr,
const char* name,
int parametersCount,
int* parametersMetaTypes,
int* signalIndex);
void dos_qobject_property_create(void* vptr,
const char* name,
int propertyMetaType,
const char* readSlot,
const char* writeSlot,
const char* notifySignal);
void dos_qobject_delete(void *vptr);
void dos_qobject_signal_emit(void* vptr,
const char* name,
int parametersCount,
void** parameters);
void dos_qobject_property_create(void* vptr,
const char* name,
int propertyMetaType,
const char* readSlot,
const char* writeSlot,
const char* notifySignal);
void dos_qobject_delete(void* vptr);
// QModelIndex
void dos_qmodelindex_create(void** vptr);
void dos_qmodelindex_delete(void* vptr);
void dos_qmodelindex_row(void* vptr, int* row);
void dos_qmodelindex_column(void* vptr, int* column);
void dos_qmodelindex_isValid(void* vptr, bool* isValid);
void dos_qmodelindex_data(void* vptr, int role, void* data);
void dos_qmodelindex_parent(void* vptr, void* parent);
void dos_qmodelindex_child(void* vptr, int row, int column, void* child);
void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling);
// QHash<int, QByteArray>
void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr);
void dos_qhash_int_qbytearray_delete(QHashIntQByteArrayVoidPtr vptr);
void dos_qhash_int_qbytearray_insert(QHashIntQByteArrayVoidPtr vptr, int key, const char* value);
void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, char** result);
// QAbstractListModel
void dos_qabstractlistmodel_create(void** vptr,
void* callbackObject,
DObjectCallback dObjectCallback,
RowCountCallback rowCountCallback,
ColumnCountCallback columnCountCallback,
DataCallback dataCallback,
SetDataCallback setDataCallback,
RoleNamesCallback roleNamesCallback,
FlagsCallback flagsCallback,
HeaderDataCallback headerDataCallback);
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_endRemoveRows(void* vptr);
void dos_qabstractlistmodel_beginResetModel(void* vptr);
void dos_qabstractlistmodel_endResetModel(void* vptr);
void dos_qabstractlistmodel_dataChanged(void* vptr,
QModelIndexVoidPtr topLeftIndex,
QModelIndexVoidPtr bottomRightIndex,
int* rolesArrayPtr,
int rolesArrayLength);
void dos_qabstractlistmodel_delete(void* vptr);
#ifdef __cplusplus
}

View File

@ -0,0 +1,27 @@
#ifndef DOTHERSIDETYPES_H
#define DOTHERSIDETYPES_H
// Raw data types
typedef bool* BoolPtr;
typedef int* IntPtr;
typedef char* CharPtr;
typedef const char* ConstCharPtr;
typedef void* QVariantVoidPtr;
typedef void* QModelIndexVoidPtr;
typedef void* QAbstractListModelVoidPtr;
typedef void* QQmlApplicationEngineVoidPtr;
typedef void* QQuickViewVoidPtr;
typedef void* QQmlContextVoidPtr;
typedef void* QHashIntQByteArrayVoidPtr;
// Raw function types
typedef void (*Function)(void*);
typedef void (*DObjectCallback)(void*, void*, int, void**);
typedef void (*RowCountCallback)(void* model, QModelIndexVoidPtr index, IntPtr result);
typedef void (*ColumnCountCallback)(void* model, QModelIndexVoidPtr index, IntPtr result);
typedef void (*DataCallback)(void* model, QModelIndexVoidPtr index, int role, QVariantVoidPtr result);
typedef void (*SetDataCallback) (void* model, QModelIndexVoidPtr index, QVariantVoidPtr value, int role, BoolPtr result);
typedef void (*RoleNamesCallback)(void* model, QHashIntQByteArrayVoidPtr result);
typedef void (*FlagsCallback) (void* model, QModelIndexVoidPtr index, IntPtr result);
typedef void (*HeaderDataCallback) (void* model, int section, int orientation, int role, QVariantVoidPtr result);
#endif

View File

@ -15,7 +15,6 @@ set(HEADERS_LIST
set(SRC_LIST
DynamicProperty.cpp
DynamicQObject.cpp
DynamicSignal.cpp
DynamicSlot.cpp
)

View File

@ -1,119 +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;
}

View File

@ -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
@ -23,7 +23,9 @@ public:
QString name() const;
QMetaType::Type type() const;
bool isValid() const { return d != nullptr; }
bool isValid() const {
return d != nullptr;
}
bool isReadable() const;
bool isWriteable() const;
@ -36,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

View File

@ -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();
}

View File

@ -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,37 +25,37 @@ 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;
virtual const QMetaObject* metaObject() const;
/// The qt metacall. Called from Qt when a signals, slot or property is invoked
int qt_metacall(QMetaObject::Call, int, void **);
int qt_metacall(QMetaObject::Call, int, void**);
private:
bool executeSlot(const DynamicSlot& slot, void** args);
@ -67,9 +70,9 @@ private:
/// The creation is customizable by injecting custom code after signals and slots have
/// been added
static QMetaObject* recreateMetaObjectBuilder(QMetaObject* currentMetaObject,
const std::function<void(QMetaObjectBuilder&)>& afterSignalAdded,
const std::function<void(QMetaObjectBuilder&)>& afterSlotAdded,
const std::function<void(QMetaObjectBuilder&)>& afterPropertyAdded);
const std::function<void(QMetaObjectBuilder&)>& afterSignalAdded,
const std::function<void(QMetaObjectBuilder&)>& afterSlotAdded,
const std::function<void(QMetaObjectBuilder&)>& afterPropertyAdded);
QHash<QString, DynamicSignal> m_signalsByName;
QHash<QByteArray, DynamicSignal> m_signalsBySignature;
@ -78,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

View File

@ -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();
}

View File

@ -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

View File

@ -1,111 +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();
qDebug() << "C++: slot signature is " << d->signature;
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 &block;
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

View File

@ -5,7 +5,7 @@
#include <DynamicQObject.h>
#include <QDebug>
int main(int argc, char *argv[])
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);

View File

@ -0,0 +1,2 @@
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_nim_executable(TARGET AbstractItemModel SOURCES main.nim PATHS ../../NimQml)

View File

@ -0,0 +1,64 @@
import NimQml
import macros
import typeinfo
import tables
type
Roles {.pure.} = enum
Name = cint(0)
MyQAbstractListModel = ref object of QAbstractListModel
m_roleNames: Table[int, cstring]
m_names: seq[string]
proc create(self: MyQAbstractListModel) =
var qAbstractListModel = self.QAbstractListModel
qAbstractListModel.create
self.m_names = @["John", "Max", "Paul", "Anna"]
self.m_roleNames = initTable[int, cstring]()
self.m_roleNames[0] = "name"
proc delete(self: MyQAbstractListModel) =
var qAbstractListModel = self.QAbstractListModel
qAbstractListModel.delete
proc newMyQAbstractListModel(): MyQAbstractListModel =
new(result, delete)
result.create
method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint =
return self.m_names.len.cint
method data(self: MyQAbstractListModel, index: QModelIndex, role: cint): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.m_names.len:
return
if role == Roles.Name.cint:
return newQVariant(self.m_names[index.row])
method roleNames(self: MyQAbstractListModel): Table[int, cstring] =
return self.m_roleNames
proc mainProc() =
var app = newQApplication()
defer: app.delete
var myListModel = newMyQAbstractListModel()
defer: myListModel.delete
var engine = newQQmlApplicationEngine()
defer: engine.delete
var variant = newQVariant(myListModel)
defer: variant.delete
engine.rootContext.setContextProperty("myListModel", variant)
engine.load("main.qml")
app.exec()
when isMainModule:
mainProc()
GC_fullcollect()

View File

@ -0,0 +1,25 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
ApplicationWindow
{
width: 400
height: 300
title: "AbstractItemModel"
Component.onCompleted: visible = true
Component
{
id: myListModelDelegate
Label { text: "Name:" + name }
}
ListView
{
anchors.fill: parent
model: myListModel
delegate: myListModelDelegate
}
}

View File

@ -2,4 +2,5 @@ add_subdirectory(HelloWorld)
add_subdirectory(SimpleData)
add_subdirectory(SlotsAndProperties)
add_subdirectory(QtObjectMacro)
add_subdirectory(ContactApp)
add_subdirectory(ContactApp)
add_subdirectory(AbstractItemModel)

View File

@ -1,44 +1,62 @@
## Please note we are using templates where ordinarily we would like to use procedures
## due to bug: https://github.com/Araq/Nim/issues/1821
import NimQml, NimQmlMacros, Contact
import NimQml, NimQmlMacros, Contact, Tables
QtObject:
type ContactList* = ref object of QObject
contacts*: seq[Contact]
type
ContactList* = ref object of QAbstractListModel
contacts*: seq[Contact]
ContactRoles {.pure.} = enum
FirstName = 0
Surname = 1
proc delete*(self: ContactList) =
let qobject = self.QObject
qobject.delete
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 delete(self: ContactList) =
let model = self.QAbstractListModel
model.delete
for contact in self.contacts:
contact.delete
self.contacts = @[]
proc newContactList*(): ContactList =
new(result)
new(result, delete)
result.contacts = @[]
result.create()
method getCount(self: ContactList): int {.slot.} =
result.create
method rowCount(self: ContactList, index: QModelIndex = nil): cint =
return self.contacts.len
method countChanged(self: ContactList) {.signal.}
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
let contact = self.contacts[index.row]
let contactRole = role.ContactRoles
case contactRole:
of ContactRoles.FirstName: return contact.firstName
of ContactRoles.Surname: return contact.surname
else: return
method roleNames(self: ContactList): Table[cint, cstring] =
result = initTable[cint, cstring]()
result[ContactRoles.FirstName] = "firstName"
result[ContactRoles.Surname] = "surname"
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.countChanged()
self.endInsertRows()
method get*(self: ContactList, index: int): QObject {.slot.} =
if index < 0 or index >= self.contacts.len:
return nil
result = self.contacts[index].QObject
method del*(self: ContactList, index: int) {.slot.} =
self.contacts.del(index)
self.countChanged()
QtProperty[int] count:
read = getCount
notify = countChanged
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

View File

@ -3,50 +3,91 @@ import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
ApplicationWindow
{
width: 400
ApplicationWindow {
width: 500
height: 300
title: "ContactApp"
visible: true
menuBar: MenuBar {
Menu
{
Menu {
title: "&File"
MenuItem { text: "Load"; onTriggered: logic.onLoadTriggered() }
MenuItem { text: "Save"; onTriggered: logic.onSaveTriggered() }
MenuItem { text: "Exit"; onTriggered: logic.onExitTriggered() }
MenuItem { text: "&Load"; onTriggered: logic.onLoadTriggered() }
MenuItem { text: "&Save"; onTriggered: logic.onSaveTriggered() }
MenuItem { text: "&Exit"; onTriggered: logic.onExitTriggered() }
}
}
ColumnLayout
{
ColumnLayout {
anchors.fill: parent
ListView
{
Layout.fillWidth: true
Layout.fillHeight: true
model: logic.contactList.count
spacing: 5
delegate: RowLayout {
width: ListView.view.width
property QtObject contact: logic.contactList.get(index)
TextField { Layout.fillWidth: true; text: contact.firstName }
TextField { Layout.fillWidth: true; text: contact.surname }
Button { text: "Save" }
Button { text: "Delete"; onClicked: logic.contactList.del(index) }
Component {
id: tableTextDelegate
Label {
id: tableTextDelegateInstance
property var styleData: undefined
states: State {
when: styleData !== undefined
PropertyChanges {
target: tableTextDelegateInstance;
text: styleData.value;
color: styleData.textColor
}
}
}
}
RowLayout
{
Component {
id: tableButtonDelegate
Button {
id: tableButtonDelegateInstance
property var styleData: undefined
text: "Delete"
onClicked: logic.contactList.del(styleData.row)
}
}
Component {
id: tableItemDelegate
Loader {
id: tableItemDelegateInstance
sourceComponent: {
if (styleData.column === 0 || styleData.column === 1)
return tableTextDelegate
else if (styleData.column === 2)
return tableButtonDelegate
else
return tableTextDelegate
}
Binding {
target: tableItemDelegateInstance.item
property: "styleData"
value: styleData
}
}
}
TableView {
model: logic.contactList
Layout.fillWidth: true
Layout.fillHeight: true
TableViewColumn { role: "firstName"; title: "FirstName"; width: 200 }
TableViewColumn { role: "surname"; title: "Surname"; width: 200}
TableViewColumn { width: 100; }
itemDelegate: tableItemDelegate
}
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.contactList.add(nameTextField.text, surnameTextField.text) }
Button {
text: "Add"
onClicked: logic.contactList.add(nameTextField.text, surnameTextField.text)
enabled: nameTextField.text !== "" && surnameTextField.text !== ""
}
}
}
}

View File

@ -26,22 +26,37 @@ type QMetaType* {.pure.} = enum ## \
var qobjectRegistry = initTable[ptr QObjectObj, bool]()
proc debugMsg(message: string) =
echo "NimQml: ", message
template debugMsg(message: string) =
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
when defined(debug):
{.pop.}
echo "NimQml: ", message
else:
{.pop.}
template debugMsg(typeName: string, procName: string) =
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
when defined(debug):
{.pop.}
var message = typeName
message &= ": "
message &= procName
debugMsg(message)
else:
{.pop.}
proc debugMsg(typeName: string, procName: string) =
var message = typeName
message &= ": "
message &= procName
debugMsg(message)
proc debugMsg(typeName: string, procName: string, userMessage: string) =
var message = typeName
message &= ": "
message &= procName
message &= " "
message &= userMessage
debugMsg(message)
template debugMsg(typeName: string, procName: string, userMessage: string) =
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
when defined(debug):
{.pop.}
var message = typeName
message &= ": "
message &= procName
message &= " "
message &= userMessage
debugMsg(message)
else:
{.pop.}
template newWithCondFinalizer(variable: expr, finalizer: expr) =
## calls ``new`` but only setting a finalizer when ``nimqml_use_finalizers``
@ -101,7 +116,7 @@ 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: RawQVariant) =
@ -225,8 +240,8 @@ proc `stringVal=`*(variant: QVariant, value: string) =
proc `qobjectVal=`*(variant: QVariant, value: QObject) =
## Sets the QVariant qobject value
dos_qvariant_setQObject(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
dos_qvariant_assign(leftValue.data, rightValue.data)
@ -491,3 +506,284 @@ proc newQQuickView*(): QQuickView =
## Return a new QQuickView
newWithCondFinalizer(result, delete)
result.create()
# QModelIndex
proc dos_qmodelindex_create(modelIndex: var RawQModelIndex) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_delete(modelIndex: RawQModelIndex) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_row(modelIndex: RawQModelIndex, row: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_column(modelIndex: RawQModelIndex, column: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_isValid(modelIndex: RawQModelIndex, column: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_data(modelIndex: RawQModelIndex, role: cint, data: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_parent(modelIndex: RawQModelIndex, parent: RawQModelIndex) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_child(modelIndex: RawQModelIndex, row: cint, column: cint, parent: RawQModelIndex) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qmodelindex_sibling(modelIndex: RawQModelIndex, row: cint, column: cint, sibling: RawQModelIndex) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc create*(modelIndex: var QModelIndex) =
## Create a new QModelIndex
dos_qmodelindex_create(modelIndex.data)
modelIndex.deleted = false
proc create*(modelIndex: var QModelIndex, rawQModelIndex: RawQModelIndex) =
## Create a new QModelIndex
modelIndex.data = rawQModelIndex
modelIndex.deleted = false
proc delete*(modelIndex: QModelIndex) =
## Delete the given QModelIndex
if not modelIndex.deleted:
debugMsg("QModelIndex", "delete")
dos_qmodelindex_delete(modelIndex.data)
modelIndex.data = nil.RawQModelIndex
modelIndex.deleted = true
proc newQModelIndex*(): QModelIndex =
## Return a new QModelIndex
newWithCondFinalizer(result, delete)
result.create()
proc newQModelIndex*(rawQModelIndex: RawQModelIndex): QModelIndex =
## Return a new QModelIndex given a raw index
newWithCondFinalizer(result, delete)
result.create(rawQModelIndex)
proc row*(modelIndex: QModelIndex): cint =
## Return the index row
dos_qmodelindex_row(modelIndex.data, result)
proc column*(modelIndex: QModelIndex): cint =
## Return the index column
dos_qmodelindex_column(modelIndex.data, result)
proc isValid*(modelIndex: QModelIndex): bool =
## Return true if the index is valid, false otherwise
dos_qmodelindex_isValid(modelIndex.data, result)
proc data*(modelIndex: QModelIndex, role: cint): QVariant =
## Return the model data associated to the given role
result = newQVariant()
dos_qmodelindex_data(modelIndex.data, role, result.data)
proc parent*(modelIndex: QModelIndex): QModelIndex =
## Return the parent index
result = newQModelIndex()
dos_qmodelindex_parent(modelIndex.data, result.data)
proc child*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex =
## Return the child index associated to the given row and column
result = newQModelIndex()
dos_qmodelindex_child(modelIndex.data, row, column, result.data)
proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex =
## Return the sibling index associated to the given row and column
result = newQModelIndex()
dos_qmodelindex_sibling(modelIndex.data, row, column, result.data)
# QHashIntByteArray
proc dos_qhash_int_qbytearray_create(qHash: var RawQHashIntByteArray) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qhash_int_qbytearray_delete(qHash: RawQHashIntByteArray) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qhash_int_qbytearray_insert(qHash: RawQHashIntByteArray, key: int, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qhash_int_qbytearray_value(qHash: RawQHashIntByteArray, key: int, value: var cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc create*(qHash: var QHashIntByteArray) =
## Create the QHash
debugMsg("QHashIntByteArray", "create")
dos_qhash_int_qbytearray_create(qHash.data)
qHash.deleted = false
proc delete*(qHash: QHashIntByteArray) =
## Delete the QHash
if not qHash.deleted:
debugMsg("QHashIntByteArray", "delete")
dos_qhash_int_qbytearray_delete(qHash.data)
qHash.deleted = true
proc insert*(qHash: QHashIntByteArray, key: int, value: cstring) =
## Insert the value at the given key
dos_qhash_int_qbytearray_insert(qHash.data, key, value)
proc value*(qHash: QHashIntByteArray, key: int): string =
## Return the value associated at the given key
var rawString: cstring
dos_qhash_int_qbytearray_value(qHash.data, key, rawString)
result = $rawString
dos_chararray_delete(rawString)
proc newQHashIntQByteArray*(): QHashIntByteArray =
## Create a new QHashIntQByteArray
newWithCondFinalizer(result, delete)
result.create()
# QAbstractListModel
type
RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.}
ColumnCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.}
DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.}
SetDataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, value: RawQVariant, role: cint, result: var bool) {.cdecl.}
RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: RawQHashIntByteArray) {.cdecl.}
FlagsCallback = proc(modelObject: ptr QAbstractListModelObj, index: RawQModelIndex, result: var cint) {.cdecl.}
HeaderDataCallback = proc(modelObject: ptr QAbstractListModelObj, section: cint, orientation: cint, role: cint, result: RawQVariant) {.cdecl.}
proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel,
modelPtr: ptr QAbstractListModelObj,
qobjectCallback: QObjectCallBack,
rowCountCallback: RowCountCallback,
columnCountCallback: ColumnCountCallback,
dataCallback: DataCallback,
setDataCallback: SetDataCallBack,
roleNamesCallback: RoleNamesCallback,
flagsCallback: FlagsCallback,
headerDataCallback: HeaderDataCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_beginInsertRows(model: RawQAbstractListModel,
parentIndex: RawQModelIndex,
first: cint,
last: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_endInsertRows(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_beginRemoveRows(model: RawQAbstractListModel,
parentIndex: RawQModelIndex,
first: cint,
last: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_endRemoveRows(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_beginResetModel(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_endResetModel(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.}
proc dos_qabstractlistmodel_dataChanged(model: RawQAbstractListModel,
parentLeft: RawQModelIndex,
bottomRight: RawQModelIndex,
rolesArrayPtr: ptr cint,
rolesArrayLength: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
method rowCount*(model: QAbstractListModel, index: QModelIndex): cint =
## Return the model's row count
return 0
proc rowCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "rowCountCallback")
let model = cast[QAbstractListModel](modelObject)
let index = newQModelIndex(rawIndex)
result = model.rowCount(index)
method columnCount*(model: QAbstractListModel, index: QModelIndex): cint =
## Return the model's column count
return 1
proc columnCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "columnCountCallback")
let model = cast[QAbstractListModel](modelObject)
let index = newQModelIndex(rawIndex)
result = model.columnCount(index)
method data*(model: QAbstractListModel, index: QModelIndex, role: cint): QVariant =
## Return the data at the given model index and role
return nil
proc dataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "dataCallback")
let model = cast[QAbstractListModel](modelObject)
let index = newQModelIndex(rawIndex)
let variant = data(model, index, role)
if variant != nil:
dos_qvariant_assign(result, variant.data)
variant.delete
method setData*(model: QAbstractListModel, index: QModelIndex, value: QVariant, role: cint): bool =
## Sets the data at the given index and role. Return true on success, false otherwise
return false
proc setDataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, rawQVariant: RawQVariant, role: cint, result: var bool) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "setDataCallback")
let model = cast[QAbstractListModel](modelObject)
let index = newQModelIndex(rawIndex)
let variant = newQVariant(rawQVariant)
result = model.setData(index, variant, role)
method roleNames*(model: QAbstractListModel): Table[cint, cstring] =
## Return the model role names
result = initTable[cint, cstring]()
proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashIntByteArray) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "roleNamesCallback")
let model = cast[QAbstractListModel](modelObject)
let table = model.roleNames()
for pair in table.pairs:
dos_qhash_int_qbytearray_insert(hash, pair.key, pair.val)
method flags*(model: QAbstractListModel, index: QModelIndex): QtItemFlag =
## Return the item flags and the given index
return QtItemFlag.None
proc flagsCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "flagsCallback")
let model = cast[QAbstractListModel](modelObject)
let index = newQModelIndex(rawIndex)
result = model.flags(index).cint
method headerData*(model: QAbstractListModel, section: cint, orientation: QtOrientation, role: cint): QVariant =
## Returns the data for the given role and section in the header with the specified orientation
return nil
proc headerDataCallback(modelObject: ptr QAbstractListModelObj, section: cint, orientation: cint, role: cint, result: RawQVariant) {.cdecl, exportc.} =
debugMsg("QAbstractListModel", "headerDataCallback")
let model = cast[QAbstractListModel](modelObject)
let variant = model.headerData(section, orientation.QtOrientation, role)
if variant != nil:
dos_qvariant_assign(result, variant.data)
variant.delete
proc create*(model: var QAbstractListModel) =
## Create a new QAbstractListModel
debugMsg("QAbstractListModel", "create")
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, columnCountCallback, dataCallback, setDataCallback, roleNamesCallback, flagsCallback, headerDataCallback)
qobjectRegistry[modelPtr] = true
proc delete*(model: QAbstractListModel) =
## Delete the given QAbstractListModel
if not model.deleted:
debugMsg("QAbstractListModel", "delete")
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)
result.create()
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.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.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.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.RawQAbstractListModel)
proc beginResetModel*(model: QAbstractListModel) =
## Notify the view that the model is about to resetting
dos_qabstractlistmodel_beginResetModel(model.data.RawQAbstractListModel)
proc endResetModel*(model: QAbstractListModel) =
## Notify the view that model has finished resetting
dos_qabstractlistmodel_endResetModel(model.data.RawQAbstractListModel)
proc dataChanged*(model: QAbstractListModel,
topLeft: QModelIndex,
bottomRight: QModelIndex,
roles: seq[cint]) =
## Notify the view that the model data changed
var copy = roles
dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, copy[0].addr, copy.len.cint)

View File

@ -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
@ -33,3 +41,28 @@ type
QQmlContext* = distinct pointer ## A QQmlContext
RawQModelIndex = distinct pointer
QModelIndex* = ref object of RootObj ## A QModelIndex
data: RawQModelIndex
deleted: bool
RawQHashIntByteArray = distinct pointer
QHashIntByteArrayObj = object of RootObj
data: RawQHashIntByteArray
deleted: bool
QHashIntByteArray* = ref QHashIntByteArrayObj ## A QHash<int,QByteArray>
QtItemFlag* {.pure.} = enum
None = 0.cint,
IsSelectable = 1.cint,
IsEditable = 2.cint,
IsDragEnabled = 4.cint,
IsDropEnabled = 8.cint,
IsUserCheckable = 16.cint,
IsEnabled = 32.cint,
IsTristate = 64.cint,
NeverHasChildren = 128.cint
QtOrientation {.pure.} = enum
Horizontal = 1.cint,
Vertical = 2.cint