From 983c9b95c4bd974bda12ac19abdae6126c9a5ad1 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 6 Jan 2015 20:02:23 +0000 Subject: [PATCH 01/58] improve type safety of FFI calls with the types that are already defined --- Nim/NimQml/NimQml.nim | 108 ++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 62 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index cd40e6c..a57676f 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -40,125 +40,111 @@ proc debugMsg(typeName: string, procName: string, userMessage: string) = debugMsg(message) # QVariant -proc dos_qvariant_create(variant: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_int(variant: var pointer, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_bool(variant: var pointer, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_string(variant: var pointer, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_qobject(variant: var pointer, value: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_delete(variant: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_isnull(variant: pointer, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toInt(variant: pointer, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toBool(variant: pointer, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toString(variant: pointer, value: var cstring, length: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setInt(variant: pointer, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setBool(variant: pointer, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setString(variant: pointer, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create(variant: var QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_int(variant: var QVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_bool(variant: var QVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_string(variant: var QVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qobject(variant: var QVariant, value: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_delete(variant: QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_isnull(variant: QVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toInt(variant: QVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toBool(variant: QVariant, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toString(variant: QVariant, value: var cstring, length: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setInt(variant: QVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setBool(variant: QVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setString(variant: QVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: var QVariant) = ## Create a new QVariant - var data: pointer - dos_qvariant_create(data) - variant = QVariant(data) + dos_qvariant_create(variant) proc create*(variant: var QVariant, value: cint) = ## Create a new QVariant given a cint value - var data: pointer - dos_qvariant_create_int(data, value) - variant = QVariant(data) + dos_qvariant_create_int(variant, value) proc create*(variant: var QVariant, value: bool) = ## Create a new QVariant given a bool value - var data: pointer - dos_qvariant_create_bool(data, value) - variant = QVariant(data) + dos_qvariant_create_bool(variant, value) proc create*(variant: var QVariant, value: string) = ## Create a new QVariant given a string value - var data: pointer - dos_qvariant_create_string(data, value) - variant = QVariant(data) + dos_qvariant_create_string(variant, value) proc create*(variant: var QVariant, value: QObject) = ## Create a new QVariant given a QObject - var data: pointer - dos_qvariant_create_qobject(data, value.data) - variant = QVariant(data) + dos_qvariant_create_qobject(variant, value.data) proc delete*(variant: QVariant) = ## Delete a QVariant debugMsg("QVariant", "delete") - dos_qvariant_delete(pointer(variant)) + dos_qvariant_delete(variant) proc isNull*(variant: QVariant): bool = ## Return true if the QVariant value is null, false otherwise - dos_qvariant_isnull(pointer(variant), result) + dos_qvariant_isnull(variant, result) proc intVal*(variant: QVariant): int = ## Return the QVariant value as int var rawValue: cint - dos_qvariant_toInt(pointer(variant), rawValue) + dos_qvariant_toInt(variant, rawValue) result = cast[int](rawValue) proc `intVal=`*(variant: QVariant, value: int) = ## Sets the QVariant value int value var rawValue = cast[cint](value) - dos_qvariant_setInt(pointer(variant), rawValue) + dos_qvariant_setInt(variant, rawValue) proc boolVal*(variant: QVariant): bool = ## Return the QVariant value as bool - dos_qvariant_toBool(pointer(variant), result) + dos_qvariant_toBool(variant, result) proc `boolVal=`*(variant: QVariant, value: bool) = ## Sets the QVariant bool value - dos_qvariant_setBool(pointer(variant), value) + dos_qvariant_setBool(variant, value) proc stringVal*(variant: QVariant): string = ## Return the QVariant value as string var rawCString: cstring var rawCStringLength: cint - dos_qvariant_toString(pointer(variant), rawCString, rawCStringLength) + dos_qvariant_toString(variant, rawCString, rawCStringLength) result = $rawCString dos_chararray_delete(rawCString) proc `stringVal=`*(variant: QVariant, value: string) = ## Sets the QVariant string value - dos_qvariant_setString(pointer(variant), value) + dos_qvariant_setString(variant, value) # QQmlApplicationEngine -proc dos_qqmlapplicationengine_create(engine: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_load(engine: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_context(engine: pointer, context: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_delete(engine: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_create(engine: var QQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_load(engine: QQmlApplicationEngine, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_context(engine: QQmlApplicationEngine, context: var QQmlContext) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_delete(engine: QQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(engine: var QQmlApplicationEngine) = ## Create an new QQmlApplicationEngine - var temp: pointer - dos_qqmlapplicationengine_create(temp) - engine = QQmlApplicationEngine(temp) + dos_qqmlapplicationengine_create(engine) proc load*(engine: QQmlApplicationEngine, filename: cstring) = ## Load the given Qml file - dos_qqmlapplicationengine_load(pointer(engine), filename) + dos_qqmlapplicationengine_load(engine, filename) proc rootContext*(engine: QQmlApplicationEngine): QQmlContext = ## Return the engine root context - var context: pointer - dos_qqmlapplicationengine_context(pointer(engine), context) - result = cast[QQmlContext](context) + dos_qqmlapplicationengine_context(engine, result) proc delete*(engine: QQmlApplicationEngine) = ## Delete the given QQmlApplicationEngine debugMsg("QQmlApplicationEngine", "delete") - dos_qqmlapplicationengine_delete(pointer(engine)) + dos_qqmlapplicationengine_delete(engine) # QQmlContext -proc dos_qqmlcontext_setcontextproperty(context: pointer, propertyName: cstring, propertyValue: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlcontext_setcontextproperty(context: QQmlContext, propertyName: cstring, propertyValue: QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc setContextProperty*(context: QQmlContext, propertyName: string, propertyValue: QVariant) = ## Sets a new property with the given value - dos_qqmlcontext_setcontextproperty(pointer(context), propertyName, pointer(propertyValue)) + dos_qqmlcontext_setcontextproperty(context, propertyName, propertyValue) # QApplication proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} @@ -261,34 +247,32 @@ proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) dos_qobject_signal_emit(qobject.data, signalName, 0, cast[pointer](0)) # QQuickView -proc dos_qquickview_create(view: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_delete(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_show(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_source(view: pointer, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_set_source(view: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_create(view: var QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_delete(view: QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_show(view: QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_source(view: QQuickView, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_set_source(view: QQuickView, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create(view: var QQuickView) = ## Create a new QQuickView - var temp: pointer - dos_qquickview_create(temp) - view = QQuickView(temp) + dos_qquickview_create(view) proc source(view: QQuickView): cstring = ## Return the source Qml file loaded by the view var length: int - dos_qquickview_source(pointer(view), result, length) + dos_qquickview_source(view, result, length) proc `source=`(view: QQuickView, filename: cstring) = ## Sets the source Qml file laoded by the view - dos_qquickview_set_source(pointer(view), filename) + dos_qquickview_set_source(view, filename) proc show(view: QQuickView) = ## Sets the view visible - dos_qquickview_show(pointer(view)) + dos_qquickview_show(view) proc delete(view: QQuickView) = ## Delete the given QQuickView - dos_qquickview_delete(pointer(view)) + dos_qquickview_delete(view) From 98e47591b9c746ec95732e713c5c2b54b1bce449 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 6 Jan 2015 20:56:43 +0000 Subject: [PATCH 02/58] improve type safety of internal qobject --- Nim/NimQml/NimQml.nim | 25 +++++++++++++------------ Nim/NimQml/NimQmlTypes.nim | 4 +++- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index a57676f..581b899 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -44,7 +44,7 @@ proc dos_qvariant_create(variant: var QVariant) {.cdecl, dynlib:"libDOtherSide.s proc dos_qvariant_create_int(variant: var QVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_bool(variant: var QVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_string(variant: var QVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_qobject(variant: var QVariant, value: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qobject(variant: var QVariant, value: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: QVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_toInt(variant: QVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -176,23 +176,24 @@ proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = result = @[] for metaType in metaTypes: result.add(cint(metaType)) + +type QObjectCallBack = proc(nimobject: ptr QObject, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl.} -proc dos_qobject_create(qobject: var pointer, nimobject: pointer, qobjectCallback: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_delete(qobject: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_slot_create(qobject: pointer, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_signal_create(qobject: pointer, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_signal_emit(qobject: pointer, signalName: cstring, argumentsCount: cint, arguments: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_property_create(qobject: pointer, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_create(qobject: var DynamicQObject, nimobject: ptr QObject, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_delete(qobject: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_slot_create(qobject: DynamicQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_signal_create(qobject: DynamicQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_signal_emit(qobject: DynamicQObject, signalName: cstring, argumentsCount: cint, arguments: ptr QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_property_create(qobject: DynamicQObject, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVariant]) = ## Called from the NimQml bridge when a slot is called from Qml. ## Subclasses can override the given method for handling the slot call discard() -proc qobjectCallback(nimobject: pointer, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.exportc.} = - var nimQObjectCasted = cast[ptr QObject](nimobject) +proc qobjectCallback(nimobject: ptr QObject, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl, exportc.} = # forward to the QObject subtype instance - nimQObjectCasted[].onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments)) + nimobject[].onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments)) proc create*(qobject: var QObject) = ## Create a new QObject @@ -242,9 +243,9 @@ proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) var copy: seq[QVariant] for i in 0..args.len-1: copy.add(args[i]) - dos_qobject_signal_emit(qobject.data, signalName, cast[cint](args.len), cast[pointer](addr(copy[0]))) + dos_qobject_signal_emit(qobject.data, signalName, args.len.cint, addr(copy[0])) else: - dos_qobject_signal_emit(qobject.data, signalName, 0, cast[pointer](0)) + dos_qobject_signal_emit(qobject.data, signalName, 0, nil) # QQuickView proc dos_qquickview_create(view: var QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 7e173c0..718bb44 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -5,9 +5,11 @@ type QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine QQmlContext* = distinct pointer ## A QQmlContext QApplication* = distinct pointer ## A QApplication + DynamicQObject* = distinct pointer + ## internal representation of a QObject, as recognised by DOtherSide QObject* {.inheritable.} = ref object of RootObj ## A QObject name*: string - data*: pointer + data*: DynamicQObject slots*: Table[string, cint] signals*: Table[string, cint] properties*: Table[string, cint] From 254a7c5f68c172d3ff9017727deceeae6d46ba9d Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 6 Jan 2015 23:16:26 +0000 Subject: [PATCH 03/58] create no longer takes var parameter --- Nim/NimQml/NimQml.nim | 23 +++++++++++++++-------- Nim/NimQml/NimQmlTypes.nim | 3 ++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 581b899..84d5ab9 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -22,6 +22,8 @@ type QMetaType* {.pure.} = enum ## \ QVariant = cint(41), Void = cint(43) +var qobjectRegistry = initTable[ptr QObjectObj, QObject]() + proc debugMsg(message: string) = echo "NimQml: ", message @@ -177,9 +179,9 @@ proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = for metaType in metaTypes: result.add(cint(metaType)) -type QObjectCallBack = proc(nimobject: ptr QObject, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl.} +type QObjectCallBack = proc(nimobject: ptr QObjectObj, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl.} -proc dos_qobject_create(qobject: var DynamicQObject, nimobject: ptr QObject, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_create(qobject: var DynamicQObject, nimobject: ptr QObjectObj, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_delete(qobject: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_slot_create(qobject: DynamicQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_signal_create(qobject: DynamicQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -191,19 +193,26 @@ method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVari ## Subclasses can override the given method for handling the slot call discard() -proc qobjectCallback(nimobject: ptr QObject, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl, exportc.} = +proc qobjectCallback(nimobject: ptr QObjectObj, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl, exportc.} = + let qobject = qobjectRegistry[nimobject] + assert qobject != nil, "expecting valid QObject" # forward to the QObject subtype instance - nimobject[].onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments)) + qobject.onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments)) -proc create*(qobject: var QObject) = +proc create*(qobject: QObject) = ## Create a new QObject + let internalRef = qobject + let qobjectPtr = addr(qobject[]) + qobjectRegistry[qobjectPtr] = internalRef qobject.name = "QObject" qobject.slots = initTable[string,cint]() qobject.signals = initTable[string, cint]() - dos_qobject_create(qobject.data, addr(qobject), qobjectCallback) + dos_qobject_create(qobject.data, qobjectPtr, qobjectCallback) proc delete*(qobject: QObject) = ## Delete the given QObject + let qobjectPtr = addr(qobject[]) + qobjectRegistry.del qobjectPtr dos_qobject_delete(qobject.data) proc registerSlot*(qobject: var QObject, @@ -275,5 +284,3 @@ proc delete(view: QQuickView) = ## Delete the given QQuickView dos_qquickview_delete(view) - - diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 718bb44..ccba20d 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -7,10 +7,11 @@ type QApplication* = distinct pointer ## A QApplication DynamicQObject* = distinct pointer ## internal representation of a QObject, as recognised by DOtherSide - QObject* {.inheritable.} = ref object of RootObj ## A QObject + QObjectObj* = object of RootObj ## A QObject name*: string data*: DynamicQObject slots*: Table[string, cint] signals*: Table[string, cint] properties*: Table[string, cint] + QObject* = ref QObjectObj QQuickView* = distinct pointer ## A QQuickView From 8bd7353b823f2d4ec93de1510ca3a5afcf5e74cf Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 6 Jan 2015 23:23:32 +0000 Subject: [PATCH 04/58] simplify copy of openarray in emit --- Nim/NimQml/NimQml.nim | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 84d5ab9..f30e37c 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -249,9 +249,7 @@ proc registerProperty*(qobject: var QObject, proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) = ## Emit the signal with the given name and values if args.len > 0: - var copy: seq[QVariant] - for i in 0..args.len-1: - copy.add(args[i]) + var copy = @args dos_qobject_signal_emit(qobject.data, signalName, args.len.cint, addr(copy[0])) else: dos_qobject_signal_emit(qobject.data, signalName, 0, nil) From cf4ae16201d67e917b7e500f9fa6b5e434bd5f7a Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 6 Jan 2015 23:34:20 +0000 Subject: [PATCH 05/58] changed some unsafe casts to type conversions, removed some unnecessary var parameters --- Nim/NimQml/NimQml.nim | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index f30e37c..9c008ea 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -90,11 +90,11 @@ proc intVal*(variant: QVariant): int = ## Return the QVariant value as int var rawValue: cint dos_qvariant_toInt(variant, rawValue) - result = cast[int](rawValue) + result = rawValue.cint proc `intVal=`*(variant: QVariant, value: int) = ## Sets the QVariant value int value - var rawValue = cast[cint](value) + var rawValue = value.cint dos_qvariant_setInt(variant, rawValue) proc boolVal*(variant: QVariant): bool = @@ -215,36 +215,36 @@ proc delete*(qobject: QObject) = qobjectRegistry.del qobjectPtr dos_qobject_delete(qobject.data) -proc registerSlot*(qobject: var QObject, +proc registerSlot*(qobject: QObject, slotName: string, metaTypes: openarray[QMetaType]) = ## Register a slot in the QObject with the given name and signature # Copy the metatypes array var copy = toCIntSeq(metatypes) var index: cint - dos_qobject_slot_create(qobject.data, slotName, cint(copy.len), cast[ptr cint](addr(copy[0])), index) + dos_qobject_slot_create(qobject.data, slotName, cint(copy.len), addr(copy[0].cint), index) qobject.slots[slotName] = index -proc registerSignal*(qobject: var QObject, +proc registerSignal*(qobject: QObject, signalName: string, metatypes: openarray[QMetaType]) = ## Register a signal in the QObject with the given name and signature var index: cint if metatypes.len > 0: var copy = toCIntSeq(metatypes) - dos_qobject_signal_create(qobject.data, signalName, cast[cint](copy.len), cast[ptr cint](addr(copy[0])), index) + dos_qobject_signal_create(qobject.data, signalName, copy.len.cint, addr(copy[0].cint), index) else: - dos_qobject_signal_create(qobject.data, signalName, 0, cast[ptr cint](0), index) + dos_qobject_signal_create(qobject.data, signalName, 0, nil, index) qobject.signals[signalName] = index -proc registerProperty*(qobject: var QObject, +proc registerProperty*(qobject: QObject, propertyName: string, propertyType: QMetaType, readSlot: string, writeSlot: string, notifySignal: string) = ## Register a property in the QObject with the given name and type. - dos_qobject_property_create(qobject.data, propertyName, cast[cint](propertyType), readSlot, writeSlot, notifySignal) + dos_qobject_property_create(qobject.data, propertyName, propertyType.cint, readSlot, writeSlot, notifySignal) proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) = ## Emit the signal with the given name and values From 685236d11e910c16d7729dbee283549e80c1014a Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 8 Jan 2015 23:34:17 +0100 Subject: [PATCH 06/58] Initial support for finalizers for QObject and QVariant --- Nim/Examples/SlotsAndProperties/Contact.nim | 29 ++-- Nim/Examples/SlotsAndProperties/main.nim | 3 +- Nim/NimQml/NimQml.nim | 145 +++++++++++++------- Nim/NimQml/NimQmlTypes.nim | 10 +- 4 files changed, 124 insertions(+), 63 deletions(-) diff --git a/Nim/Examples/SlotsAndProperties/Contact.nim b/Nim/Examples/SlotsAndProperties/Contact.nim index 797d82c..0f7fdd5 100644 --- a/Nim/Examples/SlotsAndProperties/Contact.nim +++ b/Nim/Examples/SlotsAndProperties/Contact.nim @@ -4,17 +4,24 @@ import NimQml type Contact = ref object of QObject m_name: string - -template newContact*(): Contact = - var result = Contact(m_name: "initialName") - result.create() - result.m_name = "InitialName" - result.registerSlot("getName", [QMetaType.QString]) - result.registerSlot("setName", [QMetaType.Void, QMetaType.QString]) - result.registerSignal("nameChanged", [QMetaType.Void]) - result.registerProperty("name", QMetaType.QString, "getName", "setName", "nameChanged") - result +proc delete(self: Contact) = + var qobject = self.QObject + qobject.delete() + +proc create(self: Contact) = + var qobject = self.QObject + qobject.create() + self.m_name = "InitialName" + self.registerSlot("getName", [QMetaType.QString]) + self.registerSlot("setName", [QMetaType.Void, QMetaType.QString]) + self.registerSignal("nameChanged", [QMetaType.Void]) + self.registerProperty("name", QMetaType.QString, "getName", "setName", "nameChanged") + +proc newContact*(): Contact = + new(result, delete) + result.create() + method getName*(self: Contact): string = result = self.m_name @@ -30,4 +37,4 @@ method onSlotCalled(self: Contact, slotName: string, args: openarray[QVariant]) of "setName": self.setName(args[1].stringVal) else: - discard() \ No newline at end of file + discard() diff --git a/Nim/Examples/SlotsAndProperties/main.nim b/Nim/Examples/SlotsAndProperties/main.nim index 3e85e9e..261eeb1 100644 --- a/Nim/Examples/SlotsAndProperties/main.nim +++ b/Nim/Examples/SlotsAndProperties/main.nim @@ -13,8 +13,7 @@ proc mainProc() = engine.create() defer: engine.delete() - var variant: QVariant - variant.create(contact) + var variant = newQVariant(contact) defer: variant.delete() var rootContext: QQmlContext = engine.rootContext() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 9c008ea..e8519ec 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -22,7 +22,7 @@ type QMetaType* {.pure.} = enum ## \ QVariant = cint(41), Void = cint(43) -var qobjectRegistry = initTable[ptr QObjectObj, QObject]() +var qobjectRegistry = initTable[ptr QObjectObj, bool]() proc debugMsg(message: string) = echo "NimQml: ", message @@ -42,80 +42,118 @@ proc debugMsg(typeName: string, procName: string, userMessage: string) = debugMsg(message) # QVariant -proc dos_qvariant_create(variant: var QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_int(variant: var QVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_bool(variant: var QVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_string(variant: var QVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_qobject(variant: var QVariant, value: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_delete(variant: QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_isnull(variant: QVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toInt(variant: QVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toBool(variant: QVariant, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toString(variant: QVariant, value: var cstring, length: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setInt(variant: QVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setBool(variant: QVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setString(variant: QVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create(variant: var RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_int(variant: var RawQVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_bool(variant: var RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_string(variant: var RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qobject(variant: var RawQVariant, value: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toBool(variant: RawQVariant, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toString(variant: RawQVariant, value: var cstring, length: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setInt(variant: RawQVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setBool(variant: RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setString(variant: RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc create*(variant: var QVariant) = +proc create*(variant: QVariant) = ## Create a new QVariant - dos_qvariant_create(variant) + dos_qvariant_create(variant.data) + variant.deleted = false -proc create*(variant: var QVariant, value: cint) = +proc create*(variant: QVariant, value: cint) = ## Create a new QVariant given a cint value - dos_qvariant_create_int(variant, value) + dos_qvariant_create_int(variant.data, value) + variant.deleted = false -proc create*(variant: var QVariant, value: bool) = +proc create*(variant: QVariant, value: bool) = ## Create a new QVariant given a bool value - dos_qvariant_create_bool(variant, value) + dos_qvariant_create_bool(variant.data, value) + variant.deleted = false -proc create*(variant: var QVariant, value: string) = +proc create*(variant: QVariant, value: string) = ## Create a new QVariant given a string value - dos_qvariant_create_string(variant, value) + dos_qvariant_create_string(variant.data, value) + variant.deleted = false -proc create*(variant: var QVariant, value: QObject) = +proc create*(variant: QVariant, value: QObject) = ## Create a new QVariant given a QObject - dos_qvariant_create_qobject(variant, value.data) - + dos_qvariant_create_qobject(variant.data, value.data) + variant.deleted = false + proc delete*(variant: QVariant) = ## Delete a QVariant + if variant.deleted: + return debugMsg("QVariant", "delete") - dos_qvariant_delete(variant) + dos_qvariant_delete(variant.data) + variant.deleted = true +proc newQVariant*(): QVariant = + ## Return a new QVariant + new(result, delete) + result.create() + +proc newQVariant*(value: cint): QVariant = + new(result, delete) + result.create(value) + +proc newQVariant*(value: bool): QVariant = + new(result, delete) + result.create(value) + +proc newQVariant*(value: string): QVariant = + new(result, delete) + result.create(value) + +proc newQVariant*(value: QObject): QVariant = + new(result, delete) + result.create(value) + +proc newQVariant*(value: RawQVariant, takeOwnership: bool = false): QVariant = + if takeOwnership: + new(result, delete) + result.deleted = false + else: + new(result) + result.deleted = true # Disable explicit delete + result.data = value + proc isNull*(variant: QVariant): bool = ## Return true if the QVariant value is null, false otherwise - dos_qvariant_isnull(variant, result) + dos_qvariant_isnull(variant.data, result) proc intVal*(variant: QVariant): int = ## Return the QVariant value as int var rawValue: cint - dos_qvariant_toInt(variant, rawValue) + dos_qvariant_toInt(variant.data, rawValue) result = rawValue.cint proc `intVal=`*(variant: QVariant, value: int) = ## Sets the QVariant value int value var rawValue = value.cint - dos_qvariant_setInt(variant, rawValue) + dos_qvariant_setInt(variant.data, rawValue) proc boolVal*(variant: QVariant): bool = ## Return the QVariant value as bool - dos_qvariant_toBool(variant, result) + dos_qvariant_toBool(variant.data, result) proc `boolVal=`*(variant: QVariant, value: bool) = ## Sets the QVariant bool value - dos_qvariant_setBool(variant, value) + dos_qvariant_setBool(variant.data, value) proc stringVal*(variant: QVariant): string = ## Return the QVariant value as string var rawCString: cstring var rawCStringLength: cint - dos_qvariant_toString(variant, rawCString, rawCStringLength) + dos_qvariant_toString(variant.data, rawCString, rawCStringLength) result = $rawCString dos_chararray_delete(rawCString) proc `stringVal=`*(variant: QVariant, value: string) = ## Sets the QVariant string value - dos_qvariant_setString(variant, value) + dos_qvariant_setString(variant.data, value) # QQmlApplicationEngine @@ -142,11 +180,11 @@ proc delete*(engine: QQmlApplicationEngine) = dos_qqmlapplicationengine_delete(engine) # QQmlContext -proc dos_qqmlcontext_setcontextproperty(context: QQmlContext, propertyName: cstring, propertyValue: QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlcontext_setcontextproperty(context: QQmlContext, propertyName: cstring, propertyValue: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc setContextProperty*(context: QQmlContext, propertyName: string, propertyValue: QVariant) = ## Sets a new property with the given value - dos_qqmlcontext_setcontextproperty(context, propertyName, propertyValue) + dos_qqmlcontext_setcontextproperty(context, propertyName, propertyValue.data) # QApplication proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} @@ -166,20 +204,20 @@ proc delete*(application: QApplication) = dos_qguiapplication_delete() # QObject -type QVariantArray {.unchecked.} = array[0..0, QVariant] -type QVariantArrayPtr = ptr QVariantArray +type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant] +type RawQVariantArrayPtr = ptr RawQVariantArray -proc toVariantSeq(args: QVariantArrayPtr, numArgs: cint): seq[QVariant] = +proc toVariantSeq(args: RawQVariantArrayPtr, numArgs: cint): seq[QVariant] = result = @[] for i in 0..numArgs-1: - result.add(args[i]) + result.add(newQVariant(args[i])) proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = result = @[] for metaType in metaTypes: result.add(cint(metaType)) -type QObjectCallBack = proc(nimobject: ptr QObjectObj, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl.} +type QObjectCallBack = proc(nimobject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl.} proc dos_qobject_create(qobject: var DynamicQObject, nimobject: ptr QObjectObj, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_delete(qobject: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -193,27 +231,38 @@ method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVari ## Subclasses can override the given method for handling the slot call discard() -proc qobjectCallback(nimobject: ptr QObjectObj, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.cdecl, exportc.} = - let qobject = qobjectRegistry[nimobject] - assert qobject != nil, "expecting valid QObject" - # forward to the QObject subtype instance - qobject.onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments)) +proc qobjectCallback(nimObject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl, exportc.} = + if not qobjectRegistry[nimObject]: + return + let qobject = cast[QObject](nimObject) + GC_ref(qobject) + qobject.onSlotCalled(newQVariant(slotName).stringVal, arguments.toVariantSeq(numArguments)) + GC_unref(qobject) proc create*(qobject: QObject) = ## Create a new QObject - let internalRef = qobject + debugMsg("QObject", "create") let qobjectPtr = addr(qobject[]) - qobjectRegistry[qobjectPtr] = internalRef + qobjectRegistry[qobjectPtr] = true qobject.name = "QObject" + qobject.deleted = false qobject.slots = initTable[string,cint]() qobject.signals = initTable[string, cint]() dos_qobject_create(qobject.data, qobjectPtr, qobjectCallback) - + proc delete*(qobject: QObject) = ## Delete the given QObject + if qobject.deleted: + return + debugMsg("QObject", "delete") let qobjectPtr = addr(qobject[]) qobjectRegistry.del qobjectPtr dos_qobject_delete(qobject.data) + qobject.deleted = true + +proc newQObject*(): QObject = + new(result, delete) + result.create() proc registerSlot*(qobject: QObject, slotName: string, diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index ccba20d..e30c0cb 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -1,17 +1,23 @@ import tables type - QVariant* = distinct pointer ## A QVariant + RawQVariant* = distinct pointer ## A QVariant + QVariant* = ref object of RootObj + data*: RawQVariant + deleted*: bool + QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine QQmlContext* = distinct pointer ## A QQmlContext QApplication* = distinct pointer ## A QApplication DynamicQObject* = distinct pointer - ## internal representation of a QObject, as recognised by DOtherSide + QObjectObj* = object of RootObj ## A QObject name*: string data*: DynamicQObject slots*: Table[string, cint] signals*: Table[string, cint] properties*: Table[string, cint] + deleted*: bool QObject* = ref QObjectObj + QQuickView* = distinct pointer ## A QQuickView From 7dcfa8255ec0480c8c228255d1a4c5ba750f6515 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 8 Jan 2015 23:41:33 +0100 Subject: [PATCH 07/58] Added some documentation --- Nim/NimQml/NimQml.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index e8519ec..aff7f7c 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -96,22 +96,27 @@ proc newQVariant*(): QVariant = result.create() proc newQVariant*(value: cint): QVariant = + ## Return a new QVariant given a cint new(result, delete) result.create(value) proc newQVariant*(value: bool): QVariant = + ## Return a new QVariant given a bool new(result, delete) result.create(value) proc newQVariant*(value: string): QVariant = + ## Return a new QVariant given a string new(result, delete) result.create(value) proc newQVariant*(value: QObject): QVariant = + ## Return a new QVariant given a QObject new(result, delete) result.create(value) proc newQVariant*(value: RawQVariant, takeOwnership: bool = false): QVariant = + ## Return a new QVariant given a raw QVariant pointer if takeOwnership: new(result, delete) result.deleted = false @@ -261,6 +266,7 @@ proc delete*(qobject: QObject) = qobject.deleted = true proc newQObject*(): QObject = + ## Return a new QObject new(result, delete) result.create() From 76894f3bc395daea41f2f06c4eda6844088e6a6d Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 8 Jan 2015 23:51:23 +0100 Subject: [PATCH 08/58] Updated the SimpleData example --- Nim/Examples/SimpleData/main.nim | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index 01f5eb9..622d645 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -11,20 +11,14 @@ proc mainProc() = engine.create() defer: engine.delete() - var qVar1: QVariant - qVar1.create() + var qVar1 = newQVariant(10) defer: qVar1.delete() - qVar1.intVal = 10 - var qVar2: QVariant - qVar2.create() + var qVar2 = newQVariant("Hello World") defer: qVar2.delete() - qVar2.stringVal = "Hello World" - var qVar3: QVariant - qVar3.create() + var qVar3 = newQVariant(false) defer: qVar3.delete() - qVar3.boolVal = false engine.rootContext.setContextProperty("qVar1", qVar1) engine.rootContext.setContextProperty("qVar2", qVar2) From 3857a48d865eba357b46f9f5eb0c7820004828ed Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 10 Jan 2015 11:26:23 +0100 Subject: [PATCH 09/58] Added support for creating a new QVariant given another and for assign operations --- DOtherSide/DOtherSide/DOtherSide.cpp | 15 +++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 8bbbc3d..f9ea951 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -146,6 +146,14 @@ void dos_qvariant_create_string(void** vptr, const char* value) *vptr = new QVariant(value); } +void dos_qvariant_create_qvariant(void** vptr, void* other) +{ + auto newQVariant = new QVariant(); + auto otherQVariant = reinterpret_cast(other); + *newQVariant = *otherQVariant; + *vptr = newQVariant; +} + void dos_qvariant_create_qobject(void **vptr, void* value) { auto qobject = reinterpret_cast(value); @@ -166,6 +174,13 @@ void dos_qvariant_delete(void *vptr) delete variant; } +void dos_qvariant_assign(void* vptr, void* other) +{ + auto leftQVariant = reinterpret_cast(vptr); + auto rightQVariant = reinterpret_cast(other); + *leftQVariant = *rightQVariant; +} + void dos_qvariant_toInt(void* vptr, int& value) { auto variant = reinterpret_cast(vptr); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index cb1abe7..f118496 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -43,6 +43,7 @@ extern "C" 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_toInt(void* vptr, int& value); void dos_qvariant_setInt(void* vptr, int value); void dos_qvariant_toBool(void* vptr, bool& value); @@ -51,6 +52,7 @@ extern "C" void dos_qvariant_setString(void* vptr, const char* value); void dos_qvariant_isnull(void *vptr, bool& isNull); void dos_qvariant_delete(void *vptr); + void dos_qvariant_assign(void* vptr, void* other); // QObject void dos_qobject_create(void **vptr, From 4d50125d4bc7c5d2ac86bc444f4dbdf8edf4e58d Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 10 Jan 2015 11:29:32 +0100 Subject: [PATCH 10/58] QVariant are not copied by default when passed in the onSlotCalled method --- Nim/NimQml/NimQml.nim | 83 ++++++++++++++++++++++++-------------- Nim/NimQml/NimQmlTypes.nim | 21 +++++----- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index aff7f7c..90f1c14 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -1,4 +1,4 @@ -import NimQmlTypes +include NimQmlTypes import tables ## NimQml aims to provide binding to the QML for the Nim programming language @@ -47,6 +47,7 @@ proc dos_qvariant_create_int(variant: var RawQVariant, value: cint) {.cdecl, dyn proc dos_qvariant_create_bool(variant: var RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_string(variant: var RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_qobject(variant: var RawQVariant, value: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -55,6 +56,7 @@ proc dos_qvariant_toString(variant: RawQVariant, value: var cstring, length: var proc dos_qvariant_setInt(variant: RawQVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setBool(variant: RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setString(variant: RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_assign(leftValue: RawQVariant, rightValue: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: QVariant) = @@ -81,14 +83,22 @@ proc create*(variant: QVariant, value: QObject) = ## Create a new QVariant given a QObject dos_qvariant_create_qobject(variant.data, value.data) variant.deleted = false + +proc create*(variant: QVariant, value: RawQVariant) = + ## Create a new QVariant givan another QVariant + dos_qvariant_create_qvariant(variant.data, value) + variant.deleted = false + +proc create*(variant: QVariant, value: QVariant) = + create(variant, value.data) proc delete*(variant: QVariant) = ## Delete a QVariant - if variant.deleted: - return - debugMsg("QVariant", "delete") - dos_qvariant_delete(variant.data) - variant.deleted = true + if not variant.deleted: + debugMsg("QVariant", "delete") + dos_qvariant_delete(variant.data) + variant.data = nil.RawQVariant + variant.deleted = true proc newQVariant*(): QVariant = ## Return a new QVariant @@ -115,15 +125,15 @@ proc newQVariant*(value: QObject): QVariant = new(result, delete) result.create(value) -proc newQVariant*(value: RawQVariant, takeOwnership: bool = false): QVariant = +proc newQVariant*(value: RawQVariant): QVariant = ## Return a new QVariant given a raw QVariant pointer - if takeOwnership: - new(result, delete) - result.deleted = false - else: - new(result) - result.deleted = true # Disable explicit delete - result.data = value + new(result, delete) + result.create(value) + +proc newQVariant*(value: QVariant): QVariant = + ## Return a new QVariant given another QVariant + new(result, delete) + result.create(value) proc isNull*(variant: QVariant): bool = ## Return true if the QVariant value is null, false otherwise @@ -160,6 +170,9 @@ proc `stringVal=`*(variant: QVariant, value: string) = ## Sets the QVariant string value dos_qvariant_setString(variant.data, value) +proc assign*(leftValue: QVariant, rightValue: QVariant): QVariant = + ## Assign a QVariant with another. The inner value of the QVariant is copied + dos_qvariant_assign(leftValue.data, rightValue.data) # QQmlApplicationEngine proc dos_qqmlapplicationengine_create(engine: var QQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -217,6 +230,10 @@ proc toVariantSeq(args: RawQVariantArrayPtr, numArgs: cint): seq[QVariant] = for i in 0..numArgs-1: result.add(newQVariant(args[i])) +proc delete(sequence: seq[QVariant]) = + for variant in sequence: + variant.delete + proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = result = @[] for metaType in metaTypes: @@ -237,33 +254,39 @@ method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVari discard() proc qobjectCallback(nimObject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl, exportc.} = - if not qobjectRegistry[nimObject]: - return - let qobject = cast[QObject](nimObject) - GC_ref(qobject) - qobject.onSlotCalled(newQVariant(slotName).stringVal, arguments.toVariantSeq(numArguments)) - GC_unref(qobject) + if qobjectRegistry[nimObject]: + let qobject = cast[QObject](nimObject) + GC_ref(qobject) + let slotNameAsQVariant = newQVariant(slotName) + defer: slotNameAsQVariant.delete + let argumentsAsQVariant = arguments.toVariantSeq(numArguments) + defer: argumentsAsQVariant.delete + # Forward to args to the slot + qobject.onSlotCalled(slotNameAsQVariant.stringVal, argumentsAsQVariant) + # Update the slot return value + dos_qvariant_assign(arguments[0], argumentsAsQVariant[0].data) + GC_unref(qobject) proc create*(qobject: QObject) = ## Create a new QObject debugMsg("QObject", "create") - let qobjectPtr = addr(qobject[]) - qobjectRegistry[qobjectPtr] = true - qobject.name = "QObject" qobject.deleted = false qobject.slots = initTable[string,cint]() qobject.signals = initTable[string, cint]() + qobject.properties = initTable[string, cint]() + let qobjectPtr = addr(qobject[]) dos_qobject_create(qobject.data, qobjectPtr, qobjectCallback) + qobjectRegistry[qobjectPtr] = true proc delete*(qobject: QObject) = ## Delete the given QObject - if qobject.deleted: - return - debugMsg("QObject", "delete") - let qobjectPtr = addr(qobject[]) - qobjectRegistry.del qobjectPtr - dos_qobject_delete(qobject.data) - qobject.deleted = true + if not qobject.deleted: + debugMsg("QObject", "delete") + let qobjectPtr = addr(qobject[]) + qobjectRegistry.del qobjectPtr + dos_qobject_delete(qobject.data) + qobject.data = nil.DynamicQObject + qobject.deleted = true proc newQObject*(): QObject = ## Return a new QObject diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index e30c0cb..81b0e98 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -1,23 +1,22 @@ import tables type - RawQVariant* = distinct pointer ## A QVariant + RawQVariant = distinct pointer ## A QVariant QVariant* = ref object of RootObj - data*: RawQVariant - deleted*: bool + data: RawQVariant + deleted: bool QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine QQmlContext* = distinct pointer ## A QQmlContext QApplication* = distinct pointer ## A QApplication - DynamicQObject* = distinct pointer - QObjectObj* = object of RootObj ## A QObject - name*: string - data*: DynamicQObject - slots*: Table[string, cint] - signals*: Table[string, cint] - properties*: Table[string, cint] - deleted*: bool + DynamicQObject = distinct pointer + QObjectObj = object of RootObj ## A QObject + data: DynamicQObject + slots: Table[string, cint] + signals: Table[string, cint] + properties: Table[string, cint] + deleted: bool QObject* = ref QObjectObj QQuickView* = distinct pointer ## A QQuickView From d0f01b092af3dca0f5e7c140319b63de01a5762c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 10 Jan 2015 11:58:24 +0100 Subject: [PATCH 11/58] Added constructors for QApplication, QQmlApplicationEngine and QQuickView --- Nim/NimQml/NimQml.nim | 88 ++++++++++++++++++++++++-------------- Nim/NimQml/NimQmlTypes.nim | 32 +++++++++----- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 90f1c14..b250f4d 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -1,5 +1,4 @@ include NimQmlTypes -import tables ## NimQml aims to provide binding to the QML for the Nim programming language @@ -46,7 +45,7 @@ proc dos_qvariant_create(variant: var RawQVariant) {.cdecl, dynlib:"libDOtherSid proc dos_qvariant_create_int(variant: var RawQVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_bool(variant: var RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_string(variant: var RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_qobject(variant: var RawQVariant, value: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -175,27 +174,36 @@ proc assign*(leftValue: QVariant, rightValue: QVariant): QVariant = dos_qvariant_assign(leftValue.data, rightValue.data) # QQmlApplicationEngine -proc dos_qqmlapplicationengine_create(engine: var QQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_load(engine: QQmlApplicationEngine, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_context(engine: QQmlApplicationEngine, context: var QQmlContext) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_delete(engine: QQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_create(engine: var RawQQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_load(engine: RawQQmlApplicationEngine, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_context(engine: RawQQmlApplicationEngine, context: var QQmlContext) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_delete(engine: RawQQmlApplicationEngine) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc create*(engine: var QQmlApplicationEngine) = +proc create*(engine: QQmlApplicationEngine) = ## Create an new QQmlApplicationEngine - dos_qqmlapplicationengine_create(engine) - + dos_qqmlapplicationengine_create(engine.data) + engine.deleted = false + proc load*(engine: QQmlApplicationEngine, filename: cstring) = ## Load the given Qml file - dos_qqmlapplicationengine_load(engine, filename) + dos_qqmlapplicationengine_load(engine.data, filename) proc rootContext*(engine: QQmlApplicationEngine): QQmlContext = ## Return the engine root context - dos_qqmlapplicationengine_context(engine, result) + dos_qqmlapplicationengine_context(engine.data, result) proc delete*(engine: QQmlApplicationEngine) = ## Delete the given QQmlApplicationEngine - debugMsg("QQmlApplicationEngine", "delete") - dos_qqmlapplicationengine_delete(engine) + if not engine.deleted: + debugMsg("QQmlApplicationEngine", "delete") + dos_qqmlapplicationengine_delete(engine.data) + engine.data = nil.RawQQmlApplicationEngine + engine.deleted = true + +proc newQQmlApplicationEngine*(): QQmlApplicationEngine = + ## Return a new QQmlApplicationEngine + new(result, delete) + result.create() # QQmlContext proc dos_qqmlcontext_setcontextproperty(context: QQmlContext, propertyName: cstring, propertyValue: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -212,6 +220,7 @@ proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(application: QApplication) = ## Create a new QApplication dos_qguiapplication_create() + application.deleted = false proc exec*(application: QApplication) = ## Start the Qt event loop @@ -219,7 +228,15 @@ proc exec*(application: QApplication) = proc delete*(application: QApplication) = ## Delete the given QApplication - dos_qguiapplication_delete() + if not application.deleted: + debugMsg("QApplication", "delete") + dos_qguiapplication_delete() + application.deleted = true + +proc newQApplication*(): QApplication = + ## Return a new QApplication + new(result, delete) + result.create() # QObject type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant] @@ -241,12 +258,12 @@ proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = type QObjectCallBack = proc(nimobject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl.} -proc dos_qobject_create(qobject: var DynamicQObject, nimobject: ptr QObjectObj, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_delete(qobject: DynamicQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_slot_create(qobject: DynamicQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_signal_create(qobject: DynamicQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_signal_emit(qobject: DynamicQObject, signalName: cstring, argumentsCount: cint, arguments: ptr QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_property_create(qobject: DynamicQObject, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_create(qobject: var RawQObject, nimobject: ptr QObjectObj, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_delete(qobject: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_slot_create(qobject: RawQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_signal_create(qobject: RawQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_signal_emit(qobject: RawQObject, signalName: cstring, argumentsCount: cint, arguments: ptr QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_property_create(qobject: RawQObject, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVariant]) = ## Called from the NimQml bridge when a slot is called from Qml. @@ -285,7 +302,7 @@ proc delete*(qobject: QObject) = let qobjectPtr = addr(qobject[]) qobjectRegistry.del qobjectPtr dos_qobject_delete(qobject.data) - qobject.data = nil.DynamicQObject + qobject.data = nil.RawQObject qobject.deleted = true proc newQObject*(): QObject = @@ -333,30 +350,39 @@ proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) dos_qobject_signal_emit(qobject.data, signalName, 0, nil) # QQuickView -proc dos_qquickview_create(view: var QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_delete(view: QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_show(view: QQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_source(view: QQuickView, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_set_source(view: QQuickView, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_create(view: var RawQQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_delete(view: RawQQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_show(view: RawQQuickView) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_source(view: RawQQuickView, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_set_source(view: RawQQuickView, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create(view: var QQuickView) = ## Create a new QQuickView - dos_qquickview_create(view) + dos_qquickview_create(view.data) + view.deleted = false proc source(view: QQuickView): cstring = ## Return the source Qml file loaded by the view var length: int - dos_qquickview_source(view, result, length) + dos_qquickview_source(view.data, result, length) proc `source=`(view: QQuickView, filename: cstring) = ## Sets the source Qml file laoded by the view - dos_qquickview_set_source(view, filename) + dos_qquickview_set_source(view.data, filename) proc show(view: QQuickView) = ## Sets the view visible - dos_qquickview_show(view) + dos_qquickview_show(view.data) proc delete(view: QQuickView) = ## Delete the given QQuickView - dos_qquickview_delete(view) + if not view.deleted: + debugMsg("QQuickView", "delete") + dos_qquickview_delete(view.data) + view.data = nil.RawQQuickView + view.deleted = true +proc newQQuickView*(): QQuickView = + ## Return a new QQuickView + new(result, delete) + result.create() diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 81b0e98..7308517 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -1,22 +1,32 @@ import tables type - RawQVariant = distinct pointer ## A QVariant - QVariant* = ref object of RootObj + RawQVariant = distinct pointer + QVariant* = ref object of RootObj ## A QVariant data: RawQVariant deleted: bool - - QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine - QQmlContext* = distinct pointer ## A QQmlContext - QApplication* = distinct pointer ## A QApplication - DynamicQObject = distinct pointer - QObjectObj = object of RootObj ## A QObject - data: DynamicQObject + RawQQmlApplicationEngine = distinct pointer + QQmlApplicationEngine* = ref object of RootObj ## A QQmlApplicationEngine + data: RawQQmlApplicationEngine + deleted: bool + + QApplication* = ref object of RootObj ## A QApplication + deleted: bool + + RawQObject = distinct pointer + QObjectObj = object of RootObj + data: RawQObject slots: Table[string, cint] signals: Table[string, cint] properties: Table[string, cint] deleted: bool - QObject* = ref QObjectObj + QObject* = ref QObjectObj ## A QObject + + RawQQuickView = distinct pointer + QQuickView = ref object of RootObj ## A QQuickView + data: RawQQuickView + deleted: bool + + QQmlContext* = distinct pointer ## A QQmlContext - QQuickView* = distinct pointer ## A QQuickView From 3613bfea4e38e76290f30c2265b08eb5521677a1 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 10 Jan 2015 11:58:41 +0100 Subject: [PATCH 12/58] Fixed examples --- Nim/Examples/HelloWorld/main.nim | 7 +++--- Nim/Examples/QtObjectMacro/Contact.nim | 28 ++++++++++++++---------- Nim/Examples/QtObjectMacro/main.nim | 12 ++++------ Nim/Examples/SimpleData/main.nim | 8 +++---- Nim/Examples/SlotsAndProperties/main.nim | 10 ++++----- 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/Nim/Examples/HelloWorld/main.nim b/Nim/Examples/HelloWorld/main.nim index 897a160..a0bc25f 100644 --- a/Nim/Examples/HelloWorld/main.nim +++ b/Nim/Examples/HelloWorld/main.nim @@ -3,12 +3,10 @@ import macros import typeinfo proc mainProc() = - var app: QApplication - app.create() + var app = newQApplication() defer: app.delete() - var engine: QQmlApplicationEngine - engine.create() + var engine = newQQmlApplicationEngine() defer: engine.delete() engine.load("main.qml") @@ -17,3 +15,4 @@ proc mainProc() = when isMainModule: mainProc() +GC_fullcollect() diff --git a/Nim/Examples/QtObjectMacro/Contact.nim b/Nim/Examples/QtObjectMacro/Contact.nim index 7b9c79e..e404895 100644 --- a/Nim/Examples/QtObjectMacro/Contact.nim +++ b/Nim/Examples/QtObjectMacro/Contact.nim @@ -6,20 +6,24 @@ QtObject: type Contact* = ref object of QObject m_name: string - template newContact*(): Contact = - var result = Contact(m_name: "initialName") - result.create - result - - method getName*(contact: Contact): string {.slot.} = - result = contact.m_name + proc delete(self: Contact) = + var qobject = self.QObject + qobject.delete() - method nameChanged*(contact: Contact) {.signal.} + proc newContact*(): Contact = + new(result, delete) + result.m_name = "InitialName" + result.create - method setName*(contact: Contact, name: string) {.slot.} = - if contact.m_name != name: - contact.m_name = name - contact.nameChanged() + method getName*(self: Contact): string {.slot.} = + result = self.m_name + + method nameChanged*(self: Contact) {.signal.} + + method setName*(self: Contact, name: string) {.slot.} = + if self.m_name != name: + self.m_name = name + self.nameChanged() QtProperty[string] name: read = getName diff --git a/Nim/Examples/QtObjectMacro/main.nim b/Nim/Examples/QtObjectMacro/main.nim index 9c45926..ba4ea02 100644 --- a/Nim/Examples/QtObjectMacro/main.nim +++ b/Nim/Examples/QtObjectMacro/main.nim @@ -2,23 +2,19 @@ import NimQml import Contact proc mainProc() = - var app: QApplication - app.create() + var app = newQApplication() defer: app.delete() var contact = newContact() defer: contact.delete() - var engine: QQmlApplicationEngine - engine.create() + var engine = newQQmlApplicationEngine() defer: engine.delete() - var variant: QVariant - variant.create(contact) + var variant = newQVariant(contact) defer: variant.delete() - var rootContext: QQmlContext = engine.rootContext() - rootContext.setContextProperty("contact", variant) + engine.rootContext.setContextProperty("contact", variant) engine.load("main.qml") app.exec() diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index 622d645..2022850 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -3,12 +3,10 @@ import macros import typeinfo proc mainProc() = - var app: QApplication - app.create() + var app = newQApplication() defer: app.delete() - var engine: QQmlApplicationEngine - engine.create() + var engine = newQQmlApplicationEngine() defer: engine.delete() var qVar1 = newQVariant(10) @@ -23,10 +21,10 @@ proc mainProc() = engine.rootContext.setContextProperty("qVar1", qVar1) engine.rootContext.setContextProperty("qVar2", qVar2) engine.rootContext.setContextProperty("qVar3", qVar2) - engine.load("main.qml") app.exec() when isMainModule: mainProc() +GC_fullcollect() diff --git a/Nim/Examples/SlotsAndProperties/main.nim b/Nim/Examples/SlotsAndProperties/main.nim index 261eeb1..98e8cef 100644 --- a/Nim/Examples/SlotsAndProperties/main.nim +++ b/Nim/Examples/SlotsAndProperties/main.nim @@ -2,25 +2,23 @@ import NimQml import Contact proc mainProc() = - var app: QApplication - app.create() + var app = newQApplication() defer: app.delete() var contact = newContact() defer: contact.delete() - var engine: QQmlApplicationEngine - engine.create() + var engine = newQQmlApplicationEngine() defer: engine.delete() var variant = newQVariant(contact) defer: variant.delete() - var rootContext: QQmlContext = engine.rootContext() - rootContext.setContextProperty("contact", variant) + engine.rootContext.setContextProperty("contact", variant) engine.load("main.qml") app.exec() when isMainModule: mainProc() +GC_fullcollect() From d1c2dbc224b409fc5afb7901d52c21299f6cda69 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 12:19:24 +0100 Subject: [PATCH 13/58] Removed export statements --- Nim/NimQml/NimQml.nim | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index b250f4d..57f6201 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -2,12 +2,6 @@ include NimQmlTypes ## NimQml aims to provide binding to the QML for the Nim programming language -export QObject -export QApplication -export QVariant -export QQmlApplicationEngine -export QQmlContext - type QMetaType* {.pure.} = enum ## \ ## Qt metatypes values used for specifing the ## signals and slots argument and return types. From df1e3ec72e51a66b9b609565a6f645d89a1e3d02 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 12:58:35 +0100 Subject: [PATCH 14/58] Fixed emit arguments types --- Nim/NimQml/NimQml.nim | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 57f6201..b950270 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -235,12 +235,18 @@ proc newQApplication*(): QApplication = # QObject type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant] type RawQVariantArrayPtr = ptr RawQVariantArray +type RawQVariantSeq = seq[RawQVariant] proc toVariantSeq(args: RawQVariantArrayPtr, numArgs: cint): seq[QVariant] = result = @[] for i in 0..numArgs-1: result.add(newQVariant(args[i])) +proc toRawVariantSeq(args: openarray[QVariant]): RawQVariantSeq = + result = @[] + for variant in args: + result.add(variant.data) + proc delete(sequence: seq[QVariant]) = for variant in sequence: variant.delete @@ -256,7 +262,7 @@ proc dos_qobject_create(qobject: var RawQObject, nimobject: ptr QObjectObj, qobj proc dos_qobject_delete(qobject: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_slot_create(qobject: RawQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_signal_create(qobject: RawQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qobject_signal_emit(qobject: RawQObject, signalName: cstring, argumentsCount: cint, arguments: ptr QVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_signal_emit(qobject: RawQObject, signalName: cstring, argumentsCount: cint, arguments: ptr RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qobject_property_create(qobject: RawQObject, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVariant]) = @@ -338,8 +344,8 @@ proc registerProperty*(qobject: QObject, proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) = ## Emit the signal with the given name and values if args.len > 0: - var copy = @args - dos_qobject_signal_emit(qobject.data, signalName, args.len.cint, addr(copy[0])) + var copy = args.toRawVariantSeq + dos_qobject_signal_emit(qobject.data, signalName, copy.len.cint, addr(copy[0])) else: dos_qobject_signal_emit(qobject.data, signalName, 0, nil) From 8aa9b7f5a2cbb3902b85045af736cd5fbc9f3f2e Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 12:59:24 +0100 Subject: [PATCH 15/58] Fixed typo in SimpleData example --- Nim/Examples/SimpleData/main.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index 2022850..bdb169a 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -20,7 +20,7 @@ proc mainProc() = engine.rootContext.setContextProperty("qVar1", qVar1) engine.rootContext.setContextProperty("qVar2", qVar2) - engine.rootContext.setContextProperty("qVar3", qVar2) + engine.rootContext.setContextProperty("qVar3", qVar3) engine.load("main.qml") app.exec() From e281666ca0ae421fdb5a66e3d82c58b610c74130 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 13:01:46 +0100 Subject: [PATCH 16/58] Added GC_fullcollect() to all examples --- Nim/Examples/HelloWorld/main.nim | 2 +- Nim/Examples/QtObjectMacro/main.nim | 2 +- Nim/Examples/SimpleData/main.nim | 2 +- Nim/Examples/SlotsAndProperties/main.nim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Nim/Examples/HelloWorld/main.nim b/Nim/Examples/HelloWorld/main.nim index a0bc25f..1936404 100644 --- a/Nim/Examples/HelloWorld/main.nim +++ b/Nim/Examples/HelloWorld/main.nim @@ -14,5 +14,5 @@ proc mainProc() = when isMainModule: mainProc() + GC_fullcollect() -GC_fullcollect() diff --git a/Nim/Examples/QtObjectMacro/main.nim b/Nim/Examples/QtObjectMacro/main.nim index ba4ea02..784a67d 100644 --- a/Nim/Examples/QtObjectMacro/main.nim +++ b/Nim/Examples/QtObjectMacro/main.nim @@ -20,4 +20,4 @@ proc mainProc() = when isMainModule: mainProc() - + GC_fullcollect() diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index bdb169a..e614322 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -26,5 +26,5 @@ proc mainProc() = when isMainModule: mainProc() + GC_fullcollect() -GC_fullcollect() diff --git a/Nim/Examples/SlotsAndProperties/main.nim b/Nim/Examples/SlotsAndProperties/main.nim index 98e8cef..e395a41 100644 --- a/Nim/Examples/SlotsAndProperties/main.nim +++ b/Nim/Examples/SlotsAndProperties/main.nim @@ -20,5 +20,5 @@ proc mainProc() = when isMainModule: mainProc() + GC_fullcollect() -GC_fullcollect() From 8868b9a07a9b034cc165cbcb8a09fa9d3491fcf3 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 13:05:23 +0100 Subject: [PATCH 17/58] Added support for constant properties --- DOtherSide/DynamicQObject/DynamicQObject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DOtherSide/DynamicQObject/DynamicQObject.cpp b/DOtherSide/DynamicQObject/DynamicQObject.cpp index dfd3f26..57705d8 100644 --- a/DOtherSide/DynamicQObject/DynamicQObject.cpp +++ b/DOtherSide/DynamicQObject/DynamicQObject.cpp @@ -127,6 +127,8 @@ bool DynamicQObject::registerProperty(const QString& name, auto builder = metaObjectBuilder.addProperty(name.toUtf8(), QMetaObject::normalizedType(typeName), signalIndex); + if (signalIndex == -1) + builder.setConstant(true); }; auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data() From f40d4bc44a3b7e88ac00af6f6586045fbeb6a73c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 13:05:50 +0100 Subject: [PATCH 18/58] Added stop method to QGuiApplication and Float and Double qvariant types --- DOtherSide/DOtherSide/DOtherSide.cpp | 39 +++++++++++++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 9 +++++- Nim/NimQml/NimQml.nim | 43 +++++++++++++++++++++++++++- Nim/NimQml/NimQmlMacros.nim | 29 ++++++++++++------- 4 files changed, 108 insertions(+), 12 deletions(-) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index f9ea951..7152325 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -34,6 +34,11 @@ void dos_qguiapplication_exec() qApp->exec(); } +void dos_qguiapplication_quit() +{ + qApp->quit(); +} + void dos_qqmlapplicationengine_create(void **vptr) { *vptr = new QQmlApplicationEngine(); @@ -162,6 +167,16 @@ void dos_qvariant_create_qobject(void **vptr, void* value) *vptr = variant; } +void dos_qvariant_create_float(void** vptr, float value) +{ + *vptr = new QVariant(value); +} + +void dos_qvariant_create_double(void** vptr, double value) +{ + *vptr = new QVariant(value); +} + void dos_qvariant_isnull(void* vptr, bool& isNull) { auto variant = reinterpret_cast(vptr); @@ -193,6 +208,18 @@ void dos_qvariant_toBool(void* vptr, bool& value) value = variant->toBool(); } +void dos_qvariant_toFloat(void* vptr, float& value) +{ + auto variant = reinterpret_cast(vptr); + value = variant->toFloat(); +} + +void dos_qvariant_toDouble(void* vptr, double& value) +{ + auto variant = reinterpret_cast(vptr); + value = variant->toDouble(); +} + void dos_qvariant_toString(void* vptr, CharPtr& ptr, int& size) { auto variant = reinterpret_cast(vptr); @@ -211,6 +238,18 @@ void dos_qvariant_setBool(void* vptr, bool value) *variant = value; } +void dos_qvariant_setFloat(void* vptr, float value) +{ + auto variant = reinterpret_cast(vptr); + *variant = value; +} + +void dos_qvariant_setDouble(void* vptr, double value) +{ + auto variant = reinterpret_cast(vptr); + *variant = value; +} + void dos_qvariant_setString(void* vptr, const char* value) { auto variant = reinterpret_cast(vptr); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index f118496..89581bd 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -13,9 +13,10 @@ extern "C" // QGuiApplication void dos_qguiapplication_create(); void dos_qguiapplication_exec(); + void dos_qguiapplication_quit(); void dos_qguiapplication_delete(); - /// QQmlApplicationEngine + // QQmlApplicationEngine void dos_qqmlapplicationengine_create(void** vptr); void dos_qqmlapplicationengine_load(void* vptr, const char* filename); void dos_qqmlapplicationengine_context(void* vptr, void** context); @@ -44,10 +45,16 @@ extern "C" 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_isnull(void *vptr, bool& isNull); diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index b950270..92131fd 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -41,6 +41,8 @@ proc dos_qvariant_create_bool(variant: var RawQVariant, value: bool) {.cdecl, dy proc dos_qvariant_create_string(variant: var RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_float(variant: var RawQVariant, value: cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_double(variant: var RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -50,6 +52,10 @@ proc dos_qvariant_setInt(variant: RawQVariant, value: cint) {.cdecl, dynlib:"lib proc dos_qvariant_setBool(variant: RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setString(variant: RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_assign(leftValue: RawQVariant, rightValue: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toFloat(variant: QVariant, value: var cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setFloat(variant: QVariant, value: float) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toDouble(variant: QVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setDouble(variant: QVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: QVariant) = @@ -81,6 +87,11 @@ proc create*(variant: QVariant, value: RawQVariant) = ## Create a new QVariant givan another QVariant dos_qvariant_create_qvariant(variant.data, value) variant.deleted = false + +proc create*(variant: QVariant, value: cfloat) = + ## Create a new QVariant givan another QVariant + dos_qvariant_create_float(variant.data, value) + variant.deleted = false proc create*(variant: QVariant, value: QVariant) = create(variant, value.data) @@ -127,6 +138,11 @@ proc newQVariant*(value: QVariant): QVariant = ## Return a new QVariant given another QVariant new(result, delete) result.create(value) + +proc newQVariant*(value: float): QVariant = + ## Return a new QVariant given a float + new(result, delete) + result.create(value) proc isNull*(variant: QVariant): bool = ## Return true if the QVariant value is null, false otherwise @@ -151,6 +167,26 @@ proc `boolVal=`*(variant: QVariant, value: bool) = ## Sets the QVariant bool value dos_qvariant_setBool(variant.data, value) +proc floatVal*(variant: QVariant): float = + ## Return the QVariant value as float + var rawValue: cfloat + dos_qvariant_toFloat(variant, rawValue) + result = rawValue.cfloat + +proc `floatVal=`*(variant: QVariant, value: float) = + ## Sets the QVariant float value + dos_qvariant_setFloat(variant, value.cfloat) + +proc doubleVal*(variant: QVariant): cdouble = + ## Return the QVariant value as double + var rawValue: cdouble + dos_qvariant_toDouble(variant, rawValue) + result = rawValue + +proc `doubleVal=`*(variant: QVariant, value: cdouble) = + ## Sets the QVariant double value + dos_qvariant_setDouble(variant, value) + proc stringVal*(variant: QVariant): string = ## Return the QVariant value as string var rawCString: cstring @@ -163,7 +199,7 @@ proc `stringVal=`*(variant: QVariant, value: string) = ## Sets the QVariant string value dos_qvariant_setString(variant.data, value) -proc assign*(leftValue: QVariant, rightValue: QVariant): QVariant = +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) @@ -209,6 +245,7 @@ proc setContextProperty*(context: QQmlContext, propertyName: string, propertyVal # QApplication proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qguiapplication_quit() {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(application: QApplication) = @@ -220,6 +257,10 @@ proc exec*(application: QApplication) = ## Start the Qt event loop dos_qguiapplication_exec() +proc quit*(application: QApplication) = + ## Quit the Qt event loop + dos_qguiapplication_quit() + proc delete*(application: QApplication) = ## Delete the given QApplication if not application.deleted: diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index 40372d7..032b40a 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -17,6 +17,7 @@ let nimFromQtVariant {.compileTime.} = { "int" : "intVal", "string" : "stringVal", "bool" : "boolVal", + "float" : "floatVal", }.toTable let nim2QtMeta {.compileTime.} = { @@ -362,23 +363,31 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = args.add ident "myQObject" for i in 2.. Date: Sun, 11 Jan 2015 13:13:04 +0100 Subject: [PATCH 19/58] Updated the SimpleData example with float --- Nim/Examples/SimpleData/main.nim | 4 ++++ Nim/Examples/SimpleData/main.qml | 1 + 2 files changed, 5 insertions(+) diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index e614322..d20e464 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -17,10 +17,14 @@ proc mainProc() = var qVar3 = newQVariant(false) defer: qVar3.delete() + + var qVar4 = newQVariant(3.5.float) + defer: qVar4.delete() engine.rootContext.setContextProperty("qVar1", qVar1) engine.rootContext.setContextProperty("qVar2", qVar2) engine.rootContext.setContextProperty("qVar3", qVar3) + engine.rootContext.setContextProperty("qVar4", qVar4) engine.load("main.qml") app.exec() diff --git a/Nim/Examples/SimpleData/main.qml b/Nim/Examples/SimpleData/main.qml index 8f32b75..99ecb91 100644 --- a/Nim/Examples/SimpleData/main.qml +++ b/Nim/Examples/SimpleData/main.qml @@ -16,5 +16,6 @@ ApplicationWindow SpinBox { value: qVar1} TextField { text: qVar2} CheckBox { checked: qVar3} + SpinBox { value: qVar4; decimals: 1 } } } From e8075796bc734a6e6f3a4e97f060f68f115d8740 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 13:29:44 +0100 Subject: [PATCH 20/58] Added support for QGuiApplication --- DOtherSide/DOtherSide/CMakeLists.txt | 3 +- DOtherSide/DOtherSide/DOtherSide.cpp | 24 ++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 6 ++++ Nim/NimQml/NimQml.nim | 47 +++++++++++++++++++++++----- Nim/NimQml/NimQmlTypes.nim | 3 ++ 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/DOtherSide/DOtherSide/CMakeLists.txt b/DOtherSide/DOtherSide/CMakeLists.txt index 08d65d0..7397864 100644 --- a/DOtherSide/DOtherSide/CMakeLists.txt +++ b/DOtherSide/DOtherSide/CMakeLists.txt @@ -8,6 +8,7 @@ find_package(Qt5Core) find_package(Qt5Qml) find_package(Qt5Gui) find_package(Qt5Quick) +find_package(Qt5Widgets) set(HEADERS_LIST DOtherSide.h @@ -18,5 +19,5 @@ set(SRC_LIST ) add_library(${PROJECT_NAME} SHARED ${SRC_LIST} ${HEADERS_LIST}) -target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Qml Qt5::Quick DynamicQObject) +target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick DynamicQObject) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../DynamicQObject) \ No newline at end of file diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 7152325..24a5b2a 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -1,5 +1,6 @@ #include "DOtherSide.h" +#include #include #include #include @@ -39,6 +40,29 @@ void dos_qguiapplication_quit() qApp->quit(); } +void dos_qapplication_create() +{ + static int argc = 1; + static char empty[1] = {0}; + static char* argv[] = {empty}; + new QApplication(argc, argv); +} + +void dos_qapplication_delete() +{ + delete qApp; +} + +void dos_qapplication_exec() +{ + qApp->exec(); +} + +void dos_qapplication_quit() +{ + qApp->quit(); +} + void dos_qqmlapplicationengine_create(void **vptr) { *vptr = new QQmlApplicationEngine(); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 89581bd..92a2608 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -16,6 +16,12 @@ extern "C" 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); diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 92131fd..f48b093 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -243,29 +243,29 @@ proc setContextProperty*(context: QQmlContext, propertyName: string, propertyVal dos_qqmlcontext_setcontextproperty(context, propertyName, propertyValue.data) # QApplication -proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} -proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qguiapplication_quit() {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} +proc dos_qapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qapplication_quit() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(application: QApplication) = ## Create a new QApplication - dos_qguiapplication_create() + dos_qapplication_create() application.deleted = false proc exec*(application: QApplication) = ## Start the Qt event loop - dos_qguiapplication_exec() + dos_qapplication_exec() proc quit*(application: QApplication) = ## Quit the Qt event loop - dos_qguiapplication_quit() + dos_qapplication_quit() proc delete*(application: QApplication) = ## Delete the given QApplication if not application.deleted: debugMsg("QApplication", "delete") - dos_qguiapplication_delete() + dos_qapplication_delete() application.deleted = true proc newQApplication*(): QApplication = @@ -273,6 +273,37 @@ proc newQApplication*(): QApplication = new(result, delete) result.create() +# QGuiApplication +proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} +proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qguiapplication_quit() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create*(application: QGuiApplication) = + ## Create a new QApplication + dos_qguiapplication_create() + application.deleted = false + +proc exec*(application: QGuiApplication) = + ## Start the Qt event loop + dos_qguiapplication_exec() + +proc quit*(application: QGuiApplication) = + ## Quit the Qt event loop + dos_qguiapplication_quit() + +proc delete*(application: QGuiApplication) = + ## Delete the given QApplication + if not application.deleted: + debugMsg("QApplication", "delete") + dos_qguiapplication_delete() + application.deleted = true + +proc newQGuiApplication*(): QGuiApplication = + ## Return a new QApplication + new(result, delete) + result.create() + # QObject type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant] type RawQVariantArrayPtr = ptr RawQVariantArray diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 7308517..6874d72 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -13,6 +13,9 @@ type QApplication* = ref object of RootObj ## A QApplication deleted: bool + + QGuiApplication* = ref object of RootObj ## A QGuiApplication + deleted: bool RawQObject = distinct pointer QObjectObj = object of RootObj From 42ded08c7f5c023d5f3915cb6793860e3969a17c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 11 Jan 2015 21:01:00 +0100 Subject: [PATCH 21/58] Added a sample contact application Basic contact app the shows how to expose a list of elements to Qml --- Nim/Examples/CMakeLists.txt | 3 +- Nim/Examples/ContactApp/ApplicationLogic.nim | 34 +++++++++++++ Nim/Examples/ContactApp/CMakeLists.txt | 3 ++ Nim/Examples/ContactApp/Contact.nim | 51 +++++++++++++++++++ Nim/Examples/ContactApp/ContactList.nim | 43 ++++++++++++++++ Nim/Examples/ContactApp/main.nim | 15 ++++++ Nim/Examples/ContactApp/main.qml | 52 ++++++++++++++++++++ 7 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 Nim/Examples/ContactApp/ApplicationLogic.nim create mode 100644 Nim/Examples/ContactApp/CMakeLists.txt create mode 100644 Nim/Examples/ContactApp/Contact.nim create mode 100644 Nim/Examples/ContactApp/ContactList.nim create mode 100644 Nim/Examples/ContactApp/main.nim create mode 100644 Nim/Examples/ContactApp/main.qml diff --git a/Nim/Examples/CMakeLists.txt b/Nim/Examples/CMakeLists.txt index d9f665a..15abd67 100644 --- a/Nim/Examples/CMakeLists.txt +++ b/Nim/Examples/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(HelloWorld) add_subdirectory(SimpleData) add_subdirectory(SlotsAndProperties) -add_subdirectory(QtObjectMacro) \ No newline at end of file +add_subdirectory(QtObjectMacro) +add_subdirectory(ContactApp) \ No newline at end of file diff --git a/Nim/Examples/ContactApp/ApplicationLogic.nim b/Nim/Examples/ContactApp/ApplicationLogic.nim new file mode 100644 index 0000000..6af7c61 --- /dev/null +++ b/Nim/Examples/ContactApp/ApplicationLogic.nim @@ -0,0 +1,34 @@ +import NimQml, NimQmlMacros, Contact, ContactList + +QtObject: + type ApplicationLogic* = ref object of QObject + contactList: ContactList + app: QApplication + + proc delete*(self: ApplicationLogic) = + let qobject = self.QObject + qobject.delete() + + proc newApplicationLogic*(app: QApplication): ApplicationLogic = + new(result, delete) + result.contactList = newContactList() + result.app = app + result.create() + + method getContactList(self: ApplicationLogic): QVariant {.slot.} = + return newQVariant(self.contactList) + + method onLoadTriggered(self: ApplicationLogic) {.slot.} = + echo "Load Triggered" + self.contactList.add("John", "Doo") + + method onSaveTriggered(self: ApplicationLogic) {.slot.} = + echo "Save Triggered" + + method onExitTriggered(self: ApplicationLogic) {.slot.} = + self.app.quit() + + QtProperty[QVariant] contactList: + read = getContactList + write = "" + notify = "" diff --git a/Nim/Examples/ContactApp/CMakeLists.txt b/Nim/Examples/ContactApp/CMakeLists.txt new file mode 100644 index 0000000..28c0862 --- /dev/null +++ b/Nim/Examples/ContactApp/CMakeLists.txt @@ -0,0 +1,3 @@ +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ContactForm.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +add_nim_executable(TARGET ContactApp SOURCES main.nim PATHS ../../NimQml) \ No newline at end of file diff --git a/Nim/Examples/ContactApp/Contact.nim b/Nim/Examples/ContactApp/Contact.nim new file mode 100644 index 0000000..b9c343e --- /dev/null +++ b/Nim/Examples/ContactApp/Contact.nim @@ -0,0 +1,51 @@ +## 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 + +QtObject: + type Contact* = ref object of QObject + name: string + surname: string + + proc delete(self: Contact) = + let qobject = self.QObject + qobject.delete() + + proc newContact*(): Contact = + new(result, delete) + result.name = "" + result.create + + method name*(self: Contact): string {.slot.} = + result = self.name + + method nameChanged*(self: Contact) {.signal.} + + method setName(self: Contact, name: string) {.slot.} = + if self.name != name: + self.name = name + self.nameChanged() + + proc `name=`*(self: Contact, name: string) = self.setName(name) + + QtProperty[string] name: + read = name + write = setName + notify = nameChanged + + method surname*(self: Contact): string {.slot.} = + result = self.surname + + method surnameChanged*(self: Contact) {.signal.} + + method setSurname(self: Contact, surname: string) {.slot.} = + if self.surname != surname: + self.surname = surname + self.surnameChanged() + + proc `surname=`*(self: Contact, surname: string) = self.setSurname(surname) + + QtProperty[string] surname: + read = surname + write = setSurname + notify = surnameChanged diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim new file mode 100644 index 0000000..49742a6 --- /dev/null +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -0,0 +1,43 @@ +## 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 + +QtObject: + type ContactList* = ref object of QObject + contacts*: seq[Contact] + + proc delete*(self: ContactList) = + let qobject = self.QObject + qobject.delete() + + proc newContactList*(): ContactList = + new(result, delete) + result.contacts = @[] + result.create() + + method getCount(self: ContactList): int {.slot.} = + return self.contacts.len + + method countChanged(self: ContactList) {.signal.} + + method add*(self: ContactList, name: string, surname: string) {.slot.} = + let contact = newContact() + contact.name = name + contact.surname = surname + self.contacts.add(contact) + self.countChanged() + + method get*(self: ContactList, index: int): QVariant {.slot.} = + if index < 0 or index >= self.contacts.len: + return newQVariant() + let contact = self.contacts[index] + result = newQVariant(newQVariant(contact)) + + method del*(self: ContactList, index: int) {.slot.} = + self.contacts.del(index) + self.countChanged() + + QtProperty[int] count: + read = getCount + write = "" + notify = countChanged diff --git a/Nim/Examples/ContactApp/main.nim b/Nim/Examples/ContactApp/main.nim new file mode 100644 index 0000000..87f92bc --- /dev/null +++ b/Nim/Examples/ContactApp/main.nim @@ -0,0 +1,15 @@ +import NimQml, ApplicationLogic + +proc mainProc() = + let app = newQApplication() + defer: app.delete + let logic = newApplicationLogic(app) + defer: logic.delete + let engine = newQQmlApplicationEngine() + defer: engine.delete + engine.rootContext.setContextProperty("logic", newQVariant(logic)) + engine.load("main.qml") + app.exec() + +when isMainModule: + mainProc() diff --git a/Nim/Examples/ContactApp/main.qml b/Nim/Examples/ContactApp/main.qml new file mode 100644 index 0000000..8c35cf8 --- /dev/null +++ b/Nim/Examples/ContactApp/main.qml @@ -0,0 +1,52 @@ +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: "ContactApp" + visible: true + + menuBar: MenuBar { + Menu + { + title: "&File" + MenuItem { text: "Load"; onTriggered: logic.onLoadTriggered() } + MenuItem { text: "Save"; onTriggered: logic.onSaveTriggered() } + MenuItem { text: "Exit"; onTriggered: logic.onExitTriggered() } + } + } + + 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.name } + TextField { Layout.fillWidth: true; text: contact.surname } + Button { text: "Save" } + Button { text: "Delete"; onClicked: logic.contactList.del(index) } + } + } + + 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) } + } + } +} From f153c3f1db4466152941366ea59792ef19a1dca5 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Mon, 12 Jan 2015 16:30:10 +0000 Subject: [PATCH 22/58] make finalizers optional --- Nim/NimQml/NimQml.nim | 45 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index f48b093..fa2b7fb 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -1,6 +1,14 @@ include NimQmlTypes ## NimQml aims to provide binding to the QML for the Nim programming language +## +## Optional finalizers +## ------------------- +## To enable finalizers you must define ``nimqml_use_finalizers`` by passing +## the option, ``-d:nimqml_use_finalizers``, to the Nim compiler. The relevant +## delete method will then be called automatically by the garbage collector. +## Care should be taken when using this approach as there are no guarantees +## when a finalzier will be run, or if, indeed, it will run at all. type QMetaType* {.pure.} = enum ## \ ## Qt metatypes values used for specifing the @@ -34,6 +42,17 @@ proc debugMsg(typeName: string, procName: string, userMessage: string) = message &= userMessage debugMsg(message) +template newWithCondFinalizer(variable: expr, finalizer: expr) = + ## calls ``new`` but only setting a finalizer when ``nimqml_use_finalizers`` + ## is defined + {.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon + when defined(nimqml_use_finalizers): + {.pop.} + new(variable, finalizer) + else: + {.pop.} + new(variable) + # QVariant proc dos_qvariant_create(variant: var RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_int(variant: var RawQVariant, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -106,42 +125,42 @@ proc delete*(variant: QVariant) = proc newQVariant*(): QVariant = ## Return a new QVariant - new(result, delete) + newWithCondFinalizer(result, delete) result.create() proc newQVariant*(value: cint): QVariant = ## Return a new QVariant given a cint - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: bool): QVariant = ## Return a new QVariant given a bool - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: string): QVariant = ## Return a new QVariant given a string - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: QObject): QVariant = ## Return a new QVariant given a QObject - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: RawQVariant): QVariant = ## Return a new QVariant given a raw QVariant pointer - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: QVariant): QVariant = ## Return a new QVariant given another QVariant - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc newQVariant*(value: float): QVariant = ## Return a new QVariant given a float - new(result, delete) + newWithCondFinalizer(result, delete) result.create(value) proc isNull*(variant: QVariant): bool = @@ -232,7 +251,7 @@ proc delete*(engine: QQmlApplicationEngine) = proc newQQmlApplicationEngine*(): QQmlApplicationEngine = ## Return a new QQmlApplicationEngine - new(result, delete) + newWithCondFinalizer(result, delete) result.create() # QQmlContext @@ -270,7 +289,7 @@ proc delete*(application: QApplication) = proc newQApplication*(): QApplication = ## Return a new QApplication - new(result, delete) + newWithCondFinalizer(result, delete) result.create() # QGuiApplication @@ -301,7 +320,7 @@ proc delete*(application: QGuiApplication) = proc newQGuiApplication*(): QGuiApplication = ## Return a new QApplication - new(result, delete) + newWithCondFinalizer(result, delete) result.create() # QObject @@ -379,7 +398,7 @@ proc delete*(qobject: QObject) = proc newQObject*(): QObject = ## Return a new QObject - new(result, delete) + newWithCondFinalizer(result, delete) result.create() proc registerSlot*(qobject: QObject, @@ -456,5 +475,5 @@ proc delete(view: QQuickView) = proc newQQuickView*(): QQuickView = ## Return a new QQuickView - new(result, delete) + newWithCondFinalizer(result, delete) result.create() From 467524e4ad9dd60efacdde166629f1f05afa6e50 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Mon, 12 Jan 2015 16:39:26 +0000 Subject: [PATCH 23/58] fixed a naming conflict in Contact app --- Nim/Examples/ContactApp/Contact.nim | 18 +++++++++--------- Nim/Examples/ContactApp/ContactList.nim | 2 +- Nim/Examples/ContactApp/main.nim | 4 +++- Nim/Examples/ContactApp/main.qml | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Nim/Examples/ContactApp/Contact.nim b/Nim/Examples/ContactApp/Contact.nim index b9c343e..8289e80 100644 --- a/Nim/Examples/ContactApp/Contact.nim +++ b/Nim/Examples/ContactApp/Contact.nim @@ -16,22 +16,22 @@ QtObject: result.name = "" result.create - method name*(self: Contact): string {.slot.} = + method firstName*(self: Contact): string {.slot.} = result = self.name - method nameChanged*(self: Contact) {.signal.} + method firstNameChanged*(self: Contact) {.signal.} - method setName(self: Contact, name: string) {.slot.} = + method setFirstName(self: Contact, name: string) {.slot.} = if self.name != name: self.name = name - self.nameChanged() + self.firstNameChanged() - proc `name=`*(self: Contact, name: string) = self.setName(name) + proc `firstName=`*(self: Contact, name: string) = self.setFirstName(name) - QtProperty[string] name: - read = name - write = setName - notify = nameChanged + QtProperty[string] firstName: + read = firstName + write = setFirstName + notify = firstNameChanged method surname*(self: Contact): string {.slot.} = result = self.surname diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index 49742a6..121a061 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -22,7 +22,7 @@ QtObject: method add*(self: ContactList, name: string, surname: string) {.slot.} = let contact = newContact() - contact.name = name + contact.firstName = name contact.surname = surname self.contacts.add(contact) self.countChanged() diff --git a/Nim/Examples/ContactApp/main.nim b/Nim/Examples/ContactApp/main.nim index 87f92bc..d5761fb 100644 --- a/Nim/Examples/ContactApp/main.nim +++ b/Nim/Examples/ContactApp/main.nim @@ -7,7 +7,9 @@ proc mainProc() = defer: logic.delete let engine = newQQmlApplicationEngine() defer: engine.delete - engine.rootContext.setContextProperty("logic", newQVariant(logic)) + let logicVariant = newQVariant(logic) + defer: logicVariant.delete + engine.rootContext.setContextProperty("logic", logicVariant) engine.load("main.qml") app.exec() diff --git a/Nim/Examples/ContactApp/main.qml b/Nim/Examples/ContactApp/main.qml index 8c35cf8..e4fe7e5 100644 --- a/Nim/Examples/ContactApp/main.qml +++ b/Nim/Examples/ContactApp/main.qml @@ -33,7 +33,7 @@ ApplicationWindow delegate: RowLayout { width: ListView.view.width property QtObject contact: logic.contactList.get(index) - TextField { Layout.fillWidth: true; text: contact.name } + 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) } From bba226f55088ea3e7e4d860d2f63455db05b1ce3 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Mon, 12 Jan 2015 17:52:22 +0000 Subject: [PATCH 24/58] allow nil strings for readSlot, writeSlot and notifySlot in registerProperty --- Nim/NimQml/NimQml.nim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index f48b093..4a2a6f7 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -411,7 +411,12 @@ proc registerProperty*(qobject: QObject, writeSlot: string, notifySignal: string) = ## Register a property in the QObject with the given name and type. - dos_qobject_property_create(qobject.data, propertyName, propertyType.cint, readSlot, writeSlot, notifySignal) + assert propertyName != nil, "property name cannot be nil" + # don't convert a nil string, else we get a strange memory address + let cReadSlot: cstring = if readSlot == nil: cast[cstring](nil) else: readSlot + let cWriteSlot: cstring = if writeSlot == nil: cast[cstring](nil) else: writeSlot + let cNotifySignal: cstring = if notifySignal == nil: cast[cstring](nil) else: notifySignal + dos_qobject_property_create(qobject.data, propertyName, propertyType.cint, cReadSlot, cWriteSlot, cNotifySignal) proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) = ## Emit the signal with the given name and values From 78d7808fb16e6ad9a5bb68a0577518da249282cf Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 12 Jan 2015 20:36:02 +0100 Subject: [PATCH 25/58] Removed useless copy directive in CMakeLists.txt --- Nim/Examples/ContactApp/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Nim/Examples/ContactApp/CMakeLists.txt b/Nim/Examples/ContactApp/CMakeLists.txt index 28c0862..a6c189e 100644 --- a/Nim/Examples/ContactApp/CMakeLists.txt +++ b/Nim/Examples/ContactApp/CMakeLists.txt @@ -1,3 +1,2 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ContactForm.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_nim_executable(TARGET ContactApp SOURCES main.nim PATHS ../../NimQml) \ No newline at end of file From f878966cbbf938faa6239c6b033f14225466fddc Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 12 Jan 2015 21:21:46 +0100 Subject: [PATCH 26/58] Added some love to the ContactApp example --- DOtherSide/DOtherSide/DOtherSide.cpp | 7 +++++ DOtherSide/DOtherSide/DOtherSide.h | 1 + Nim/Examples/ContactApp/ApplicationLogic.nim | 11 ++++--- Nim/Examples/ContactApp/Contact.nim | 6 ++-- Nim/Examples/ContactApp/ContactList.nim | 17 ++++++----- Nim/NimQml/NimQml.nim | 31 +++++++++++++------- Nim/NimQml/NimQmlMacros.nim | 4 ++- 7 files changed, 48 insertions(+), 29 deletions(-) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 24a5b2a..7c0f32a 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -280,6 +280,13 @@ void dos_qvariant_setString(void* vptr, const char* value) *variant = value; } +void dos_qvariant_setQObject(void* vptr, void* value) +{ + auto variant = reinterpret_cast(vptr); + auto qobject = reinterpret_cast(value); + variant->setValue(qobject); +} + void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback) { auto dynamicQObject = new DynamicQObject(); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 92a2608..5b66cc5 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -63,6 +63,7 @@ extern "C" 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); diff --git a/Nim/Examples/ContactApp/ApplicationLogic.nim b/Nim/Examples/ContactApp/ApplicationLogic.nim index 6af7c61..ed1242d 100644 --- a/Nim/Examples/ContactApp/ApplicationLogic.nim +++ b/Nim/Examples/ContactApp/ApplicationLogic.nim @@ -1,4 +1,4 @@ -import NimQml, NimQmlMacros, Contact, ContactList +import NimQml, NimQmlMacros, ContactList QtObject: type ApplicationLogic* = ref object of QObject @@ -7,10 +7,11 @@ QtObject: proc delete*(self: ApplicationLogic) = let qobject = self.QObject - qobject.delete() + qobject.delete + self.contactList.delete proc newApplicationLogic*(app: QApplication): ApplicationLogic = - new(result, delete) + new(result) result.contactList = newContactList() result.app = app result.create() @@ -26,9 +27,7 @@ QtObject: echo "Save Triggered" method onExitTriggered(self: ApplicationLogic) {.slot.} = - self.app.quit() + self.app.quit QtProperty[QVariant] contactList: read = getContactList - write = "" - notify = "" diff --git a/Nim/Examples/ContactApp/Contact.nim b/Nim/Examples/ContactApp/Contact.nim index 8289e80..ec5f2b2 100644 --- a/Nim/Examples/ContactApp/Contact.nim +++ b/Nim/Examples/ContactApp/Contact.nim @@ -7,12 +7,12 @@ QtObject: name: string surname: string - proc delete(self: Contact) = + proc delete*(self: Contact) = let qobject = self.QObject - qobject.delete() + qobject.delete proc newContact*(): Contact = - new(result, delete) + new(result) result.name = "" result.create diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index 121a061..6b0dc04 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -8,10 +8,13 @@ QtObject: proc delete*(self: ContactList) = let qobject = self.QObject - qobject.delete() + qobject.delete + for contact in self.contacts: + contact.delete + self.contacts = @[] proc newContactList*(): ContactList = - new(result, delete) + new(result) result.contacts = @[] result.create() @@ -27,17 +30,15 @@ QtObject: self.contacts.add(contact) self.countChanged() - method get*(self: ContactList, index: int): QVariant {.slot.} = + method get*(self: ContactList, index: int): QObject {.slot.} = if index < 0 or index >= self.contacts.len: - return newQVariant() - let contact = self.contacts[index] - result = newQVariant(newQVariant(contact)) - + 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 - write = "" notify = countChanged diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 735e02d..5f20fb3 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -20,8 +20,9 @@ type QMetaType* {.pure.} = enum ## \ Int = cint(2), QString = cint(10), VoidStar = cint(31), + QObjectStar = cint(39), QVariant = cint(41), - Void = cint(43) + Void = cint(43), var qobjectRegistry = initTable[ptr QObjectObj, bool]() @@ -71,10 +72,11 @@ proc dos_qvariant_setInt(variant: RawQVariant, value: cint) {.cdecl, dynlib:"lib proc dos_qvariant_setBool(variant: RawQVariant, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setString(variant: RawQVariant, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_assign(leftValue: RawQVariant, rightValue: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toFloat(variant: QVariant, value: var cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setFloat(variant: QVariant, value: float) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toDouble(variant: QVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setDouble(variant: QVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toFloat(variant: RawQVariant, value: var cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setFloat(variant: RawQVariant, value: float) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toDouble(variant: RawQVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setDouble(variant: RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setQObject(variant: RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: QVariant) = @@ -103,16 +105,19 @@ proc create*(variant: QVariant, value: QObject) = variant.deleted = false proc create*(variant: QVariant, value: RawQVariant) = - ## Create a new QVariant givan another QVariant + ## Create a new QVariant given another QVariant. + ## The inner value of the QVariant is copied dos_qvariant_create_qvariant(variant.data, value) variant.deleted = false proc create*(variant: QVariant, value: cfloat) = - ## Create a new QVariant givan another QVariant + ## Create a new QVariant given a cfloat value dos_qvariant_create_float(variant.data, value) variant.deleted = false proc create*(variant: QVariant, value: QVariant) = + ## Create a new QVariant given another QVariant. + ## The inner value of the QVariant is copied create(variant, value.data) proc delete*(variant: QVariant) = @@ -189,22 +194,22 @@ proc `boolVal=`*(variant: QVariant, value: bool) = proc floatVal*(variant: QVariant): float = ## Return the QVariant value as float var rawValue: cfloat - dos_qvariant_toFloat(variant, rawValue) + dos_qvariant_toFloat(variant.data, rawValue) result = rawValue.cfloat proc `floatVal=`*(variant: QVariant, value: float) = ## Sets the QVariant float value - dos_qvariant_setFloat(variant, value.cfloat) + dos_qvariant_setFloat(variant.data, value.cfloat) proc doubleVal*(variant: QVariant): cdouble = ## Return the QVariant value as double var rawValue: cdouble - dos_qvariant_toDouble(variant, rawValue) + dos_qvariant_toDouble(variant.data, rawValue) result = rawValue proc `doubleVal=`*(variant: QVariant, value: cdouble) = ## Sets the QVariant double value - dos_qvariant_setDouble(variant, value) + dos_qvariant_setDouble(variant.data, value) proc stringVal*(variant: QVariant): string = ## Return the QVariant value as string @@ -218,6 +223,10 @@ proc `stringVal=`*(variant: QVariant, value: string) = ## Sets the QVariant string value dos_qvariant_setString(variant.data, value) +proc `qobjectVal=`*(variant: QVariant, value: QObject) = + ## Sets the QVariant qobject value + dos_qvariant_setQObject(variant.data, value.data) + 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) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index 032b40a..cd902e0 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -17,7 +17,8 @@ let nimFromQtVariant {.compileTime.} = { "int" : "intVal", "string" : "stringVal", "bool" : "boolVal", - "float" : "floatVal", + "float" : "floatVal", + "QObject" : "qobjectVal", }.toTable let nim2QtMeta {.compileTime.} = { @@ -25,6 +26,7 @@ let nim2QtMeta {.compileTime.} = { "int" : "Int", "string" : "QString", "pointer" : "VoidStar", + "QObject" : "QObjectStar", "QVariant": "QVariant", "" : "Void", # no return, which is represented by an nnkEmpty node }.toTable From 412bb14eb22b04faed96d12a6ae5953669726f8c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 12 Jan 2015 22:47:21 +0100 Subject: [PATCH 27/58] Added missing export of the delete proc --- Nim/Examples/QtObjectMacro/Contact.nim | 2 +- Nim/Examples/SlotsAndProperties/Contact.nim | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Nim/Examples/QtObjectMacro/Contact.nim b/Nim/Examples/QtObjectMacro/Contact.nim index e404895..380d18b 100644 --- a/Nim/Examples/QtObjectMacro/Contact.nim +++ b/Nim/Examples/QtObjectMacro/Contact.nim @@ -6,7 +6,7 @@ QtObject: type Contact* = ref object of QObject m_name: string - proc delete(self: Contact) = + proc delete*(self: Contact) = var qobject = self.QObject qobject.delete() diff --git a/Nim/Examples/SlotsAndProperties/Contact.nim b/Nim/Examples/SlotsAndProperties/Contact.nim index 0f7fdd5..3310b0b 100644 --- a/Nim/Examples/SlotsAndProperties/Contact.nim +++ b/Nim/Examples/SlotsAndProperties/Contact.nim @@ -5,11 +5,11 @@ import NimQml type Contact = ref object of QObject m_name: string -proc delete(self: Contact) = +proc delete*(self: Contact) = var qobject = self.QObject qobject.delete() -proc create(self: Contact) = +proc create*(self: Contact) = var qobject = self.QObject qobject.create() self.m_name = "InitialName" From 358811dcbd2cba112f3890ffc5ba832c5e394097 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 15 Jan 2015 20:34:36 +0000 Subject: [PATCH 28/58] Allow signals and slots to be defined as procedures --- Nim/NimQml/NimQmlMacros.nim | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index cd902e0..4037964 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -213,7 +213,7 @@ proc getArgName*(arg: PNimrodNode): PNimrodNode {.compileTime.} = proc addSignalBody(signal: PNimrodNode): PNimrodNode {.compileTime.} = # e.g: produces: emit(MyQObject, "nameChanged") - expectKind signal, nnkMethodDef + assert signal.kind in {nnkMethodDef, nnkProcDef} result = newStmtList() # if exported, will use postfix let name = if signal.name.kind == nnkIdent: signal.name else: signal.name[1] @@ -269,6 +269,32 @@ proc getIdentDefName*(a: PNimrodNode): PNimrodNode {.compileTime.} = elif a[0].kind == nnkPostFix: return a[0][1] +proc tryHandleSigSlot(def: PNimrodNode, signals: var seq[PNimrodNode], slots: var seq[PNimrodNode], + generatedCode: var PNimrodNode): bool {.compileTime.} = + ## Checks a method/proc definition for signals and slots. On finding a method/proc with + ## a {.signal.} or {.slot.} pragma, it will strip the pragma, add the definition to the + ## appropriate seq, append the stripped version to the generated code block and return true + ## indicating the definition was a signal or a slot. If the method/proc is not a slot + ## or a slot it will return false. + expectKind generatedCode, nnkStmtList + assert (not signals.isNil) + assert (not slots.isNil) + assert def.kind in {nnkMethodDef, nnkProcDef} + result = false + if def.hasPragma("slot"): + let pragma = def.pragma() + def.pragma = pragma.removePragma("slot") + slots.add def # we need to gensome code later + generatedCode.add def + result = true + elif def.hasPragma("signal"): + let pragma = def.pragma() + def.pragma = pragma.removePragma("signal") + def.body = addSignalBody(def) + generatedCode.add def + signals.add def + result = true + macro QtObject*(qtDecl: stmt): stmt {.immediate.} = ## Generates boiler plate code for registering signals, slots ## and properties. @@ -314,20 +340,10 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = result.add it result.add genSuperTemplate(typeDecl) elif it.kind == nnkMethodDef: - if it.hasPragma("slot"): - let pragma = it.pragma() - it.pragma = pragma.removePragma("slot") - slots.add it # we need to gensome code later - result.add it - elif it.hasPragma("signal"): - let pragma = it.pragma() - it.pragma = pragma.removePragma("signal") - it.body = addSignalBody(it) - result.add it - signals.add it - else: - userDefined.add it + if tryHandleSigSlot(it, signals, slots, result): continue + userDefined.add it elif it.kind == nnkProcDef: + if tryHandleSigSlot(it, signals, slots, result): continue userDefined.add it elif it.kind == nnkCommand: let bracket = it[0] From 360afaddd51c52880291da46d853008ce84f6807 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 15 Jan 2015 21:04:13 +0000 Subject: [PATCH 29/58] Support signals/slots with inheritance --- Nim/NimQml/NimQmlMacros.nim | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index cd902e0..f384bfc 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -228,10 +228,14 @@ proc addSignalBody(signal: PNimrodNode): PNimrodNode {.compileTime.} = args.add getArgName params[i] result.add newCall("emit", args) -#FIXME: changed typ from typedesc to expr to workaround Nim issue #1874 -template declareOnSlotCalled(typ: expr): stmt = +#FIXME: changed typ from typedesc to expr to workaround Nim issue #1874 +# This is declared dirty so that identifers are not bound to symbols. +# The alternative is to use `removeOpenSym` as we did for `prototypeCreate`. +# We should decide which method is preferable. +template declareOnSlotCalled(typ: expr): stmt {.dirty.} = method onSlotCalled(myQObject: typ, slotName: string, args: openarray[QVariant]) = - discard + var super = (typ.superType())(myQObject) + procCall onSlotCalled(super, slotName, args) #FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874 template prototypeCreate(typ: expr): stmt = @@ -396,7 +400,7 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = # add else: discard caseStmt.add newNimNode(nnkElse) .add newStmtList().add newNimNode(nnkDiscardStmt).add newNimNode(nnkEmpty) - slotProto.body = newStmtList().add caseStmt + slotProto.body.add caseStmt result.add slotProto # generate create method From 8c8f958a01dbe6336182a47015d5a0dca8fa248d Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Thu, 15 Jan 2015 21:09:27 +0000 Subject: [PATCH 30/58] make naming consistent --- Nim/NimQml/NimQmlMacros.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index f384bfc..1f6ad9c 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -232,7 +232,7 @@ proc addSignalBody(signal: PNimrodNode): PNimrodNode {.compileTime.} = # This is declared dirty so that identifers are not bound to symbols. # The alternative is to use `removeOpenSym` as we did for `prototypeCreate`. # We should decide which method is preferable. -template declareOnSlotCalled(typ: expr): stmt {.dirty.} = +template prototypeOnSlotCalled(typ: expr): stmt {.dirty.} = method onSlotCalled(myQObject: typ, slotName: string, args: openarray[QVariant]) = var super = (typ.superType())(myQObject) procCall onSlotCalled(super, slotName, args) @@ -353,7 +353,7 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = let typeName = typ.getTypeName() ## define onSlotCalled - var slotProto = (getAst declareOnSlotCalled(typeName))[0] + var slotProto = (getAst prototypeOnSlotCalled(typeName))[0] var caseStmt = newNimNode(nnkCaseStmt) caseStmt.add ident("slotName") for slot in slots: From d2fc0c3c00316e95f97ca7e08f9e027ad8b3f08c Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 10 Feb 2015 21:22:16 +0000 Subject: [PATCH 31/58] Preserve ordering of declarations in QtObject macro --- Nim/NimQml/NimQmlMacros.nim | 286 +++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 137 deletions(-) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index a914a47..aa33fc1 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -239,7 +239,7 @@ template prototypeOnSlotCalled(typ: expr): stmt {.dirty.} = #FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874 template prototypeCreate(typ: expr): stmt = - template create*(myQObject: var typ) = + proc create*(myQObject: var typ) = var super = (typ.superType())(myQObject) procCall create(super) @@ -299,77 +299,86 @@ proc tryHandleSigSlot(def: PNimrodNode, signals: var seq[PNimrodNode], slots: va signals.add def result = true -macro QtObject*(qtDecl: stmt): stmt {.immediate.} = - ## Generates boiler plate code for registering signals, slots - ## and properties. - ## - ## Currently generates: - ## - create: a method to register signal, slots and properties - ## - superType: a template that returns the super type of the - ## object defined within the macro body - ## - onSlotCalled: a method to dispatch an on slot call to the - ## appropiate method. - ## - ## Current limitations: - ## - only one type can be defined within the body of code sent to the - ## the macro. It is assumed, but not checked, that somewhere in the - ## inheritance hierarchy this object derives from ``QObject``. - ## - generics are not currently supported - expectKind(qtDecl, nnkStmtList) - #echo treeRepr qtDecl - result = newStmtList() - var slots = newSeq[PNimrodNode]() - var properties = newSeq[PNimrodNode]() - var signals = newSeq[PNimrodNode]() - # holds all user defined procedures so we can add them after create - var userDefined = newSeq[PNimrodNode]() - # assume only one type per section for now - var typ: PNimrodNode - for it in qtDecl.children(): - if it.kind == nnkTypeSection: - let typeDecl = it.findChild(it.kind == nnkTypeDef) - let superType = typeDecl.getSuperType() - if superType.kind == nnkEmpty: - # allow simple types and type aliases - result.add it - else: - # may come in useful if we want to check objects inherit from QObject - #let superName = if superType.kind == nnkIdent: superType - # else: superType.getNodeOf(nnkIdent) - if typ != nil: - error("you may not define more than one type " & - "within the code block passed to this macro") - else: # without this else, it fails to compile - typ = typeDecl - result.add it - result.add genSuperTemplate(typeDecl) - elif it.kind == nnkMethodDef: - if tryHandleSigSlot(it, signals, slots, result): continue - userDefined.add it - elif it.kind == nnkProcDef: - if tryHandleSigSlot(it, signals, slots, result): continue - userDefined.add it - elif it.kind == nnkCommand: - let bracket = it[0] - if bracket.kind != nnkBracketExpr: - error("do not know how to handle: \n" & repr(it)) - # BracketExpr - # Ident !"QtProperty" - # Ident !"string" - let cmdIdent = bracket[0] - if cmdIdent == nil or cmdIdent.kind != nnkIdent or - ($cmdIdent).toLower() != "qtproperty": - error("do not know how to handle: \n" & repr(it)) - properties.add it - else: - # everything else should pass through unchanged - result.add it - if typ == nil: - error("you must declare an object that inherits from QObject") +proc genCreateDecl(typ: PNimrodNode): PNimrodNode {.compileTime.} = + ## generates forward declaration for ``create`` procedure + expectKind typ, nnkTypeDef let typeName = typ.getTypeName() + result = (getAst prototypeCreate(typeName))[0] + result.body = newEmptyNode() + if typ.isExported: + result.exportDef() + else: + result.unexportDef() - ## define onSlotCalled - var slotProto = (getAst prototypeOnSlotCalled(typeName))[0] +proc genCreate(typ: PNimrodNode, signals: seq[PNimrodNode], slots: seq[PNimrodNode], + properties: seq[PNimrodNode]): PNimrodNode {.compileTime.} = + expectKind typ, nnkTypeDef + let typeName = typ.getTypeName() + result = (getAst prototypeCreate(typeName))[0] + # the template creates loads of openSyms - replace these with idents + result = doRemoveOpenSym(result) + if typ.isExported: + result.exportDef() + else: + result.unexportDef() + var createBody = result.body + for slot in slots: + let params = slot.params + let regSlotDot = newDotExpr(ident "myQObject", ident "registerSlot") + let name = ($slot.name).replace("*","") + let argTypesArray = genArgTypeArray(params) + let call = newCall(regSlotDot, newLit name, argTypesArray) + createBody.add call + for signal in signals: + let params = signal.params + let regSigDot = newDotExpr(ident "myQObject", ident "registerSignal") + let name = ($signal.name).replace("*","") + let argTypesArray = genArgTypeArray(params) + let call = newCall(regSigDot, newLit name, argTypesArray) + createBody.add call + for property in properties: + let bracket = property[0] + expectKind bracket, nnkBracketExpr + #Command + # BracketExpr + # Ident !"QtProperty" + # Ident !"string" + # Ident !"name" + # StmtList + let nimPropType = bracket[1] + let qtPropMeta = nim2QtMeta[$nimPropType] + if qtPropMeta == nil: error($nimPropType & " not supported") + let metaDot = newDotExpr(ident "QMetaType", ident qtPropMeta) + let propertyName = property[1] + var read, write, notify: PNimrodNode + let stmtList = property[2] + # fields + # StmtList + # Asgn + # Ident !"read" + # Ident !"getName + for asgn in stmtList.children: + let name = asgn[0] + case $name + of "read": + read = asgn[1] + of "write": + write = asgn[1] + of "notify": + notify = asgn[1] + else: + error("unknown property field: " & $name) + let regPropDot = newDotExpr(ident "myQObject", ident "registerProperty") + let readArg = if read == nil: newNilLit() else: newLit($read) + let writeArg = if write == nil: newNilLit() else: newLit($write) + let notifyArg = if notify == nil: newNilLit() else: newLit($notify) + let call = newCall(regPropDot, newLit($propertyName), metaDot, readArg, writeArg, notifyArg) + createBody.add call + +proc genOnSlotCalled(typ: PNimrodNode, slots: seq[PNimrodNode]): PNimrodNode {.compileTime.} = + expectKind typ, nnkTypeDef + let typeName = typ.getTypeName() + result = (getAst prototypeOnSlotCalled(typeName))[0] var caseStmt = newNimNode(nnkCaseStmt) caseStmt.add ident("slotName") for slot in slots: @@ -410,82 +419,85 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = let mapper = nimFromQtVariant[$retType] let dot = newDotExpr(argAccess, ident mapper) call = newAssignment(dot, call) - branchStmts.add call + branchStmts.add call ofBranch.add branchStmts caseStmt.add ofBranch # add else: discard caseStmt.add newNimNode(nnkElse) .add newStmtList().add newNimNode(nnkDiscardStmt).add newNimNode(nnkEmpty) - slotProto.body.add caseStmt - result.add slotProto + result.body.add caseStmt - # generate create method - var createProto = (getAst prototypeCreate(typeName))[0] - # the template creates loads of openSyms - replace these with idents - createProto = doRemoveOpenSym(createProto) - if typ.isExported: - createProto.exportDef() - else: - createProto.unexportDef() - var createBody = createProto.templateBody - for slot in slots: - let params = slot.params - let regSlotDot = newDotExpr(ident "myQObject", ident "registerSlot") - let name = ($slot.name).replace("*","") - let argTypesArray = genArgTypeArray(params) - let call = newCall(regSlotDot, newLit name, argTypesArray) - createBody.add call - for signal in signals: - let params = signal.params - let regSigDot = newDotExpr(ident "myQObject", ident "registerSignal") - let name = ($signal.name).replace("*","") - let argTypesArray = genArgTypeArray(params) - let call = newCall(regSigDot, newLit name, argTypesArray) - createBody.add call - for property in properties: - let bracket = property[0] - expectKind bracket, nnkBracketExpr - #Command - # BracketExpr - # Ident !"QtProperty" - # Ident !"string" - # Ident !"name" - # StmtList - let nimPropType = bracket[1] - let qtPropMeta = nim2QtMeta[$nimPropType] - if qtPropMeta == nil: error($nimPropType & " not supported") - let metaDot = newDotExpr(ident "QMetaType", ident qtPropMeta) - let propertyName = property[1] - var read, write, notify: PNimrodNode - let stmtList = property[2] - # fields - # StmtList - # Asgn - # Ident !"read" - # Ident !"getName - for asgn in stmtList.children: - let name = asgn[0] - case $name - of "read": - read = asgn[1] - of "write": - write = asgn[1] - of "notify": - notify = asgn[1] +macro QtObject*(qtDecl: stmt): stmt {.immediate.} = + ## Generates boiler plate code for registering signals, slots + ## and properties. + ## + ## Currently generates: + ## - create: a method to register signal, slots and properties + ## - superType: a template that returns the super type of the + ## object defined within the macro body + ## - onSlotCalled: a method to dispatch an on slot call to the + ## appropiate method. + ## + ## Current limitations: + ## - only one type can be defined within the body of code sent to the + ## the macro. It is assumed, but not checked, that somewhere in the + ## inheritance hierarchy this object derives from ``QObject``. + ## - generics are not currently supported + expectKind(qtDecl, nnkStmtList) + #echo treeRepr qtDecl + result = newStmtList() + var slots = newSeq[PNimrodNode]() + var properties = newSeq[PNimrodNode]() + var signals = newSeq[PNimrodNode]() + # assume only one type per section for now + var typ: PNimrodNode + for it in qtDecl.children(): + if it.kind == nnkTypeSection: + let typeDecl = it.findChild(it.kind == nnkTypeDef) + let superType = typeDecl.getSuperType() + if superType.kind == nnkEmpty: + # allow simple types and type aliases + result.add it else: - error("unknown property field: " & $name) - let regPropDot = newDotExpr(ident "myQObject", ident "registerProperty") - let readArg = if read == nil: newNilLit() else: newLit($read) - let writeArg = if write == nil: newNilLit() else: newLit($write) - let notifyArg = if notify == nil: newNilLit() else: newLit($notify) - let call = newCall(regPropDot, newLit($propertyName), metaDot, readArg, writeArg, notifyArg) - createBody.add call + # may come in useful if we want to check objects inherit from QObject + #let superName = if superType.kind == nnkIdent: superType + # else: superType.getNodeOf(nnkIdent) + if typ != nil: + error("you may not define more than one type " & + "within the code block passed to this macro") + else: # without this else, it fails to compile + typ = typeDecl + result.add it + result.add genSuperTemplate(typeDecl) + result.add genCreateDecl(typeDecl) + elif it.kind == nnkMethodDef: + if tryHandleSigSlot(it, signals, slots, result): continue + result.add it + elif it.kind == nnkProcDef: + if tryHandleSigSlot(it, signals, slots, result): continue + result.add it + elif it.kind == nnkCommand: + let bracket = it[0] + if bracket.kind != nnkBracketExpr: + error("do not know how to handle: \n" & repr(it)) + # BracketExpr + # Ident !"QtProperty" + # Ident !"string" + let cmdIdent = bracket[0] + if cmdIdent == nil or cmdIdent.kind != nnkIdent or + ($cmdIdent).toLower() != "qtproperty": + error("do not know how to handle: \n" & repr(it)) + properties.add it + else: + # everything else should pass through unchanged + result.add it + if typ == nil: + error("you must declare an object that inherits from QObject") + let typeName = typ.getTypeName() - #echo repr createProto - result.add createProto + result.add genOnSlotCalled(typ, slots) - for fn in userDefined: - result.add fn + result.add genCreate(typ, signals, slots, properties) debug: echo repr result From 399adc747a053a0fcf6acefabc96157da4ea1185 Mon Sep 17 00:00:00 2001 From: Will Szumski Date: Tue, 10 Feb 2015 21:42:35 +0000 Subject: [PATCH 32/58] removed unused variable: typeName --- Nim/NimQml/NimQmlMacros.nim | 1 - 1 file changed, 1 deletion(-) diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index aa33fc1..fe6fc39 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -493,7 +493,6 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = result.add it if typ == nil: error("you must declare an object that inherits from QObject") - let typeName = typ.getTypeName() result.add genOnSlotCalled(typ, slots) From 733266b36205d1768b6cfd257575b408dfae2604 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 18 Jan 2015 12:26:51 +0100 Subject: [PATCH 33/58] Add wrapping of the QModelIndex data type --- DOtherSide/DOtherSide/DOtherSide.cpp | 59 +++++++++++++++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 11 +++++ Nim/NimQml/NimQml.nim | 61 ++++++++++++++++++++++++++++ Nim/NimQml/NimQmlTypes.nim | 4 ++ 4 files changed, 135 insertions(+) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 7c0f32a..0d89242 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "DynamicQObject.h" @@ -356,3 +357,61 @@ void dos_qobject_property_create(void* vptr, 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(vptr); + delete index; +} + +void dos_qmodelindex_row(void* vptr, int& row) +{ + auto index = reinterpret_cast(vptr); + row = index->row(); +} + +void dos_qmodelindex_column(void* vptr, int& column) +{ + auto index = reinterpret_cast(vptr); + column = index->column(); +} + +void dos_qmodelindex_isValid(void* vptr, bool& isValid) +{ + auto index = reinterpret_cast(vptr); + isValid = index->isValid(); +} + +void dos_qmodelindex_data(void* vptr, int role, void* data) +{ + auto index = reinterpret_cast(vptr); + auto result = reinterpret_cast(data); + *result = index->data(role); +} + +void dos_qmodelindex_parent(void* vptr, void* parent) +{ + auto index = reinterpret_cast(vptr); + auto parentIndex = reinterpret_cast(parent); + *parentIndex = index->parent(); +} + +void dos_qmodelindex_child(void* vptr, int row, int column, void* child) +{ + auto index = reinterpret_cast(vptr); + auto childIndex = reinterpret_cast(child); + *childIndex = index->child(row, column); +} + +void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) +{ + auto index = reinterpret_cast(vptr); + auto siblingIndex = reinterpret_cast(sibling); + *siblingIndex = index->sibling(row, column); +} diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 5b66cc5..c921e50 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -98,6 +98,17 @@ extern "C" 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); + #ifdef __cplusplus } #endif diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 5f20fb3..11dd89f 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -491,3 +491,64 @@ 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 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 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) diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 6874d72..bc4f5ec 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -33,3 +33,7 @@ type QQmlContext* = distinct pointer ## A QQmlContext + RawQModelIndex = distinct pointer + QModelIndex = ref object of RootObj ## A QModelIndex + data: RawQModelIndex + deleted: bool From 92fcf6970d65619cf5ed9cb4f0782628614ead33 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 19 Jan 2015 22:23:18 +0100 Subject: [PATCH 34/58] Initial implementation of the BaseQAbstractListModel --- .../DOtherSide/BaseQAbstractListModel.cpp | 15 +++++++ .../DOtherSide/BaseQAbstractListModel.h | 18 ++++++++ DOtherSide/DOtherSide/CMakeLists.txt | 2 + DOtherSide/DOtherSide/DOtherSide.cpp | 13 ++++++ DOtherSide/DOtherSide/DOtherSide.h | 4 ++ Nim/Examples/AbstractItemModel/CMakeLists.txt | 2 + Nim/Examples/AbstractItemModel/main.nim | 12 ++++++ Nim/Examples/AbstractItemModel/main.qml | 30 +++++++++++++ Nim/Examples/CMakeLists.txt | 3 +- Nim/NimQml/NimQml.nim | 42 +++++++++++++++---- Nim/NimQml/NimQmlTypes.nim | 5 +++ 11 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 DOtherSide/DOtherSide/BaseQAbstractListModel.cpp create mode 100644 DOtherSide/DOtherSide/BaseQAbstractListModel.h create mode 100644 Nim/Examples/AbstractItemModel/CMakeLists.txt create mode 100644 Nim/Examples/AbstractItemModel/main.nim create mode 100644 Nim/Examples/AbstractItemModel/main.qml diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp new file mode 100644 index 0000000..5763b91 --- /dev/null +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -0,0 +1,15 @@ +#include "BaseQAbstractListModel.h" + +BaseQAbstractListModel::BaseQAbstractListModel() +{ +} + +int BaseQAbstractListModel::rowCount(const QModelIndex& index) const +{ + return 0; +} + +QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const +{ + return QVariant(); +} diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h new file mode 100644 index 0000000..c1b06ce --- /dev/null +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +/// This class act as a base class for D and Nim QAbstractListModel +class BaseQAbstractListModel : public QAbstractListModel +{ +public: + /// Constructor + BaseQAbstractListModel(); + + /// Return the model's row count + virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; + + /// Return the QVariant at the given index + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + +}; diff --git a/DOtherSide/DOtherSide/CMakeLists.txt b/DOtherSide/DOtherSide/CMakeLists.txt index 7397864..132dbbc 100644 --- a/DOtherSide/DOtherSide/CMakeLists.txt +++ b/DOtherSide/DOtherSide/CMakeLists.txt @@ -12,10 +12,12 @@ find_package(Qt5Widgets) set(HEADERS_LIST DOtherSide.h + BaseQAbstractListModel.h ) set(SRC_LIST DOtherSide.cpp + BaseQAbstractListModel.cpp ) add_library(${PROJECT_NAME} SHARED ${SRC_LIST} ${HEADERS_LIST}) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 0d89242..9f09593 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -10,6 +10,7 @@ #include #include "DynamicQObject.h" +#include "BaseQAbstractListModel.h" void convert_to_cstring(const QString& source, CharPtr& destination, int& length) { @@ -415,3 +416,15 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) auto siblingIndex = reinterpret_cast(sibling); *siblingIndex = index->sibling(row, column); } + +void dos_qabstractlistmodel_create(void** vptr) +{ + auto model = new BaseQAbstractListModel(); + *vptr = model; +} + +void dos_qabstractlistmodel_delete(void* vptr) +{ + auto model = reinterpret_cast(vptr); + delete model; +} diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index c921e50..b8eaa23 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -109,6 +109,10 @@ extern "C" void dos_qmodelindex_child(void* vptr, int row, int column, void* child); void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling); + // QAbstractListModel + void dos_qabstractlistmodel_create(void** vptr); + void dos_qabstractlistmodel_delete(void* vptr); + #ifdef __cplusplus } #endif diff --git a/Nim/Examples/AbstractItemModel/CMakeLists.txt b/Nim/Examples/AbstractItemModel/CMakeLists.txt new file mode 100644 index 0000000..227c09f --- /dev/null +++ b/Nim/Examples/AbstractItemModel/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim new file mode 100644 index 0000000..5eb92ad --- /dev/null +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -0,0 +1,12 @@ +import NimQml +import macros +import typeinfo + +proc mainProc() = + var myListModel = newQAbstractListModel() + defer: myListModel.delete() + +when isMainModule: + mainProc() + GC_fullcollect() + diff --git a/Nim/Examples/AbstractItemModel/main.qml b/Nim/Examples/AbstractItemModel/main.qml new file mode 100644 index 0000000..0edd37b --- /dev/null +++ b/Nim/Examples/AbstractItemModel/main.qml @@ -0,0 +1,30 @@ +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 + Rectangle + { + width: 10 + height: 10 + color: "red" + } + } + + ListView + { + anchors.fill: parent + model: myListModel + delegate: myListModelDelegate + } +} \ No newline at end of file diff --git a/Nim/Examples/CMakeLists.txt b/Nim/Examples/CMakeLists.txt index 15abd67..a6d896a 100644 --- a/Nim/Examples/CMakeLists.txt +++ b/Nim/Examples/CMakeLists.txt @@ -2,4 +2,5 @@ add_subdirectory(HelloWorld) add_subdirectory(SimpleData) add_subdirectory(SlotsAndProperties) add_subdirectory(QtObjectMacro) -add_subdirectory(ContactApp) \ No newline at end of file +add_subdirectory(ContactApp) +add_subdirectory(AbstractItemModel) \ No newline at end of file diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 11dd89f..9b17c60 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -503,12 +503,12 @@ proc dos_qmodelindex_parent(modelIndex: RawQModelIndex, parent: RawQModelIndex) 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) = +proc create*(modelIndex: var QModelIndex) = ## Create a new QModelIndex dos_qmodelindex_create(modelIndex.data) modelIndex.deleted = false -proc delete(modelIndex: QModelIndex) = +proc delete*(modelIndex: QModelIndex) = ## Delete the given QModelIndex if not modelIndex.deleted: debugMsg("QModelIndex", "delete") @@ -521,34 +521,58 @@ proc newQModelIndex*(): QModelIndex = newWithCondFinalizer(result, delete) result.create() -proc row(modelIndex: QModelIndex): cint = +proc row*(modelIndex: QModelIndex): cint = ## Return the index row dos_qmodelindex_row(modelIndex.data, result) -proc column(modelIndex: QModelIndex): cint = +proc column*(modelIndex: QModelIndex): cint = ## Return the index column dos_qmodelindex_column(modelIndex.data, result) -proc isValid(modelIndex: QModelIndex): bool = +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 = +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 = +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 = +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 = +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) + + +# QAbstractListModel +proc dos_qabstractlistmodel_create(modelIndex: var RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qabstractlistmodel_delete(modelIndex: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create*(model: var QAbstractListModel) = + ## Create a new QAbstractListModel + debugMsg("QAbstractListModel", "create") + dos_qabstractlistmodel_create(model.data) + model.deleted = false + +proc delete*(model: QAbstractListModel) = + ## Delete the given QAbstractListModel + if not model.deleted: + debugMsg("QAbstractListModel", "delete") + dos_qabstractlistmodel_delete(model.data) + model.data = nil.RawQAbstractListModel + model.deleted = true + +proc newQAbstractListModel*(): QAbstractListModel = + ## Return a new QAbstractListModel + newWithCondFinalizer(result, delete) + result.create() diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index bc4f5ec..c1f5442 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -37,3 +37,8 @@ type QModelIndex = ref object of RootObj ## A QModelIndex data: RawQModelIndex deleted: bool + + RawQAbstractListModel = distinct pointer + QAbstractListModel = ref object of RootObj ## A QAbstactListModel + data: RawQAbstractListModel + deleted: bool From 9f3be669e74bd24febba89ebe5f4240dc168083c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Tue, 20 Jan 2015 21:18:58 +0100 Subject: [PATCH 35/58] Started the rowCount callback --- .../DOtherSide/BaseQAbstractListModel.cpp | 12 +++++- .../DOtherSide/BaseQAbstractListModel.h | 12 +++++- DOtherSide/DOtherSide/DOtherSide.cpp | 6 ++- DOtherSide/DOtherSide/DOtherSide.h | 10 +++-- Nim/Examples/AbstractItemModel/main.nim | 3 ++ Nim/NimQml/NimQml.nim | 39 ++++++++++++++++--- Nim/NimQml/NimQmlTypes.nim | 3 +- 7 files changed, 70 insertions(+), 15 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 5763b91..7e49297 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -1,15 +1,23 @@ #include "BaseQAbstractListModel.h" -BaseQAbstractListModel::BaseQAbstractListModel() +BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, + RowCountCallback rowCountCallback) + : m_modelObject(modelObject) + , m_rowCountCallback(rowCountCallback) { } int BaseQAbstractListModel::rowCount(const QModelIndex& index) const { - return 0; + return m_rowCountCallback(m_modelObject); } QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const { return QVariant(); } + +void* BaseQAbstractListModel::modelObject() +{ + return m_modelObject; +} diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index c1b06ce..3f64b48 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -5,9 +5,11 @@ /// This class act as a base class for D and Nim QAbstractListModel class BaseQAbstractListModel : public QAbstractListModel { -public: + typedef int (*RowCountCallback) (void*); + + public: /// Constructor - BaseQAbstractListModel(); + BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback); /// Return the model's row count virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; @@ -15,4 +17,10 @@ public: /// Return the QVariant at the given index virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + /// Return the dModelPointer + void* modelObject(); + + private: + void* m_modelObject; + RowCountCallback m_rowCountCallback; }; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 9f09593..d3bc04b 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -417,9 +417,11 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) *siblingIndex = index->sibling(row, column); } -void dos_qabstractlistmodel_create(void** vptr) +void dos_qabstractlistmodel_create(void** vptr, + void* modelObject, + RowCountCallback rowCountCallback) { - auto model = new BaseQAbstractListModel(); + auto model = new BaseQAbstractListModel(modelObject, rowCountCallback); *vptr = model; } diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index b8eaa23..9766ab8 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -69,8 +69,8 @@ extern "C" void dos_qvariant_assign(void* vptr, void* other); // QObject - void dos_qobject_create(void **vptr, - void *dObjectPointer, + void dos_qobject_create(void** vptr, + void* dObjectPointer, DObjectCallback dObjectCallback); void dos_qobject_slot_create(void* vptr, @@ -110,7 +110,11 @@ extern "C" void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling); // QAbstractListModel - void dos_qabstractlistmodel_create(void** vptr); + typedef int(*RowCountCallback)(void*); + + void dos_qabstractlistmodel_create(void** vptr, + void* callbackObject, + RowCountCallback rowCountCallback); void dos_qabstractlistmodel_delete(void* vptr); #ifdef __cplusplus diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index 5eb92ad..b5b4adf 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -5,6 +5,9 @@ import typeinfo proc mainProc() = var myListModel = newQAbstractListModel() defer: myListModel.delete() + let rows = myListModel.rowCount + echo rows + when isMainModule: mainProc() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 9b17c60..b727622 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -63,6 +63,7 @@ proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {. proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_float(variant: var RawQVariant, value: cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_double(variant: var RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qabstractlistmodel(variant: var RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -77,6 +78,7 @@ proc dos_qvariant_setFloat(variant: RawQVariant, value: float) {.cdecl, dynlib: proc dos_qvariant_toDouble(variant: RawQVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setDouble(variant: RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setQObject(variant: RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_setQAbstractListModel(variant: RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: QVariant) = @@ -104,6 +106,11 @@ proc create*(variant: QVariant, value: QObject) = dos_qvariant_create_qobject(variant.data, value.data) variant.deleted = false +proc create*(variant: QVariant, value: QAbstractListModel) = + ## Create a new QVariant given a QAbstractListModel + dos_qvariant_create_qabstractlistmodel(variant.data, value.data) + variant.deleted = false + proc create*(variant: QVariant, value: RawQVariant) = ## Create a new QVariant given another QVariant. ## The inner value of the QVariant is copied @@ -153,6 +160,11 @@ proc newQVariant*(value: QObject): QVariant = newWithCondFinalizer(result, delete) result.create(value) +proc newQVariant*(value: QAbstractListModel): QVariant = + ## Return a new QVariant given a QAbstractListModel + newWithCondFinalizer(result, delete) + result.create(value) + proc newQVariant*(value: RawQVariant): QVariant = ## Return a new QVariant given a raw QVariant pointer newWithCondFinalizer(result, delete) @@ -227,6 +239,10 @@ proc `qobjectVal=`*(variant: QVariant, value: QObject) = ## Sets the QVariant qobject value dos_qvariant_setQObject(variant.data, value.data) +proc `qabstractListModelVal=`*(variant: QVariant, value: QAbstractListModel) = + ## Sets the QVariant qabstractlistmodel value + dos_qvariant_setQAbstractListModel(variant.data, value.data) + 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) @@ -554,14 +570,27 @@ proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex = dos_qmodelindex_sibling(modelIndex.data, row, column, result.data) -# QAbstractListModel -proc dos_qabstractlistmodel_create(modelIndex: var RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qabstractlistmodel_delete(modelIndex: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} +# QAbstractListModel +type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj): cint {.cdecl.} + +proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, + modelPtr: ptr QAbstractListModelObj, + rowCountCallback: RowCountCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} +method rowCount*(model: QAbstractListModel): cint = + ## Return the model's row count + return 0 + +proc rowCountCallback(modelObject: ptr QAbstractListModelObj): cint {.cdecl, exportc.} = + let model = cast[QAbstractListModel](modelObject) + return model.rowCount + proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel debugMsg("QAbstractListModel", "create") - dos_qabstractlistmodel_create(model.data) + let modelPtr = addr(model[]) + dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback) model.deleted = false proc delete*(model: QAbstractListModel) = @@ -571,7 +600,7 @@ proc delete*(model: QAbstractListModel) = dos_qabstractlistmodel_delete(model.data) model.data = nil.RawQAbstractListModel model.deleted = true - + proc newQAbstractListModel*(): QAbstractListModel = ## Return a new QAbstractListModel newWithCondFinalizer(result, delete) diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index c1f5442..5e794c7 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -39,6 +39,7 @@ type deleted: bool RawQAbstractListModel = distinct pointer - QAbstractListModel = ref object of RootObj ## A QAbstactListModel + QAbstractListModelObj = object of RootObj data: RawQAbstractListModel deleted: bool + QAbstractListModel = ref QAbstractListModelObj ## A QAbstractListModel From 470b2647b886c31d2c69c15b8f272af0d838f3e7 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 26 Jan 2015 19:11:50 +0100 Subject: [PATCH 36/58] Fixed the AbstractListModel example --- DOtherSide/DOtherSide/DOtherSide.cpp | 15 +++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 2 ++ Nim/Examples/AbstractItemModel/main.nim | 20 +++++++++++++++++++- Nim/NimQml/NimQmlTypes.nim | 2 +- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index d3bc04b..fe8b82b 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -203,6 +203,14 @@ void dos_qvariant_create_double(void** vptr, double value) *vptr = new QVariant(value); } +void dos_qvariant_create_qabstractlistmodel(void** vptr, void* value) +{ + auto qobject = reinterpret_cast(value); + auto variant = new QVariant(); + variant->setValue(qobject); + *vptr = variant; +} + void dos_qvariant_isnull(void* vptr, bool& isNull) { auto variant = reinterpret_cast(vptr); @@ -289,6 +297,13 @@ void dos_qvariant_setQObject(void* vptr, void* value) variant->setValue(qobject); } +void dos_qvariant_setQAbstractListModel(void* vptr, void* value) +{ + auto variant = reinterpret_cast(vptr); + auto qobject = reinterpret_cast(value); + variant->setValue(qobject); +} + void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback) { auto dynamicQObject = new DynamicQObject(); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 9766ab8..aabfee9 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -53,6 +53,7 @@ extern "C" 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); @@ -64,6 +65,7 @@ extern "C" 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_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); diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index b5b4adf..5aff7e6 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -2,8 +2,26 @@ import NimQml import macros import typeinfo +type MyQAbstractListModel = ref object of QAbstractListModel + m_name: string + +proc create(self: MyQAbstractListModel) = + var qAbstractListModel = self.QAbstractListModel + qAbstractListModel.create() + +proc delete(self: MyQAbstractListModel) = + var qAbstractListModel = self.QAbstractListModel + qAbstractListModel.delete() + +proc newMyQAbstractListModel(): MyQAbstractListModel = + new(result, delete) + result.create() + +method rowCount(self: MyQAbstractListModel): cint = + return 103 + proc mainProc() = - var myListModel = newQAbstractListModel() + var myListModel = newMyQAbstractListModel() defer: myListModel.delete() let rows = myListModel.rowCount echo rows diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 5e794c7..3163aae 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -42,4 +42,4 @@ type QAbstractListModelObj = object of RootObj data: RawQAbstractListModel deleted: bool - QAbstractListModel = ref QAbstractListModelObj ## A QAbstractListModel + QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel From b7cbe8691cab023d9dc87bbe7fdcc9cb570f34a5 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 26 Jan 2015 19:43:25 +0100 Subject: [PATCH 37/58] Added index to the rowCount callback --- .../DOtherSide/BaseQAbstractListModel.cpp | 4 ++- .../DOtherSide/BaseQAbstractListModel.h | 2 +- DOtherSide/DOtherSide/DOtherSide.h | 2 +- Nim/Examples/AbstractItemModel/main.nim | 30 +++++++++++++------ Nim/Examples/AbstractItemModel/main.qml | 2 +- Nim/NimQml/NimQml.nim | 19 +++++++++--- Nim/NimQml/NimQmlTypes.nim | 2 +- 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 7e49297..05082ae 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -9,7 +9,9 @@ BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, int BaseQAbstractListModel::rowCount(const QModelIndex& index) const { - return m_rowCountCallback(m_modelObject); + auto newIndex = new QModelIndex(); + *newIndex = index; + return m_rowCountCallback(m_modelObject, newIndex); } QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 3f64b48..f1c12c1 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -5,7 +5,7 @@ /// This class act as a base class for D and Nim QAbstractListModel class BaseQAbstractListModel : public QAbstractListModel { - typedef int (*RowCountCallback) (void*); + typedef int (*RowCountCallback) (void* model, void* index); public: /// Constructor diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index aabfee9..0aa3a41 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -112,7 +112,7 @@ extern "C" void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling); // QAbstractListModel - typedef int(*RowCountCallback)(void*); + typedef int(*RowCountCallback)(void* model, void* index); void dos_qabstractlistmodel_create(void** vptr, void* callbackObject, diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index 5aff7e6..a8ddb09 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -7,25 +7,37 @@ type MyQAbstractListModel = ref object of QAbstractListModel proc create(self: MyQAbstractListModel) = var qAbstractListModel = self.QAbstractListModel - qAbstractListModel.create() + qAbstractListModel.create proc delete(self: MyQAbstractListModel) = var qAbstractListModel = self.QAbstractListModel - qAbstractListModel.delete() + qAbstractListModel.delete proc newMyQAbstractListModel(): MyQAbstractListModel = new(result, delete) - result.create() + result.create -method rowCount(self: MyQAbstractListModel): cint = - return 103 +method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint = + echo "index valid: " & $index.isValid & " row: " & $index.row & " column: " & $index.column + return 3 proc mainProc() = - var myListModel = newMyQAbstractListModel() - defer: myListModel.delete() - let rows = myListModel.rowCount - echo rows + 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() diff --git a/Nim/Examples/AbstractItemModel/main.qml b/Nim/Examples/AbstractItemModel/main.qml index 0edd37b..f650e6d 100644 --- a/Nim/Examples/AbstractItemModel/main.qml +++ b/Nim/Examples/AbstractItemModel/main.qml @@ -17,7 +17,7 @@ ApplicationWindow { width: 10 height: 10 - color: "red" + color: index % 2 == 0 ? "red" : "black" } } diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index b727622..b91cade 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -524,6 +524,11 @@ proc create*(modelIndex: var 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: @@ -537,6 +542,11 @@ proc newQModelIndex*(): 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) @@ -571,20 +581,21 @@ proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex = # QAbstractListModel -type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj): cint {.cdecl.} +type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex): cint {.cdecl.} proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, modelPtr: ptr QAbstractListModelObj, rowCountCallback: RowCountCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} -method rowCount*(model: QAbstractListModel): cint = +method rowCount*(model: QAbstractListModel, index: QModelIndex): cint = ## Return the model's row count return 0 -proc rowCountCallback(modelObject: ptr QAbstractListModelObj): cint {.cdecl, exportc.} = +proc rowCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex): cint {.cdecl, exportc.} = let model = cast[QAbstractListModel](modelObject) - return model.rowCount + let index = newQModelIndex(rawIndex) + return model.rowCount(index) proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 3163aae..9b72844 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -34,7 +34,7 @@ type QQmlContext* = distinct pointer ## A QQmlContext RawQModelIndex = distinct pointer - QModelIndex = ref object of RootObj ## A QModelIndex + QModelIndex* = ref object of RootObj ## A QModelIndex data: RawQModelIndex deleted: bool From df498cb64c916df7f033baf5df99a78be5cab4c8 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 26 Jan 2015 21:26:21 +0100 Subject: [PATCH 38/58] Added data callback --- .../DOtherSide/BaseQAbstractListModel.cpp | 26 ++++++++++++------- .../DOtherSide/BaseQAbstractListModel.h | 8 +++--- DOtherSide/DOtherSide/DOtherSide.cpp | 7 ++--- DOtherSide/DOtherSide/DOtherSide.h | 11 ++++---- Nim/Examples/AbstractItemModel/main.nim | 3 +++ Nim/NimQml/NimQml.nim | 26 ++++++++++++++----- 6 files changed, 55 insertions(+), 26 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 05082ae..c461d9d 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -1,25 +1,33 @@ #include "BaseQAbstractListModel.h" BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, - RowCountCallback rowCountCallback) - : m_modelObject(modelObject) - , m_rowCountCallback(rowCountCallback) + RowCountCallback rowCountCallback, + DataCallback dataCallback) + : m_modelObject(modelObject) + , m_rowCountCallback(rowCountCallback) + , m_dataCallback(dataCallback) { } -int BaseQAbstractListModel::rowCount(const QModelIndex& index) const +int BaseQAbstractListModel::rowCount(const QModelIndex& index) const { - auto newIndex = new QModelIndex(); - *newIndex = index; - return m_rowCountCallback(m_modelObject, newIndex); + auto newIndex = new QModelIndex(); + *newIndex = index; + int result; + m_rowCountCallback(m_modelObject, newIndex, &result); + return result; } QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const { - return QVariant(); + auto newIndex = new QModelIndex(); + *newIndex = index; + QVariant result; + m_dataCallback(m_modelObject, newIndex, role, &result); + return result; } void* BaseQAbstractListModel::modelObject() { - return m_modelObject; + return m_modelObject; } diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index f1c12c1..13a40b7 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -1,15 +1,16 @@ #pragma once +#include "DOtherSideTypes.h" #include /// This class act as a base class for D and Nim QAbstractListModel class BaseQAbstractListModel : public QAbstractListModel { - typedef int (*RowCountCallback) (void* model, void* index); - public: /// Constructor - BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback); + BaseQAbstractListModel(void* modelObject, + RowCountCallback rowCountCallback, + DataCallback dataCallback); /// Return the model's row count virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; @@ -23,4 +24,5 @@ class BaseQAbstractListModel : public QAbstractListModel private: void* m_modelObject; RowCountCallback m_rowCountCallback; + DataCallback m_dataCallback; }; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index fe8b82b..1ba3006 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -433,10 +433,11 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) } void dos_qabstractlistmodel_create(void** vptr, - void* modelObject, - RowCountCallback rowCountCallback) + void* modelObject, + RowCountCallback rowCountCallback, + DataCallback dataCallback) { - auto model = new BaseQAbstractListModel(modelObject, rowCountCallback); + auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, dataCallback); *vptr = model; } diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 0aa3a41..158406c 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -1,6 +1,8 @@ #ifndef DOTHERSIDE_H #define DOTHERSIDE_H +#include "DOtherSideTypes.h" + #ifdef __cplusplus extern "C" { @@ -111,12 +113,11 @@ extern "C" void dos_qmodelindex_child(void* vptr, int row, int column, void* child); void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling); - // QAbstractListModel - typedef int(*RowCountCallback)(void* model, void* index); - + // QAbstractListModel void dos_qabstractlistmodel_create(void** vptr, - void* callbackObject, - RowCountCallback rowCountCallback); + void* callbackObject, + RowCountCallback rowCountCallback, + DataCallback dataCallback); void dos_qabstractlistmodel_delete(void* vptr); #ifdef __cplusplus diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index a8ddb09..a426a2a 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -20,6 +20,9 @@ proc newMyQAbstractListModel(): MyQAbstractListModel = method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint = echo "index valid: " & $index.isValid & " row: " & $index.row & " column: " & $index.column return 3 + +method data(self: MyQAbstractListModel, index: QModelIndex, role: cint): QVariant = + return nil proc mainProc() = var app = newQApplication() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index b91cade..2444eee 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -581,27 +581,41 @@ proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex = # QAbstractListModel -type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex): cint {.cdecl.} - +type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.} +type DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.} + proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, modelPtr: ptr QAbstractListModelObj, - rowCountCallback: RowCountCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} + rowCountCallback: RowCountCallback, + dataCallback: DataCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.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): cint {.cdecl, exportc.} = +proc rowCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} = let model = cast[QAbstractListModel](modelObject) let index = newQModelIndex(rawIndex) - return model.rowCount(index) + result = model.rowCount(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.} = + 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 proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel debugMsg("QAbstractListModel", "create") let modelPtr = addr(model[]) - dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback) + dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback, dataCallback) model.deleted = false proc delete*(model: QAbstractListModel) = From 95aeef5db0eedcee5a07601fbaa5b212ea04f944 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 12:50:14 +0100 Subject: [PATCH 39/58] Started adding support for RoleNames --- .../DOtherSide/BaseQAbstractListModel.cpp | 7 +++++ .../DOtherSide/BaseQAbstractListModel.h | 3 ++ DOtherSide/DOtherSide/DOtherSide.cpp | 28 +++++++++++++++---- DOtherSide/DOtherSide/DOtherSide.h | 5 ++++ Nim/Examples/AbstractItemModel/main.nim | 2 +- Nim/NimQml/NimQml.nim | 21 ++++++++++++++ Nim/NimQml/NimQmlTypes.nim | 6 ++++ 7 files changed, 66 insertions(+), 6 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index c461d9d..b86d01d 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -31,3 +31,10 @@ void* BaseQAbstractListModel::modelObject() { return m_modelObject; } + +QHash BaseQAbstractListModel::roleNames() const +{ + QHash result; + return result; +} + diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 13a40b7..c14dfc3 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -21,6 +21,9 @@ class BaseQAbstractListModel : public QAbstractListModel /// Return the dModelPointer void* modelObject(); + /// Return the roleNames + virtual QHash roleNames() const override; + private: void* m_modelObject; RowCountCallback m_rowCountCallback; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 1ba3006..f5d49a8 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -1,13 +1,13 @@ #include "DOtherSide.h" -#include -#include -#include -#include #include #include -#include #include +#include +#include +#include +#include +#include #include "DynamicQObject.h" #include "BaseQAbstractListModel.h" @@ -446,3 +446,21 @@ void dos_qabstractlistmodel_delete(void* vptr) auto model = reinterpret_cast(vptr); delete model; } + +void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr) +{ + *vptr = new QHash(); +} + +void dos_qhash_int_qbytearray_delete(QHashIntQByteArrayVoidPtr vptr) +{ + auto qHash = reinterpret_cast*>(vptr); + delete qHash; +} + +void dos_qhash_int_qbytearray_insert(QHashIntQByteArrayVoidPtr vptr, int key, ConstCharPtr value) +{ + auto qHash = reinterpret_cast*>(vptr); + qHash->insert(key, QByteArray(value)); +} + diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 158406c..83224ff 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -113,6 +113,11 @@ extern "C" 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 + 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, ConstCharPtr value); + // QAbstractListModel void dos_qabstractlistmodel_create(void** vptr, void* callbackObject, diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index a426a2a..b9279da 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -3,7 +3,6 @@ import macros import typeinfo type MyQAbstractListModel = ref object of QAbstractListModel - m_name: string proc create(self: MyQAbstractListModel) = var qAbstractListModel = self.QAbstractListModel @@ -22,6 +21,7 @@ method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint = return 3 method data(self: MyQAbstractListModel, index: QModelIndex, role: cint): QVariant = + echo "index valid: " & $index.isValid & " row: " & $index.row & " column: " & $index.column return nil proc mainProc() = diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 2444eee..50a3a1b 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -630,3 +630,24 @@ proc newQAbstractListModel*(): QAbstractListModel = ## Return a new QAbstractListModel newWithCondFinalizer(result, delete) result.create() + +# RoleNames QHash +proc dos_qhash_int_qbytearray_create(qHash: 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 create(qHash: var QHashIntByteArray) = + debugMsg("QHashIntByteArray", "create") + dos_qhash_int_qbytearray_create(qHash.data) + qHash.deleted = false + +proc delete(qHash: QHashIntByteArray) = + dos_qhash_int_qbytearray_delete(qHash.data) + qHash.deleted = true + +proc insert(qHash: QHashIntByteArray, key: int, value: cstring) = + dos_qhash_int_qbytearray_insert(qHash.data, key, value) + +proc newQHashIntQByteArray(): QHashIntByteArray = + newWithCondFinalizer(result, delete) + result.create() diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 9b72844..231b0a3 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -43,3 +43,9 @@ type data: RawQAbstractListModel deleted: bool QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel + + RawQHashIntByteArray = distinct pointer + QHashIntByteArrayObj = object of RootObj + data: RawQHashIntByteArray + deleted: bool + QHashIntByteArray = ref QHashIntByteArrayObj ## A QHash From 634cc3ea39f612f0579bc8c9c90d93103d5e0812 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 14:20:36 +0100 Subject: [PATCH 40/58] Cleanedup the DOtherSide.h C interface from C++ references types --- DOtherSide/DOtherSide/DOtherSide.cpp | 136 +++++++------- DOtherSide/DOtherSide/DOtherSide.h | 209 +++++++++++----------- DOtherSide/DOtherSide/DOtherSideTypes.h | 22 +++ DOtherSide/DynamicQObject/DynamicSlot.cpp | 2 - Nim/Examples/AbstractItemModel/main.nim | 10 +- Nim/NimQml/NimQml.nim | 63 ++++--- Nim/NimQml/NimQmlTypes.nim | 2 +- 7 files changed, 252 insertions(+), 192 deletions(-) create mode 100644 DOtherSide/DOtherSide/DOtherSideTypes.h diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index f5d49a8..b5a404d 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -8,15 +8,16 @@ #include #include #include +#include #include "DynamicQObject.h" #include "BaseQAbstractListModel.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() @@ -106,7 +107,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(vptr); QUrl url = view->source(); @@ -125,25 +126,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(vptr); QUrl url = context->baseUrl(); @@ -179,10 +180,10 @@ 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(other); - *newQVariant = *otherQVariant; - *vptr = newQVariant; + auto newQVariant = new QVariant(); + auto otherQVariant = reinterpret_cast(other); + *newQVariant = *otherQVariant; + *vptr = newQVariant; } void dos_qvariant_create_qobject(void **vptr, void* value) @@ -211,10 +212,10 @@ void dos_qvariant_create_qabstractlistmodel(void** vptr, void* value) *vptr = variant; } -void dos_qvariant_isnull(void* vptr, bool& isNull) +void dos_qvariant_isnull(void* vptr, bool* isNull) { auto variant = reinterpret_cast(vptr); - isNull = variant->isNull(); + *isNull = variant->isNull(); } void dos_qvariant_delete(void *vptr) @@ -225,36 +226,36 @@ void dos_qvariant_delete(void *vptr) void dos_qvariant_assign(void* vptr, void* other) { - auto leftQVariant = reinterpret_cast(vptr); - auto rightQVariant = reinterpret_cast(other); - *leftQVariant = *rightQVariant; + auto leftQVariant = reinterpret_cast(vptr); + auto rightQVariant = reinterpret_cast(other); + *leftQVariant = *rightQVariant; } -void dos_qvariant_toInt(void* vptr, int& value) +void dos_qvariant_toInt(void* vptr, int* value) { auto variant = reinterpret_cast(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(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(vptr); - value = variant->toFloat(); + auto variant = reinterpret_cast(vptr); + *value = variant->toFloat(); } -void dos_qvariant_toDouble(void* vptr, double& value) +void dos_qvariant_toDouble(void* vptr, double* value) { - auto variant = reinterpret_cast(vptr); - value = variant->toDouble(); + auto variant = reinterpret_cast(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(vptr); convert_to_cstring(variant->toString(), ptr, size); @@ -292,9 +293,9 @@ void dos_qvariant_setString(void* vptr, const char* value) void dos_qvariant_setQObject(void* vptr, void* value) { - auto variant = reinterpret_cast(vptr); - auto qobject = reinterpret_cast(value); - variant->setValue(qobject); + auto variant = reinterpret_cast(vptr); + auto qobject = reinterpret_cast(value); + variant->setValue(qobject); } void dos_qvariant_setQAbstractListModel(void* vptr, void* value) @@ -376,60 +377,60 @@ void dos_qobject_property_create(void* vptr, void dos_qmodelindex_create(void** vptr) { - auto index = new QModelIndex(); - *vptr = index; + auto index = new QModelIndex(); + *vptr = index; } void dos_qmodelindex_delete(void* vptr) { - auto index = reinterpret_cast(vptr); - delete index; + auto index = reinterpret_cast(vptr); + delete index; } -void dos_qmodelindex_row(void* vptr, int& row) +void dos_qmodelindex_row(void* vptr, int* row) { - auto index = reinterpret_cast(vptr); - row = index->row(); + auto index = reinterpret_cast(vptr); + *row = index->row(); } -void dos_qmodelindex_column(void* vptr, int& column) +void dos_qmodelindex_column(void* vptr, int* column) { - auto index = reinterpret_cast(vptr); - column = index->column(); + auto index = reinterpret_cast(vptr); + *column = index->column(); } -void dos_qmodelindex_isValid(void* vptr, bool& isValid) +void dos_qmodelindex_isValid(void* vptr, bool* isValid) { - auto index = reinterpret_cast(vptr); - isValid = index->isValid(); + auto index = reinterpret_cast(vptr); + *isValid = index->isValid(); } void dos_qmodelindex_data(void* vptr, int role, void* data) { - auto index = reinterpret_cast(vptr); - auto result = reinterpret_cast(data); - *result = index->data(role); + auto index = reinterpret_cast(vptr); + auto result = reinterpret_cast(data); + *result = index->data(role); } void dos_qmodelindex_parent(void* vptr, void* parent) { - auto index = reinterpret_cast(vptr); - auto parentIndex = reinterpret_cast(parent); - *parentIndex = index->parent(); + auto index = reinterpret_cast(vptr); + auto parentIndex = reinterpret_cast(parent); + *parentIndex = index->parent(); } void dos_qmodelindex_child(void* vptr, int row, int column, void* child) { - auto index = reinterpret_cast(vptr); - auto childIndex = reinterpret_cast(child); - *childIndex = index->child(row, column); + auto index = reinterpret_cast(vptr); + auto childIndex = reinterpret_cast(child); + *childIndex = index->child(row, column); } void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) { - auto index = reinterpret_cast(vptr); - auto siblingIndex = reinterpret_cast(sibling); - *siblingIndex = index->sibling(row, column); + auto index = reinterpret_cast(vptr); + auto siblingIndex = reinterpret_cast(sibling); + *siblingIndex = index->sibling(row, column); } void dos_qabstractlistmodel_create(void** vptr, @@ -437,14 +438,14 @@ void dos_qabstractlistmodel_create(void** vptr, RowCountCallback rowCountCallback, DataCallback dataCallback) { - auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, dataCallback); - *vptr = model; + auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, dataCallback); + *vptr = model; } void dos_qabstractlistmodel_delete(void* vptr) { - auto model = reinterpret_cast(vptr); - delete model; + auto model = reinterpret_cast(vptr); + delete model; } void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr) @@ -458,9 +459,16 @@ void dos_qhash_int_qbytearray_delete(QHashIntQByteArrayVoidPtr vptr) delete qHash; } -void dos_qhash_int_qbytearray_insert(QHashIntQByteArrayVoidPtr vptr, int key, ConstCharPtr value) +void dos_qhash_int_qbytearray_insert(QHashIntQByteArrayVoidPtr vptr, int key, const char* value) { auto qHash = reinterpret_cast*>(vptr); qHash->insert(key, QByteArray(value)); } +void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, char** result) +{ + auto qHash = reinterpret_cast*>(vptr); + QByteArray value = qHash->value(key); + *result = qstrdup(value.data()); +} + diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 83224ff..b14d038 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -8,122 +8,123 @@ 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_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, CharPtr& 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); +// 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); - // 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 - 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, ConstCharPtr value); - - // QAbstractListModel - void dos_qabstractlistmodel_create(void** vptr, - void* callbackObject, - RowCountCallback rowCountCallback, - DataCallback dataCallback); - void dos_qabstractlistmodel_delete(void* vptr); +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 +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, + RowCountCallback rowCountCallback, + DataCallback dataCallback); +void dos_qabstractlistmodel_delete(void* vptr); #ifdef __cplusplus } diff --git a/DOtherSide/DOtherSide/DOtherSideTypes.h b/DOtherSide/DOtherSide/DOtherSideTypes.h new file mode 100644 index 0000000..d1544e1 --- /dev/null +++ b/DOtherSide/DOtherSide/DOtherSideTypes.h @@ -0,0 +1,22 @@ +#ifndef DOTHERSIDETYPES_H +#define DOTHERSIDETYPES_H + +// Raw data types +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 (*DataCallback) (void* model, QModelIndexVoidPtr index, int role, QVariantVoidPtr result); + +#endif \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/DynamicSlot.cpp b/DOtherSide/DynamicQObject/DynamicSlot.cpp index a8a7bcc..320bc10 100644 --- a/DOtherSide/DynamicQObject/DynamicSlot.cpp +++ b/DOtherSide/DynamicQObject/DynamicSlot.cpp @@ -106,6 +106,4 @@ void DynamicSlot::_initSignature() } d->signature = signature.arg(d->name, arguments).toUtf8(); - - qDebug() << "C++: slot signature is " << d->signature; } diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index b9279da..f304d48 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -41,8 +41,16 @@ proc mainProc() = engine.load("main.qml") app.exec() + +proc mainProc2() = + var qhash = newQHashIntQByteArray() + defer: qHash.delete + qhash.insert(0,"Name") + qhash.insert(1, "Surname") + echo qhash.value(0) + echo qhash.value(1) when isMainModule: - mainProc() + mainProc2() GC_fullcollect() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 50a3a1b..16ffd96 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -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`` @@ -632,22 +647,30 @@ proc newQAbstractListModel*(): QAbstractListModel = result.create() # RoleNames QHash -proc dos_qhash_int_qbytearray_create(qHash: RawQHashIntByteArray) {.cdecl, dynlib:"libDOtherSide.so", importc.} +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) = +proc create*(qHash: var QHashIntByteArray) = debugMsg("QHashIntByteArray", "create") dos_qhash_int_qbytearray_create(qHash.data) qHash.deleted = false -proc delete(qHash: QHashIntByteArray) = +proc delete*(qHash: QHashIntByteArray) = + debugMsg("QHashIntByteArray", "delete") dos_qhash_int_qbytearray_delete(qHash.data) qHash.deleted = true -proc insert(qHash: QHashIntByteArray, key: int, value: cstring) = +proc insert*(qHash: QHashIntByteArray, key: int, value: cstring) = dos_qhash_int_qbytearray_insert(qHash.data, key, value) -proc newQHashIntQByteArray(): QHashIntByteArray = +proc value*(qHash: QHashIntByteArray, key: int): string = + var rawString: cstring + dos_qhash_int_qbytearray_value(qHash.data, key, rawString) + result = $rawString + dos_chararray_delete(rawString) + +proc newQHashIntQByteArray*(): QHashIntByteArray = newWithCondFinalizer(result, delete) result.create() diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 231b0a3..0f9c59d 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -48,4 +48,4 @@ type QHashIntByteArrayObj = object of RootObj data: RawQHashIntByteArray deleted: bool - QHashIntByteArray = ref QHashIntByteArrayObj ## A QHash + QHashIntByteArray* = ref QHashIntByteArrayObj ## A QHash From 34776efd7bb9cc44e28ae2609f4948581024409a Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 16:30:12 +0100 Subject: [PATCH 41/58] Completed the initial implementation for the RoleNames --- .../DOtherSide/BaseQAbstractListModel.cpp | 5 +- .../DOtherSide/BaseQAbstractListModel.h | 6 +- DOtherSide/DOtherSide/DOtherSide.cpp | 9 ++- DOtherSide/DOtherSide/DOtherSide.h | 3 +- DOtherSide/DOtherSide/DOtherSideTypes.h | 3 +- Nim/NimQml/NimQml.nim | 77 +++++++++++-------- 6 files changed, 66 insertions(+), 37 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index b86d01d..158c838 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -2,10 +2,12 @@ BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback, - DataCallback dataCallback) + DataCallback dataCallback, + RoleNamesCallback roleNamesCallback) : m_modelObject(modelObject) , m_rowCountCallback(rowCountCallback) , m_dataCallback(dataCallback) + , m_roleNamesCallback(roleNamesCallback) { } @@ -35,6 +37,7 @@ void* BaseQAbstractListModel::modelObject() QHash BaseQAbstractListModel::roleNames() const { QHash result; + m_roleNamesCallback(m_modelObject, &result); return result; } diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index c14dfc3..972a848 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -10,7 +10,8 @@ class BaseQAbstractListModel : public QAbstractListModel /// Constructor BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback, - DataCallback dataCallback); + DataCallback dataCallback, + RoleNamesCallback roleNamesCallback); /// Return the model's row count virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; @@ -24,8 +25,11 @@ class BaseQAbstractListModel : public QAbstractListModel /// Return the roleNames virtual QHash roleNames() const override; + + private: void* m_modelObject; RowCountCallback m_rowCountCallback; DataCallback m_dataCallback; + RoleNamesCallback m_roleNamesCallback; }; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index b5a404d..3d52e08 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -359,7 +359,6 @@ void dos_qobject_signal_emit(void* vptr, const char* name, int parametersCount, dynamicQObject->emitSignal(QString::fromStdString(name), arguments); } - void dos_qobject_property_create(void* vptr, const char* name, int type, @@ -436,9 +435,13 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) void dos_qabstractlistmodel_create(void** vptr, void* modelObject, RowCountCallback rowCountCallback, - DataCallback dataCallback) + DataCallback dataCallback, + RoleNamesCallback roleNamesCallaback) { - auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, dataCallback); + auto model = new BaseQAbstractListModel(modelObject, + rowCountCallback, + dataCallback, + roleNamesCallaback); *vptr = model; } diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index b14d038..bb2fdf7 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -123,7 +123,8 @@ void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, cha void dos_qabstractlistmodel_create(void** vptr, void* callbackObject, RowCountCallback rowCountCallback, - DataCallback dataCallback); + DataCallback dataCallback, + RoleNamesCallback roleNamesCallback); void dos_qabstractlistmodel_delete(void* vptr); #ifdef __cplusplus diff --git a/DOtherSide/DOtherSide/DOtherSideTypes.h b/DOtherSide/DOtherSide/DOtherSideTypes.h index d1544e1..b08c16d 100644 --- a/DOtherSide/DOtherSide/DOtherSideTypes.h +++ b/DOtherSide/DOtherSide/DOtherSideTypes.h @@ -18,5 +18,6 @@ typedef void (*Function)(void*); typedef void (*DObjectCallback)(void*, void*, int, void**); typedef void (*RowCountCallback) (void* model, QModelIndexVoidPtr index, IntPtr result); typedef void (*DataCallback) (void* model, QModelIndexVoidPtr index, int role, QVariantVoidPtr result); - +typedef void (*RoleNamesCallback) (void* model, QHashIntQByteArrayVoidPtr result); + #endif \ No newline at end of file diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 16ffd96..25b1042 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -594,15 +594,51 @@ proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex = 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.} type DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.} +type RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: RawQHashIntByteArray) {.cdecl.} proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, modelPtr: ptr QAbstractListModelObj, rowCountCallback: RowCountCallback, - dataCallback: DataCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} + dataCallback: DataCallback, + roleNamesCallback: RoleNamesCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} method rowCount*(model: QAbstractListModel, index: QModelIndex): cint = @@ -625,12 +661,21 @@ proc dataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelInd if variant != nil: dos_qvariant_assign(result, variant.data) variant.delete + +method roleNames*(model: QAbstractListModel): Table[int, cstring] = + discard() + +proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashIntByteArray) {.cdecl, exportc.} = + let model = cast[QAbstractListModel](modelObject) + let table = model.roleNames() + for pair in table.pairs: + dos_qhash_int_qbytearray_insert(hash, pair.key, pair.val) proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel debugMsg("QAbstractListModel", "create") let modelPtr = addr(model[]) - dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback, dataCallback) + dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback, dataCallback, roleNamesCallback) model.deleted = false proc delete*(model: QAbstractListModel) = @@ -646,31 +691,3 @@ proc newQAbstractListModel*(): QAbstractListModel = newWithCondFinalizer(result, delete) result.create() -# RoleNames QHash -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) = - debugMsg("QHashIntByteArray", "create") - dos_qhash_int_qbytearray_create(qHash.data) - qHash.deleted = false - -proc delete*(qHash: QHashIntByteArray) = - debugMsg("QHashIntByteArray", "delete") - dos_qhash_int_qbytearray_delete(qHash.data) - qHash.deleted = true - -proc insert*(qHash: QHashIntByteArray, key: int, value: cstring) = - dos_qhash_int_qbytearray_insert(qHash.data, key, value) - -proc value*(qHash: QHashIntByteArray, key: int): string = - var rawString: cstring - dos_qhash_int_qbytearray_value(qHash.data, key, rawString) - result = $rawString - dos_chararray_delete(rawString) - -proc newQHashIntQByteArray*(): QHashIntByteArray = - newWithCondFinalizer(result, delete) - result.create() From 27db2ef8545b89155f840e734f57f958b6ec0d57 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 16:46:41 +0100 Subject: [PATCH 42/58] Updated the QAbstractListModel example --- Nim/Examples/AbstractItemModel/main.nim | 37 +++++++++++++++---------- Nim/Examples/AbstractItemModel/main.qml | 7 +---- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index f304d48..b913566 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -1,12 +1,21 @@ import NimQml import macros import typeinfo +import tables -type MyQAbstractListModel = ref object of QAbstractListModel - +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 @@ -17,12 +26,18 @@ proc newMyQAbstractListModel(): MyQAbstractListModel = result.create method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint = - echo "index valid: " & $index.isValid & " row: " & $index.row & " column: " & $index.column - return 3 + return self.m_names.len.cint method data(self: MyQAbstractListModel, index: QModelIndex, role: cint): QVariant = - echo "index valid: " & $index.isValid & " row: " & $index.row & " column: " & $index.column - return nil + 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() @@ -42,15 +57,7 @@ proc mainProc() = app.exec() -proc mainProc2() = - var qhash = newQHashIntQByteArray() - defer: qHash.delete - qhash.insert(0,"Name") - qhash.insert(1, "Surname") - echo qhash.value(0) - echo qhash.value(1) - when isMainModule: - mainProc2() + mainProc() GC_fullcollect() diff --git a/Nim/Examples/AbstractItemModel/main.qml b/Nim/Examples/AbstractItemModel/main.qml index f650e6d..d3aa3a3 100644 --- a/Nim/Examples/AbstractItemModel/main.qml +++ b/Nim/Examples/AbstractItemModel/main.qml @@ -13,12 +13,7 @@ ApplicationWindow Component { id: myListModelDelegate - Rectangle - { - width: 10 - height: 10 - color: index % 2 == 0 ? "red" : "black" - } + Label { text: "Name:" + name } } ListView From 8e36e4d9574d0048a4636d926e19a705869d690a Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 17:01:03 +0100 Subject: [PATCH 43/58] Reformatted the code --- .../DOtherSide/BaseQAbstractListModel.cpp | 2 +- .../DOtherSide/BaseQAbstractListModel.h | 44 ++++++++-------- DOtherSide/DOtherSide/DOtherSide.cpp | 26 +++++----- DOtherSide/DOtherSide/DOtherSide.h | 24 ++++----- DOtherSide/DOtherSide/DOtherSideTypes.h | 8 +-- DOtherSide/DynamicQObject/DynamicProperty.cpp | 8 +-- DOtherSide/DynamicQObject/DynamicProperty.h | 4 +- DOtherSide/DynamicQObject/DynamicQObject.cpp | 52 +++++++++---------- DOtherSide/DynamicQObject/DynamicQObject.h | 20 ++++--- DOtherSide/IntegrationTest/main.cpp | 2 +- Nim/Examples/AbstractItemModel/main.nim | 1 + 11 files changed, 95 insertions(+), 96 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 158c838..35e3fcd 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -34,7 +34,7 @@ void* BaseQAbstractListModel::modelObject() return m_modelObject; } -QHash BaseQAbstractListModel::roleNames() const +QHash BaseQAbstractListModel::roleNames() const { QHash result; m_roleNamesCallback(m_modelObject, &result); diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 972a848..84ffc1d 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -6,30 +6,28 @@ /// This class act as a base class for D and Nim QAbstractListModel class BaseQAbstractListModel : public QAbstractListModel { - public: - /// Constructor - BaseQAbstractListModel(void* modelObject, - RowCountCallback rowCountCallback, - DataCallback dataCallback, - RoleNamesCallback roleNamesCallback); +public: + /// Constructor + BaseQAbstractListModel(void* modelObject, + RowCountCallback rowCountCallback, + DataCallback dataCallback, + RoleNamesCallback roleNamesCallback); - /// Return the model's row count - virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; + /// Return the model's row count + virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; - /// Return the QVariant at the given index - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + /// Return the QVariant at the given index + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - /// Return the dModelPointer - void* modelObject(); - - /// Return the roleNames - virtual QHash roleNames() const override; - - - - private: - void* m_modelObject; - RowCountCallback m_rowCountCallback; - DataCallback m_dataCallback; - RoleNamesCallback m_roleNamesCallback; + /// Return the dModelPointer + void* modelObject(); + + /// Return the roleNames + virtual QHash roleNames() const override; + +private: + void* m_modelObject; + RowCountCallback m_rowCountCallback; + DataCallback m_dataCallback; + RoleNamesCallback m_roleNamesCallback; }; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 3d52e08..fdf54c9 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -66,12 +66,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(vptr); engine->load(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QDir::separator() + QString(filename))); @@ -107,7 +107,7 @@ void dos_qquickview_delete(void* vptr) delete view; } -void dos_qquickview_source(void *vptr, char** result, int* length) +void dos_qquickview_source(void* vptr, char** result, int* length) { QQuickView* view = reinterpret_cast(vptr); QUrl url = view->source(); @@ -158,17 +158,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); } @@ -186,7 +186,7 @@ void dos_qvariant_create_qvariant(void** vptr, void* other) *vptr = newQVariant; } -void dos_qvariant_create_qobject(void **vptr, void* value) +void dos_qvariant_create_qobject(void** vptr, void* value) { auto qobject = reinterpret_cast(value); auto variant = new QVariant(); @@ -218,7 +218,7 @@ void dos_qvariant_isnull(void* vptr, bool* isNull) *isNull = variant->isNull(); } -void dos_qvariant_delete(void *vptr) +void dos_qvariant_delete(void* vptr) { auto variant = reinterpret_cast(vptr); delete variant; @@ -314,7 +314,7 @@ void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObje *vptr = dynamicQObject; } -void dos_qobject_delete(void *vptr) +void dos_qobject_delete(void* vptr) { auto dynamicQObject = reinterpret_cast(vptr); dynamicQObject->disconnect(); @@ -438,9 +438,9 @@ void dos_qabstractlistmodel_create(void** vptr, DataCallback dataCallback, RoleNamesCallback roleNamesCallaback) { - auto model = new BaseQAbstractListModel(modelObject, - rowCountCallback, - dataCallback, + auto model = new BaseQAbstractListModel(modelObject, + rowCountCallback, + dataCallback, roleNamesCallaback); *vptr = model; } @@ -458,7 +458,7 @@ void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr) void dos_qhash_int_qbytearray_delete(QHashIntQByteArrayVoidPtr vptr) { - auto qHash = reinterpret_cast*>(vptr); + auto qHash = reinterpret_cast*>(vptr); delete qHash; } diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index bb2fdf7..204becc 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -47,15 +47,15 @@ void dos_chararray_create(char** ptr, int size); void dos_chararray_delete(char* ptr); // 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_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); @@ -68,8 +68,8 @@ 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_isnull(void* vptr, bool* isNull); +void dos_qvariant_delete(void* vptr); void dos_qvariant_assign(void* vptr, void* other); // QObject @@ -100,7 +100,7 @@ void dos_qobject_property_create(void* vptr, const char* readSlot, const char* writeSlot, const char* notifySignal); -void dos_qobject_delete(void *vptr); +void dos_qobject_delete(void* vptr); // QModelIndex void dos_qmodelindex_create(void** vptr); diff --git a/DOtherSide/DOtherSide/DOtherSideTypes.h b/DOtherSide/DOtherSide/DOtherSideTypes.h index b08c16d..16a88d9 100644 --- a/DOtherSide/DOtherSide/DOtherSideTypes.h +++ b/DOtherSide/DOtherSide/DOtherSideTypes.h @@ -1,7 +1,7 @@ #ifndef DOTHERSIDETYPES_H #define DOTHERSIDETYPES_H -// Raw data types +// Raw data types typedef int* IntPtr; typedef char* CharPtr; typedef const char* ConstCharPtr; @@ -16,8 +16,8 @@ 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 (*DataCallback) (void* model, QModelIndexVoidPtr index, int role, QVariantVoidPtr result); -typedef void (*RoleNamesCallback) (void* model, QHashIntQByteArrayVoidPtr result); +typedef void (*RowCountCallback)(void* model, QModelIndexVoidPtr index, IntPtr result); +typedef void (*DataCallback)(void* model, QModelIndexVoidPtr index, int role, QVariantVoidPtr result); +typedef void (*RoleNamesCallback)(void* model, QHashIntQByteArrayVoidPtr result); #endif \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/DynamicProperty.cpp b/DOtherSide/DynamicQObject/DynamicProperty.cpp index 7682490..7a5aa0d 100644 --- a/DOtherSide/DynamicQObject/DynamicProperty.cpp +++ b/DOtherSide/DynamicQObject/DynamicProperty.cpp @@ -56,20 +56,14 @@ DynamicProperty::DynamicProperty(const DynamicProperty& other) d.reset(new PropertyData(*other.d)); } -DynamicProperty&DynamicProperty::operator=(const DynamicProperty& other) +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; } diff --git a/DOtherSide/DynamicQObject/DynamicProperty.h b/DOtherSide/DynamicQObject/DynamicProperty.h index b99056a..d77c09f 100644 --- a/DOtherSide/DynamicQObject/DynamicProperty.h +++ b/DOtherSide/DynamicQObject/DynamicProperty.h @@ -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; diff --git a/DOtherSide/DynamicQObject/DynamicQObject.cpp b/DOtherSide/DynamicQObject/DynamicQObject.cpp index 57705d8..ff8017f 100644 --- a/DOtherSide/DynamicQObject/DynamicQObject.cpp +++ b/DOtherSide/DynamicQObject/DynamicQObject.cpp @@ -21,8 +21,8 @@ bool DynamicQObject::registerSlot(const QString& name, const QMetaType::Type returnType, const QList& argumentsTypes, int& slotIndex) -{ - DynamicSlot slot (name, returnType, argumentsTypes); +{ + DynamicSlot slot(name, returnType, argumentsTypes); if (m_slotsBySignature.contains(slot.signature())) return false; @@ -33,16 +33,16 @@ bool DynamicQObject::registerSlot(const QString& name, auto afterSignalAdded = [](QMetaObjectBuilder&) {}; auto afterPropertyAdded = afterSignalAdded; - auto afterSlotAdded = [&slot, returnType](QMetaObjectBuilder& metaObjectBuilder) { + 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); + , afterSignalAdded + , afterSlotAdded + , afterPropertyAdded); m_metaObject.reset(newMetaObject); @@ -61,7 +61,7 @@ bool DynamicQObject::registerSignal(const QString& name, const QList& args QVariantList argsCopy = args; - QVector arguments(argsCopy.size() + 1 ,0); + QVector arguments(argsCopy.size() + 1 , 0); arguments[0] = 0; for (int i = 0; i < argsCopy.size(); ++i) arguments[i + 1] = &argsCopy[i]; @@ -183,7 +183,7 @@ bool DynamicQObject::executeSlot(const DynamicSlot& slot, void** args) QList arguments; for (int i = 0; i < slot.argumentsTypes().count(); ++i) - arguments << QVariant(slot.argumentTypeAt(i), args[i+1]); + arguments << QVariant(slot.argumentTypeAt(i), args[i + 1]); QVariant result = executeSlot(slot, arguments); @@ -205,7 +205,7 @@ QVariant DynamicQObject::executeSlot(const DynamicSlot& slot, const QList argumentsAsVoidPointers(numParametersPlusReturn); for (int i = 0; i < numParametersPlusReturn; ++i) { - argumentsAsVariants[i] = i == 0 ? QVariant() : args[i-1]; + argumentsAsVariants[i] = i == 0 ? QVariant() : args[i - 1]; argumentsAsVoidPointers[i] = &argumentsAsVariants[i]; } @@ -256,7 +256,7 @@ bool DynamicQObject::writeProperty(const DynamicProperty& property, void** args) if (writeSlot.returnType() != QMetaType::Void) return false; - QVariant newValue (writeSlot.argumentTypeAt(0), args[0]); + QVariant newValue(writeSlot.argumentTypeAt(0), args[0]); executeSlot(writeSlot, {newValue}); } @@ -297,9 +297,9 @@ int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** a } QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMetaObject, - const std::function& afterSignalAdded, - const std::function& afterSlotAdded, - const std::function& afterPropertyAdded) + const std::function& afterSignalAdded, + const std::function& afterSlotAdded, + const std::function& afterPropertyAdded) { // Collect the current methods and signals QList signalsList; @@ -326,7 +326,7 @@ QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMetaO metaObjectBuilder.setClassName(currentMetaObject->className()); metaObjectBuilder.setSuperClass(currentMetaObject->superClass()); - foreach(auto& method, signalsList) + foreach (auto& method, signalsList) metaObjectBuilder.addMethod(method); // Call custom code to be executed after signal have been added diff --git a/DOtherSide/DynamicQObject/DynamicQObject.h b/DOtherSide/DynamicQObject/DynamicQObject.h index 00bf636..ce826fd 100644 --- a/DOtherSide/DynamicQObject/DynamicQObject.h +++ b/DOtherSide/DynamicQObject/DynamicQObject.h @@ -12,7 +12,7 @@ class QMetaObjectBuilder; /// This class implements a QObject to which signals, slots and properties can be added dynamically class DynamicQObject : public QObject { - typedef void (*Callback)(void*, void*, int, void **); + typedef void (*Callback)(void*, void*, int, void**); public: /// Constructor @@ -22,10 +22,14 @@ public: virtual ~DynamicQObject(); /// Sets the function to be called from C++ to D or Nimrod - void setDObjectCallback(Callback callback) { m_dObjectCallback = callback; } + void setDObjectCallback(Callback callback) { + m_dObjectCallback = callback; + } /// Sets the D or Nimrod object that owns this DynamicQObject - void setDObjectPointer(void* dObjectPointer) { m_dObjectPointer = dObjectPointer; } + void setDObjectPointer(void* dObjectPointer) { + m_dObjectPointer = dObjectPointer; + } /// Register a new signal bool registerSignal(const QString& name, @@ -49,10 +53,10 @@ public: bool emitSignal(const QString& name, const QList& argumentsValues); /// 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 +71,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& afterSignalAdded, - const std::function& afterSlotAdded, - const std::function& afterPropertyAdded); + const std::function& afterSignalAdded, + const std::function& afterSlotAdded, + const std::function& afterPropertyAdded); QHash m_signalsByName; QHash m_signalsBySignature; diff --git a/DOtherSide/IntegrationTest/main.cpp b/DOtherSide/IntegrationTest/main.cpp index 11357ee..f0ac270 100644 --- a/DOtherSide/IntegrationTest/main.cpp +++ b/DOtherSide/IntegrationTest/main.cpp @@ -5,7 +5,7 @@ #include #include -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index b913566..935e693 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -6,6 +6,7 @@ import tables type Roles {.pure.} = enum Name = cint(0) + MyQAbstractListModel = ref object of QAbstractListModel m_roleNames: Table[int, cstring] m_names: seq[string] From b79d0bfb63b221313bef8b245bcd1caf9790927b Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 31 Jan 2015 17:55:14 +0100 Subject: [PATCH 44/58] Added the support for beginInsertRows and endInsertRows methods --- DOtherSide/DOtherSide/BaseQAbstractListModel.cpp | 10 ++++++++++ DOtherSide/DOtherSide/BaseQAbstractListModel.h | 6 ++++++ DOtherSide/DOtherSide/DOtherSide.cpp | 13 +++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 2 ++ Nim/Examples/AbstractItemModel/main.nim | 6 +++--- Nim/NimQml/NimQml.nim | 10 ++++++++++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 35e3fcd..c0bbc2a 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -41,3 +41,13 @@ QHash BaseQAbstractListModel::roleNames() const return result; } +void BaseQAbstractListModel::publicBeginInsertRows(const QModelIndex& index, int first, int last) +{ + beginInsertRows(index, first, last); +} + +void BaseQAbstractListModel::publicEndInsertRows() +{ + return endInsertRows(); +} + diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 84ffc1d..d2908c9 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -25,6 +25,12 @@ public: /// Return the roleNames virtual QHash roleNames() const override; + /// Expose beginInsertRows + void publicBeginInsertRows(const QModelIndex& index, int first, int last); + + /// Expose endInsertRows + void publicEndInsertRows(); + private: void* m_modelObject; RowCountCallback m_rowCountCallback; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index fdf54c9..a750c19 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -451,6 +451,19 @@ void dos_qabstractlistmodel_delete(void* vptr) delete model; } +void dos_qabstractlistmodel_beginInsertRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last) +{ + auto model = reinterpret_cast(vptr); + auto index = reinterpret_cast(parentIndex); + model->publicBeginInsertRows(*index, first, last); +} + +void dos_qabstractlistmodel_endInsertRows(void* vptr) +{ + auto model = reinterpret_cast(vptr); + model->publicEndInsertRows(); +} + void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr) { *vptr = new QHash(); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 204becc..71cb3d6 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -125,6 +125,8 @@ void dos_qabstractlistmodel_create(void** vptr, RowCountCallback rowCountCallback, DataCallback dataCallback, RoleNamesCallback roleNamesCallback); +void dos_qabstractlistmodel_beginInsertRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last); +void dos_qabstractlistmodel_endInsertRows(void* vptr); void dos_qabstractlistmodel_delete(void* vptr); #ifdef __cplusplus diff --git a/Nim/Examples/AbstractItemModel/main.nim b/Nim/Examples/AbstractItemModel/main.nim index 935e693..7be20f0 100644 --- a/Nim/Examples/AbstractItemModel/main.nim +++ b/Nim/Examples/AbstractItemModel/main.nim @@ -31,12 +31,12 @@ method rowCount(self: MyQAbstractListModel, index: QModelIndex): cint = method data(self: MyQAbstractListModel, index: QModelIndex, role: cint): QVariant = if not index.isValid: - return + return if index.row < 0 or index.row >= self.m_names.len: - return + return if role == Roles.Name.cint: return newQVariant(self.m_names[index.row]) - + method roleNames(self: MyQAbstractListModel): Table[int, cstring] = return self.m_roleNames diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 25b1042..b7ecce8 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -640,6 +640,11 @@ proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, dataCallback: DataCallback, roleNamesCallback: RoleNamesCallback) {.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.} method rowCount*(model: QAbstractListModel, index: QModelIndex): cint = ## Return the model's row count @@ -691,3 +696,8 @@ proc newQAbstractListModel*(): QAbstractListModel = newWithCondFinalizer(result, delete) result.create() +proc beginInsertRows(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = + dos_qabstractlistmodel_beginInsertRows(model.data, parentIndex.data, first.cint, last.cint) + +proc endInsertRows(model: QAbstractListModel) = + dos_qabstractlistmodel_endInsertRows(model.data) From 1e9d5babe052a02926c127969296856f76739bf2 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 1 Feb 2015 12:50:31 +0100 Subject: [PATCH 45/58] Added support for beginResetModel, endResetModel and dataChanged --- .../DOtherSide/BaseQAbstractListModel.cpp | 19 ++++++++++++++ .../DOtherSide/BaseQAbstractListModel.h | 11 ++++++++ DOtherSide/DOtherSide/DOtherSide.cpp | 25 +++++++++++++++++++ DOtherSide/DOtherSide/DOtherSide.h | 13 +++++++++- Nim/NimQml/NimQml.nim | 25 +++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index c0bbc2a..83f40a4 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -51,3 +51,22 @@ void BaseQAbstractListModel::publicEndInsertRows() return endInsertRows(); } +void BaseQAbstractListModel::publicBeginResetModel() +{ + beginResetModel(); +} + +void BaseQAbstractListModel::publicEndResetModel() +{ + endResetModel(); +} + +void BaseQAbstractListModel::publicDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + emit dataChanged(topLeft, bottomRight, roles); +} + + + diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index d2908c9..3eba6a2 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -31,6 +31,17 @@ public: /// Expose endInsertRows void publicEndInsertRows(); + /// Expose beginResetModel + void publicBeginResetModel(); + + /// Expose endResetModel + void publicEndResetModel(); + + /// Expose dataChanged + void publicDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); + private: void* m_modelObject; RowCountCallback m_rowCountCallback; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index a750c19..d1e0530 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -464,6 +464,31 @@ void dos_qabstractlistmodel_endInsertRows(void* vptr) model->publicEndInsertRows(); } +void dos_qabstractlistmodel_beginResetModel(void* vptr) +{ + auto model = reinterpret_cast(vptr); + model->publicBeginResetModel(); +} + +void dos_qabstractlistmodel_endResetModel(void* vptr) +{ + auto model = reinterpret_cast(vptr); + model->publicEndResetModel(); +} + +void dos_qabstractlistmodel_dataChanged(void* vptr, + QModelIndexVoidPtr topLeftIndex, + QModelIndexVoidPtr bottomRightIndex, + int* rolesArrayPtr, + int rolesArrayLength) +{ + auto model = reinterpret_cast(vptr); + auto topLeft = reinterpret_cast(topLeftIndex); + auto bottomRight = reinterpret_cast(bottomRightIndex); + auto roles = QVector::fromStdVector(std::vector(rolesArrayPtr, rolesArrayPtr + rolesArrayLength)); + model->publicDataChanged(*topLeft, *bottomRight, roles); +} + void dos_qhash_int_qbytearray_create(QHashIntQByteArrayVoidPtr* vptr) { *vptr = new QHash(); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 71cb3d6..4bc9ec1 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -125,8 +125,19 @@ void dos_qabstractlistmodel_create(void** vptr, RowCountCallback rowCountCallback, DataCallback dataCallback, RoleNamesCallback roleNamesCallback); -void dos_qabstractlistmodel_beginInsertRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last); +void dos_qabstractlistmodel_beginInsertRows(void* vptr, + QModelIndexVoidPtr parentIndex, + int first, + int last); void dos_qabstractlistmodel_endInsertRows(void* vptr); +void dos_qabstractlistmodel_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 diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index b7ecce8..c548bd1 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -645,6 +645,13 @@ proc dos_qabstractlistmodel_beginInsertRows(model: RawQAbstractListModel, first: cint, last: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_endInsertRows(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 @@ -697,7 +704,25 @@ proc newQAbstractListModel*(): QAbstractListModel = 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, parentIndex.data, first.cint, last.cint) proc endInsertRows(model: QAbstractListModel) = + ## Notify the view that the rows have been inserted dos_qabstractlistmodel_endInsertRows(model.data) + +proc beginResetModel(model: QAbstractListModel) = + ## Notify the view that the model is about to resetting + dos_qabstractlistmodel_beginResetModel(model.data) + +proc endResetModel(model: QAbstractListModel) = + ## Notify the view that model has finished resetting + dos_qabstractlistmodel_endResetModel(model.data) + +proc dataChanged(model: QAbstractListModel, + topLeft: QModelIndex, + bottomRight: QModelIndex, + roles: seq[cint]) = + ## Notify the view that the model data changed + var temp = roles + dos_qabstractlistmodel_dataChanged(model.data, topLeft.data, bottomRight.data, temp[0].addr, temp.len.cint) From e6e67e07b456d091a8f499e5a6db71dea06e79e1 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Wed, 4 Feb 2015 23:02:26 +0100 Subject: [PATCH 46/58] Initial version --- DOtherSide/CMakeLists.txt | 4 +- .../DOtherSide/BaseQAbstractListModel.cpp | 82 ---- .../DOtherSide/BaseQAbstractListModel.h | 104 ++++- DOtherSide/DOtherSide/BaseQObject.h | 8 + DOtherSide/DOtherSide/CMakeLists.txt | 5 +- DOtherSide/DOtherSide/DOtherSide.cpp | 20 +- DOtherSide/DOtherSide/DOtherSide.h | 18 +- DOtherSide/DynamicQObject/CMakeLists.txt | 1 - DOtherSide/DynamicQObject/DynamicProperty.cpp | 113 ----- DOtherSide/DynamicQObject/DynamicProperty.h | 118 ++++- DOtherSide/DynamicQObject/DynamicQObject.cpp | 347 --------------- DOtherSide/DynamicQObject/DynamicQObject.h | 405 +++++++++++++++++- DOtherSide/DynamicQObject/DynamicSignal.cpp | 90 ---- DOtherSide/DynamicQObject/DynamicSignal.h | 100 ++++- DOtherSide/DynamicQObject/DynamicSlot.cpp | 109 ----- DOtherSide/DynamicQObject/DynamicSlot.h | 113 ++++- DOtherSide/DynamicQObject/IDynamicQObject.h | 40 ++ .../DynamicQObject/private/qmetaobject_p.h | 100 ++--- .../private/qmetaobjectbuilder_p.h | 60 +-- DOtherSide/DynamicQObject/private/qobject_p.h | 273 ++++++------ 20 files changed, 1109 insertions(+), 1001 deletions(-) delete mode 100644 DOtherSide/DOtherSide/BaseQAbstractListModel.cpp create mode 100644 DOtherSide/DOtherSide/BaseQObject.h delete mode 100644 DOtherSide/DynamicQObject/DynamicProperty.cpp delete mode 100644 DOtherSide/DynamicQObject/DynamicQObject.cpp delete mode 100644 DOtherSide/DynamicQObject/DynamicSignal.cpp delete mode 100644 DOtherSide/DynamicQObject/DynamicSlot.cpp create mode 100644 DOtherSide/DynamicQObject/IDynamicQObject.h diff --git a/DOtherSide/CMakeLists.txt b/DOtherSide/CMakeLists.txt index 9c43bb6..012e557 100644 --- a/DOtherSide/CMakeLists.txt +++ b/DOtherSide/CMakeLists.txt @@ -1,3 +1,3 @@ add_subdirectory(DOtherSide) -add_subdirectory(DynamicQObject) -add_subdirectory(IntegrationTest) \ No newline at end of file +#add_subdirectory(DynamicQObject) +#add_subdirectory(IntegrationTest) \ No newline at end of file diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp deleted file mode 100644 index d794c0e..0000000 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "BaseQAbstractListModel.h" - -BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, - RowCountCallback rowCountCallback, - DataCallback dataCallback, - RoleNamesCallback roleNamesCallback) - : m_modelObject(modelObject) - , m_rowCountCallback(rowCountCallback) - , m_dataCallback(dataCallback) - , m_roleNamesCallback(roleNamesCallback) -{ -} - -int BaseQAbstractListModel::rowCount(const QModelIndex& index) const -{ - auto newIndex = new QModelIndex(); - *newIndex = index; - int result; - m_rowCountCallback(m_modelObject, newIndex, &result); - return result; -} - -QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const -{ - auto newIndex = new QModelIndex(); - *newIndex = index; - QVariant result; - m_dataCallback(m_modelObject, newIndex, role, &result); - return result; -} - -void* BaseQAbstractListModel::modelObject() -{ - return m_modelObject; -} - -QHash BaseQAbstractListModel::roleNames() const -{ - QHash 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& roles) -{ - emit dataChanged(topLeft, bottomRight, roles); -} - - - diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index a812ee7..cf40dc2 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -1,10 +1,12 @@ -#pragma once +#ifndef BASEQABSTRACTLISTMODEL_H +#define BASEQABSTRACTLISTMODEL_H #include "DOtherSideTypes.h" +#include "DynamicQObject.h" #include /// This class act as a base class for D and Nim QAbstractListModel -class BaseQAbstractListModel : public QAbstractListModel +class BaseQAbstractListModel : public DynamicQObject { public: /// Constructor @@ -27,30 +29,110 @@ public: /// Expose beginInsertRows void publicBeginInsertRows(const QModelIndex& index, int first, int last); - + /// Expose endInsertRows void publicEndInsertRows(); - + /// Expose beginRemoveRows void publicBeginRemoveRows(const QModelIndex& index, int first, int last); - + /// Expose endInsertRows void publicEndRemoveRows(); - + /// Expose beginResetModel void publicBeginResetModel(); - + /// Expose endResetModel void publicEndResetModel(); - + /// Expose dataChanged - void publicDataChanged(const QModelIndex& topLeft, - const QModelIndex& bottomRight, + void publicDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, const QVector& roles = QVector()); - + private: void* m_modelObject; RowCountCallback m_rowCountCallback; DataCallback m_dataCallback; RoleNamesCallback m_roleNamesCallback; }; + +BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, + RowCountCallback rowCountCallback, + DataCallback dataCallback, + RoleNamesCallback roleNamesCallback) + : m_modelObject(modelObject) + , m_rowCountCallback(rowCountCallback) + , m_dataCallback(dataCallback) + , m_roleNamesCallback(roleNamesCallback) +{ +} + +int BaseQAbstractListModel::rowCount(const QModelIndex& index) const +{ + auto newIndex = new QModelIndex(); + *newIndex = index; + int result; + m_rowCountCallback(m_modelObject, newIndex, &result); + return result; +} + +QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const +{ + auto newIndex = new QModelIndex(); + *newIndex = index; + QVariant result; + m_dataCallback(m_modelObject, newIndex, role, &result); + return result; +} + +void* BaseQAbstractListModel::modelObject() +{ + return m_modelObject; +} + +QHash BaseQAbstractListModel::roleNames() const +{ + QHash 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& roles) +{ + emit dataChanged(topLeft, bottomRight, roles); +} + +#endif diff --git a/DOtherSide/DOtherSide/BaseQObject.h b/DOtherSide/DOtherSide/BaseQObject.h new file mode 100644 index 0000000..6341610 --- /dev/null +++ b/DOtherSide/DOtherSide/BaseQObject.h @@ -0,0 +1,8 @@ +#ifndef BASEQOBJECT_H +#define BASEQOBJECT_H + +#include "DynamicQObject.h" + +class BaseQObject : public DynamicQObject {}; + +#endif diff --git a/DOtherSide/DOtherSide/CMakeLists.txt b/DOtherSide/DOtherSide/CMakeLists.txt index 132dbbc..7efc71c 100644 --- a/DOtherSide/DOtherSide/CMakeLists.txt +++ b/DOtherSide/DOtherSide/CMakeLists.txt @@ -12,14 +12,15 @@ find_package(Qt5Widgets) set(HEADERS_LIST DOtherSide.h + DOtherSideTypes.h BaseQAbstractListModel.h + BaseQObject.h ) set(SRC_LIST DOtherSide.cpp - BaseQAbstractListModel.cpp ) add_library(${PROJECT_NAME} SHARED ${SRC_LIST} ${HEADERS_LIST}) -target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick DynamicQObject) +target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../DynamicQObject) \ No newline at end of file diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index aeec3f8..2aa84a6 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -1,5 +1,7 @@ #include "DOtherSide.h" +#include + #include #include #include @@ -8,10 +10,10 @@ #include #include #include -#include #include "DynamicQObject.h" #include "BaseQAbstractListModel.h" +#include "BaseQObject.h" void convert_to_cstring(const QString& source, char** destination, int* length) { @@ -307,7 +309,7 @@ void dos_qvariant_setQAbstractListModel(void* vptr, void* value) void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback) { - auto dynamicQObject = new DynamicQObject(); + auto dynamicQObject = new DynamicQObject(); QQmlEngine::setObjectOwnership(dynamicQObject, QQmlEngine::CppOwnership); dynamicQObject->setDObjectPointer(dObjectPointer); dynamicQObject->setDObjectCallback(dObjectCallback); @@ -316,7 +318,7 @@ void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObje void dos_qobject_delete(void* vptr) { - auto dynamicQObject = reinterpret_cast(vptr); + auto dynamicQObject = reinterpret_cast*>(vptr); dynamicQObject->disconnect(); delete dynamicQObject; } @@ -326,7 +328,7 @@ void dos_qobject_slot_create(void* vptr, const char* name, int parametersCount, if (parametersCount <= 0) return; - auto dynamicQObject = reinterpret_cast(vptr); + auto dynamicQObject = reinterpret_cast*>(vptr); QMetaType::Type returnType = static_cast(parametersMetaTypes[0]); QList argumentsTypes; @@ -341,7 +343,7 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount if (parametersCount <= 0) return; - auto dynamicQObject = reinterpret_cast(vptr); + auto dynamicQObject = reinterpret_cast*>(vptr); QList argumentsTypes; for (int i = 0; i < parametersCount; ++i) @@ -352,7 +354,7 @@ 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(vptr); + auto dynamicQObject = reinterpret_cast*>(vptr); QVariantList arguments; for (int i = 0; i < parametersCount; ++i) arguments << *(reinterpret_cast(parameters[i])); @@ -366,7 +368,7 @@ void dos_qobject_property_create(void* vptr, const char* writeSlot, const char* notifySignal) { - auto dynamicQObject = reinterpret_cast(vptr); + auto dynamicQObject = reinterpret_cast*>(vptr); dynamicQObject->registerProperty(QString(name), QMetaType::Type(type), QString(readSlot), @@ -489,8 +491,8 @@ void dos_qabstractlistmodel_endResetModel(void* vptr) model->publicEndResetModel(); } -void dos_qabstractlistmodel_dataChanged(void* vptr, - QModelIndexVoidPtr topLeftIndex, +void dos_qabstractlistmodel_dataChanged(void* vptr, + QModelIndexVoidPtr topLeftIndex, QModelIndexVoidPtr bottomRightIndex, int* rolesArrayPtr, int rolesArrayLength) diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 7c87400..38f2fbe 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -125,19 +125,19 @@ void dos_qabstractlistmodel_create(void** vptr, RowCountCallback rowCountCallback, DataCallback dataCallback, RoleNamesCallback roleNamesCallback); -void dos_qabstractlistmodel_beginInsertRows(void* vptr, - QModelIndexVoidPtr parentIndex, - int first, - int last); +void dos_qabstractlistmodel_beginInsertRows(void* vptr, + QModelIndexVoidPtr parentIndex, + int first, + int last); void dos_qabstractlistmodel_endInsertRows(void* vptr); -void dos_qabstractlistmodel_beginRemoveRows(void* vptr, - QModelIndexVoidPtr parentIndex, - int first, - int last); +void dos_qabstractlistmodel_beginRemoveRows(void* vptr, + QModelIndexVoidPtr parentIndex, + int first, + int last); void dos_qabstractlistmodel_endRemoveRows(void* vptr); void dos_qabstractlistmodel_beginResetModel(void* vptr); void dos_qabstractlistmodel_endResetModel(void* vptr); -void dos_qabstractlistmodel_dataChanged(void* vptr, +void dos_qabstractlistmodel_dataChanged(void* vptr, QModelIndexVoidPtr topLeftIndex, QModelIndexVoidPtr bottomRightIndex, int* rolesArrayPtr, diff --git a/DOtherSide/DynamicQObject/CMakeLists.txt b/DOtherSide/DynamicQObject/CMakeLists.txt index 5dfc420..8a996d9 100644 --- a/DOtherSide/DynamicQObject/CMakeLists.txt +++ b/DOtherSide/DynamicQObject/CMakeLists.txt @@ -15,7 +15,6 @@ set(HEADERS_LIST set(SRC_LIST DynamicProperty.cpp - DynamicQObject.cpp DynamicSignal.cpp DynamicSlot.cpp ) diff --git a/DOtherSide/DynamicQObject/DynamicProperty.cpp b/DOtherSide/DynamicQObject/DynamicProperty.cpp deleted file mode 100644 index 7a5aa0d..0000000 --- a/DOtherSide/DynamicQObject/DynamicProperty.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "DynamicProperty.h" -#include - -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; -} - diff --git a/DOtherSide/DynamicQObject/DynamicProperty.h b/DOtherSide/DynamicQObject/DynamicProperty.h index d77c09f..b3b3dd0 100644 --- a/DOtherSide/DynamicQObject/DynamicProperty.h +++ b/DOtherSide/DynamicQObject/DynamicProperty.h @@ -1,10 +1,10 @@ -#pragma once +#ifndef DYNAMICPROPERTY_H +#define DYNAMICPROPERTY_H +#include #include #include -#include -class QString; class PropertyData; class DynamicProperty @@ -38,3 +38,115 @@ public: private: std::unique_ptr 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 \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/DynamicQObject.cpp b/DOtherSide/DynamicQObject/DynamicQObject.cpp deleted file mode 100644 index ff8017f..0000000 --- a/DOtherSide/DynamicQObject/DynamicQObject.cpp +++ /dev/null @@ -1,347 +0,0 @@ -#include "DynamicQObject.h" -#include -#include -#include -#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& 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& 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& 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 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 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& args) -{ - QVariant slotName(slot.name()); - - const int numParametersPlusReturn = slot.argumentsTypes().count() + 1; - std::vector argumentsAsVariants(numParametersPlusReturn); - std::vector 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& afterSignalAdded, - const std::function& afterSlotAdded, - const std::function& afterPropertyAdded) -{ - // Collect the current methods and signals - QList signalsList; - QList methodsList; - QList 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(); -} diff --git a/DOtherSide/DynamicQObject/DynamicQObject.h b/DOtherSide/DynamicQObject/DynamicQObject.h index ce826fd..5394f06 100644 --- a/DOtherSide/DynamicQObject/DynamicQObject.h +++ b/DOtherSide/DynamicQObject/DynamicQObject.h @@ -1,16 +1,21 @@ -#pragma once +#ifndef DYNAMICQOBJECT_H +#define DYNAMICQOBJECT_H -#include -#include +#include +#include +#include +#include +#include +#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 DynamicQObject : public T { typedef void (*Callback)(void*, void*, int, void**); @@ -22,35 +27,35 @@ public: virtual ~DynamicQObject(); /// Sets the function to be called from C++ to D or Nimrod - void setDObjectCallback(Callback callback) { + virtual void setDObjectCallback(Callback callback) { m_dObjectCallback = callback; } /// Sets the D or Nimrod object that owns this DynamicQObject - void setDObjectPointer(void* dObjectPointer) { + virtual void setDObjectPointer(void* dObjectPointer) { m_dObjectPointer = dObjectPointer; } /// Register a new signal - bool registerSignal(const QString& name, - const QList& argumentsTypes, - int& signalIndex); + virtual bool registerSignal(const QString& name, + const QList& argumentsTypes, + int& signalIndex); /// Register a new slot - bool registerSlot(const QString& name, - const QMetaType::Type returnType, - const QList& argumentsTypes, - int& slotIndex); + virtual bool registerSlot(const QString& name, + const QMetaType::Type returnType, + const QList& argumentsTypes, + int& slotIndex); /// 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 = ""); /// Emit the signal with the given name and arguments - bool emitSignal(const QString& name, const QList& argumentsValues); + virtual bool emitSignal(const QString& name, const QList& argumentsValues); /// Return the QMetaObject for this DynamicQObject virtual const QMetaObject* metaObject() const; @@ -84,3 +89,361 @@ private: void* m_dObjectPointer; Callback m_dObjectCallback; }; + +template +DynamicQObject::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 +DynamicQObject::~DynamicQObject() = default; + +template +bool DynamicQObject::registerSlot(const QString& name, + const QMetaType::Type returnType, + const QList& 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 +bool DynamicQObject::registerSignal(const QString& name, const QList& 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 +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; +} + +template +bool DynamicQObject::emitSignal(const QString& name, const QList& 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 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 +const QMetaObject* DynamicQObject::metaObject() const +{ + return m_metaObject.data(); +} + +template +bool DynamicQObject::executeSlot(const DynamicSlot& slot, void** args) +{ + if (!slot.isValid()) + return false; + + QList 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 +QVariant DynamicQObject::executeSlot(const DynamicSlot& slot, const QList& args) +{ + QVariant slotName(slot.name()); + + const int numParametersPlusReturn = slot.argumentsTypes().count() + 1; + std::vector argumentsAsVariants(numParametersPlusReturn); + std::vector 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 +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); +} + +template +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}); +} + +template +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; +} + +template +QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMetaObject, + const std::function& afterSignalAdded, + const std::function& afterSlotAdded, + const std::function& afterPropertyAdded) +{ + // Collect the current methods and signals + QList signalsList; + QList methodsList; + QList 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(); +} + +#endif \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/DynamicSignal.cpp b/DOtherSide/DynamicQObject/DynamicSignal.cpp deleted file mode 100644 index 34ad6bf..0000000 --- a/DOtherSide/DynamicQObject/DynamicSignal.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "DynamicSignal.h" -#include "DynamicQObject.h" - -struct SignalData -{ - QString name; - QList argumentsTypes; - QByteArray signature; -}; - -DynamicSignal::DynamicSignal() - : d(nullptr) -{ -} - -DynamicSignal::DynamicSignal(const QString& name, const QList& 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& 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(); -} diff --git a/DOtherSide/DynamicQObject/DynamicSignal.h b/DOtherSide/DynamicQObject/DynamicSignal.h index 3396489..58faaee 100644 --- a/DOtherSide/DynamicQObject/DynamicSignal.h +++ b/DOtherSide/DynamicQObject/DynamicSignal.h @@ -1,10 +1,14 @@ -#pragma once +#ifndef DYNAMICSIGNAL_H +#define DYNAMICSIGNAL_H -#include #include +#include +#include +#include +#include + class SignalData; -class DynamicQObject; class DynamicSignal { @@ -28,3 +32,93 @@ private: std::unique_ptr d; }; + +struct SignalData +{ + QString name; + QList argumentsTypes; + QByteArray signature; +}; + +DynamicSignal::DynamicSignal() + : d(nullptr) +{ +} + +DynamicSignal::DynamicSignal(const QString& name, const QList& 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& 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 \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/DynamicSlot.cpp b/DOtherSide/DynamicQObject/DynamicSlot.cpp deleted file mode 100644 index 320bc10..0000000 --- a/DOtherSide/DynamicQObject/DynamicSlot.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "DynamicSlot.h" -#include -#include -#include -#include -#include -#include "private/qmetaobjectbuilder_p.h" - -struct SlotData -{ - QString name; - QMetaType::Type returnType; - QList argumentsTypes; - QByteArray signature; -}; - -DynamicSlot::DynamicSlot() - : d(nullptr) -{ - -} - -DynamicSlot::DynamicSlot(const QString& name, - QMetaType::Type returnType, - const QList& 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 DynamicSlot::argumentsTypes() const -{ - return isValid() ? d->argumentsTypes : QList(); -} - -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(); -} diff --git a/DOtherSide/DynamicQObject/DynamicSlot.h b/DOtherSide/DynamicQObject/DynamicSlot.h index 187ea2c..5c45cf6 100644 --- a/DOtherSide/DynamicQObject/DynamicSlot.h +++ b/DOtherSide/DynamicQObject/DynamicSlot.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef DYNAMICSLOT_H +#define DYNAMICSLOT_H #include #include @@ -6,6 +7,12 @@ #include #include #include +#include +#include +#include +#include + +#include "private/qmetaobjectbuilder_p.h" class SlotData; class QString; @@ -34,3 +41,107 @@ private: std::unique_ptr d; }; + +struct SlotData +{ + QString name; + QMetaType::Type returnType; + QList argumentsTypes; + QByteArray signature; +}; + +DynamicSlot::DynamicSlot() + : d(nullptr) +{ + +} + +DynamicSlot::DynamicSlot(const QString& name, + QMetaType::Type returnType, + const QList& 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 DynamicSlot::argumentsTypes() const +{ + return isValid() ? d->argumentsTypes : QList(); +} + +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 \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/IDynamicQObject.h b/DOtherSide/DynamicQObject/IDynamicQObject.h new file mode 100644 index 0000000..e7abc48 --- /dev/null +++ b/DOtherSide/DynamicQObject/IDynamicQObject.h @@ -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& argumentsTypes, + int& signalIndex) = 0; + + /// Register a new slot + virtual bool registerSlot(const QString& name, + const QMetaType::Type returnType, + const QList& 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& argumentsValues) = 0; +}; + +#endif \ No newline at end of file diff --git a/DOtherSide/DynamicQObject/private/qmetaobject_p.h b/DOtherSide/DynamicQObject/private/qmetaobject_p.h index ef66927..b3c04d5 100644 --- a/DOtherSide/DynamicQObject/private/qmetaobject_p.h +++ b/DOtherSide/DynamicQObject/private/qmetaobject_p.h @@ -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(this)->_name = QMetaType::typeName(_type); + const_cast(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(metaobject->d.data); } + static inline const QMetaObjectPrivate* get(const QMetaObject* metaobject) + { + return reinterpret_cast(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 parameterTypeNamesFromSignature(const char *signature); + static QList 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) diff --git a/DOtherSide/DynamicQObject/private/qmetaobjectbuilder_p.h b/DOtherSide/DynamicQObject/private/qmetaobjectbuilder_p.h index 3a1b43c..ed76f53 100644 --- a/DOtherSide/DynamicQObject/private/qmetaobjectbuilder_p.h +++ b/DOtherSide/DynamicQObject/private/qmetaobjectbuilder_p.h @@ -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& references); + (QDataStream& stream, + const QMap& 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 Entries; // string --> index mapping diff --git a/DOtherSide/DynamicQObject/private/qobject_p.h b/DOtherSide/DynamicQObject/private/qobject_p.h index 180887b..1236a21 100644 --- a/DOtherSide/DynamicQObject/private/qobject_p.h +++ b/DOtherSide/DynamicQObject/private/qobject_p.h @@ -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 userData; - #endif +#ifndef QT_NO_USERDATA + QVector userData; +#endif QList propertyNames; QList propertyValues; QVector 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 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 - static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, - const typename QtPrivate::FunctionPointer::Object *receiverPrivate, Func2 slot, - Qt::ConnectionType type = Qt::AutoConnection); + static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer::Object* sender, Func1 signal, + const typename QtPrivate::FunctionPointer::Object* receiverPrivate, Func2 slot, + Qt::ConnectionType type = Qt::AutoConnection); template - static inline bool disconnect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, - const typename QtPrivate::FunctionPointer::Object *receiverPrivate, Func2 slot); + static inline bool disconnect(const typename QtPrivate::FunctionPointer::Object* sender, Func1 signal, + const typename QtPrivate::FunctionPointer::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 class QPrivateSlotObject : public QSlotObjectBase -{ - typedef QtPrivate::FunctionPointer FuncType; - Func function; - static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) + template class QPrivateSlotObject : public QSlotObjectBase { - switch (which) { + typedef QtPrivate::FunctionPointer FuncType; + Func function; + static void impl(int which, QSlotObjectBase* this_, QObject* r, void** a, bool* ret) + { + switch (which) { case Destroy: delete static_cast(this_); break; case Call: FuncType::template call(static_cast(this_)->function, - static_cast(QObjectPrivate::get(r)), a); + static_cast(QObjectPrivate::get(r)), a); break; case Compare: - *ret = *reinterpret_cast(a) == static_cast(this_)->function; + *ret = *reinterpret_cast(a) == static_cast(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 -inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, - const typename QtPrivate::FunctionPointer::Object *receiverPrivate, Func2 slot, - Qt::ConnectionType type) +inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer::Object* sender, Func1 signal, + const typename QtPrivate::FunctionPointer::Object* receiverPrivate, Func2 slot, + Qt::ConnectionType type) { typedef QtPrivate::FunctionPointer SignalType; typedef QtPrivate::FunctionPointer SlotType; @@ -333,15 +340,15 @@ inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate: Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible::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::types(); - return QObject::connectImpl(sender, reinterpret_cast(&signal), - receiverPrivate->q_ptr, reinterpret_cast(&slot), - new QtPrivate::QPrivateSlotObject::Value, - typename SignalType::ReturnType>(slot), - type, types, &SignalType::Object::staticMetaObject); + return QObject::connectImpl(sender, reinterpret_cast(&signal), + receiverPrivate->q_ptr, reinterpret_cast(&slot), + new QtPrivate::QPrivateSlotObject::Value, + typename SignalType::ReturnType>(slot), + type, types, &SignalType::Object::staticMetaObject); } template @@ -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::value), "Signal and slot arguments are not compatible."); - return QObject::disconnectImpl(sender, reinterpret_cast(&signal), - receiverPrivate->q_ptr, reinterpret_cast(&slot), - &SignalType::Object::staticMetaObject); + return QObject::disconnectImpl(sender, reinterpret_cast(&signal), + receiverPrivate->q_ptr, reinterpret_cast(&slot), + &SignalType::Object::staticMetaObject); } Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); @@ -367,31 +374,39 @@ class QSemaphore; class Q_CORE_EXPORT QMetaCallEvent : public QEvent { public: - QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId, - int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0); + QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject* sender, int signalId, + int nargs = 0, int* types = 0, void** args = 0, QSemaphore* semaphore = 0); /*! \internal \a signalId is in the signal index range (see QObjectPrivate::signalIndex()). */ - QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, - int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0); + QMetaCallEvent(QtPrivate::QSlotObjectBase* slotObj, const QObject* sender, int signalId, + int nargs = 0, int* types = 0, void** args = 0, QSemaphore* semaphore = 0); ~QMetaCallEvent(); - inline int id() const { return method_offset_ + method_relative_; } - inline const QObject *sender() const { return sender_; } - inline int signalId() const { return signalId_; } - inline void **args() const { return args_; } + inline int id() const { + return method_offset_ + method_relative_; + } + inline const QObject* sender() const { + return sender_; + } + inline int signalId() const { + return signalId_; + } + inline void** args() const { + return args_; + } - virtual void placeMetaCall(QObject *object); + virtual void placeMetaCall(QObject* object); private: - QtPrivate::QSlotObjectBase *slotObj_; - const QObject *sender_; + QtPrivate::QSlotObjectBase* slotObj_; + const QObject* sender_; int signalId_; int nargs_; - int *types_; - void **args_; - QSemaphore *semaphore_; + int* types_; + void** args_; + QSemaphore* semaphore_; QObjectPrivate::StaticMetaCallFunction callFunction_; ushort method_offset_; ushort method_relative_; @@ -401,32 +416,46 @@ class QBoolBlocker { Q_DISABLE_COPY(QBoolBlocker) public: - explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;} - inline ~QBoolBlocker(){block = reset; } + explicit inline QBoolBlocker(bool& b, bool value = true): block(b), reset(b) { + block = value; + } + inline ~QBoolBlocker() { + block = reset; + } private: - bool █ + bool& block; bool reset; }; -void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); +void Q_CORE_EXPORT qDeleteInEventHandler(QObject* o); struct QAbstractDynamicMetaObject; struct Q_CORE_EXPORT QDynamicMetaObjectData { virtual ~QDynamicMetaObjectData() {} - virtual void objectDestroyed(QObject *) { delete this; } + virtual void objectDestroyed(QObject*) { + delete this; + } - virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0; - virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0; + virtual QAbstractDynamicMetaObject* toDynamicMetaObject(QObject*) = 0; + virtual int metaCall(QObject*, QMetaObject::Call, int _id, void**) = 0; }; struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject { - virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) { return this; } - virtual int createProperty(const char *, const char *) { return -1; } - virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) - { return metaCall(c, _id, a); } - virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload + virtual QAbstractDynamicMetaObject* toDynamicMetaObject(QObject*) { + return this; + } + virtual int createProperty(const char*, const char*) { + return -1; + } + virtual int metaCall(QObject*, QMetaObject::Call c, int _id, void** a) + { + return metaCall(c, _id, a); + } + virtual int metaCall(QMetaObject::Call, int _id, void**) { + return _id; // Compat overload + } }; QT_END_NAMESPACE From fd0fba3fa4b0e48b567c396174d2df97f6fa48a9 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 2 Feb 2015 21:59:29 +0100 Subject: [PATCH 47/58] Added support for Added support for beginRemoveRows and endRemoveRows --- .../DOtherSide/BaseQAbstractListModel.cpp | 10 +++++++ .../DOtherSide/BaseQAbstractListModel.h | 6 +++++ DOtherSide/DOtherSide/DOtherSide.cpp | 13 +++++++++ DOtherSide/DOtherSide/DOtherSide.h | 5 ++++ Nim/NimQml/NimQml.nim | 27 ++++++++++++++----- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp index 83f40a4..d794c0e 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.cpp @@ -51,6 +51,16 @@ 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(); diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 3eba6a2..a812ee7 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -31,6 +31,12 @@ public: /// Expose endInsertRows void publicEndInsertRows(); + /// Expose beginRemoveRows + void publicBeginRemoveRows(const QModelIndex& index, int first, int last); + + /// Expose endInsertRows + void publicEndRemoveRows(); + /// Expose beginResetModel void publicBeginResetModel(); diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index d1e0530..aeec3f8 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -464,6 +464,19 @@ void dos_qabstractlistmodel_endInsertRows(void* vptr) model->publicEndInsertRows(); } +void dos_qabstractlistmodel_beginRemoveRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, int last) +{ + auto model = reinterpret_cast(vptr); + auto index = reinterpret_cast(parentIndex); + model->publicBeginRemoveRows(*index, first, last); +} + +void dos_qabstractlistmodel_endRemoveRows(void* vptr) +{ + auto model = reinterpret_cast(vptr); + model->publicEndRemoveRows(); +} + void dos_qabstractlistmodel_beginResetModel(void* vptr) { auto model = reinterpret_cast(vptr); diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 4bc9ec1..7c87400 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -130,6 +130,11 @@ void dos_qabstractlistmodel_beginInsertRows(void* vptr, 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, diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index c548bd1..9e23e24 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -645,6 +645,11 @@ proc dos_qabstractlistmodel_beginInsertRows(model: RawQAbstractListModel, 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, @@ -674,8 +679,8 @@ proc dataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelInd dos_qvariant_assign(result, variant.data) variant.delete -method roleNames*(model: QAbstractListModel): Table[int, cstring] = - discard() +method roleNames*(model: QAbstractListModel): Table[cint, cstring] = + result = initTable[cint, cstring]() proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashIntByteArray) {.cdecl, exportc.} = let model = cast[QAbstractListModel](modelObject) @@ -703,23 +708,31 @@ proc newQAbstractListModel*(): QAbstractListModel = newWithCondFinalizer(result, delete) result.create() -proc beginInsertRows(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = +proc beginInsertRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = ## Notify the view that the model is about to inserting the given number of rows dos_qabstractlistmodel_beginInsertRows(model.data, parentIndex.data, first.cint, last.cint) -proc endInsertRows(model: QAbstractListModel) = +proc endInsertRows*(model: QAbstractListModel) = ## Notify the view that the rows have been inserted dos_qabstractlistmodel_endInsertRows(model.data) -proc beginResetModel(model: QAbstractListModel) = +proc beginRemoveRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = + ## Notify the view that the model is about to remove the given number of rows + dos_qabstractlistmodel_beginRemoveRows(model.data, parentIndex.data, first.cint, last.cint) + +proc endRemoveRows*(model: QAbstractListModel) = + ## Notify the view that the rows have been removed + dos_qabstractlistmodel_endRemoveRows(model.data) + +proc beginResetModel*(model: QAbstractListModel) = ## Notify the view that the model is about to resetting dos_qabstractlistmodel_beginResetModel(model.data) -proc endResetModel(model: QAbstractListModel) = +proc endResetModel*(model: QAbstractListModel) = ## Notify the view that model has finished resetting dos_qabstractlistmodel_endResetModel(model.data) -proc dataChanged(model: QAbstractListModel, +proc dataChanged*(model: QAbstractListModel, topLeft: QModelIndex, bottomRight: QModelIndex, roles: seq[cint]) = From 67e7efbcd0e9a0f1e509bd34c957082bd91e8e0b Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 5 Feb 2015 23:04:59 +0100 Subject: [PATCH 48/58] Fixed using the IDynamicObject interface for the call that create slots, properties and signals With this change we can reuse the slots for adding slots, properties and signals for QObject for all DynamicQObject subclasses. --- DOtherSide/DOtherSide/DOtherSide.cpp | 18 ++++-- DOtherSide/DynamicQObject/DynamicQObject.h | 75 +++++++++++++--------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 2aa84a6..a1e35c8 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -309,7 +309,7 @@ void dos_qvariant_setQAbstractListModel(void* vptr, void* value) void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback) { - auto dynamicQObject = new DynamicQObject(); + auto dynamicQObject = new BaseQObject(); QQmlEngine::setObjectOwnership(dynamicQObject, QQmlEngine::CppOwnership); dynamicQObject->setDObjectPointer(dObjectPointer); dynamicQObject->setDObjectCallback(dObjectCallback); @@ -318,7 +318,7 @@ void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObje void dos_qobject_delete(void* vptr) { - auto dynamicQObject = reinterpret_cast*>(vptr); + auto dynamicQObject = reinterpret_cast(vptr); dynamicQObject->disconnect(); delete dynamicQObject; } @@ -328,7 +328,8 @@ void dos_qobject_slot_create(void* vptr, const char* name, int parametersCount, if (parametersCount <= 0) return; - auto dynamicQObject = reinterpret_cast*>(vptr); + auto qobject = reinterpret_cast(vptr); + auto dynamicQObject = dynamic_cast(qobject); QMetaType::Type returnType = static_cast(parametersMetaTypes[0]); QList argumentsTypes; @@ -343,7 +344,8 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount if (parametersCount <= 0) return; - auto dynamicQObject = reinterpret_cast*>(vptr); + auto qobject = reinterpret_cast(vptr); + auto dynamicQObject = dynamic_cast(qobject); QList argumentsTypes; for (int i = 0; i < parametersCount; ++i) @@ -354,10 +356,13 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount void dos_qobject_signal_emit(void* vptr, const char* name, int parametersCount, void** parameters) { - auto dynamicQObject = reinterpret_cast*>(vptr); + auto qobject = reinterpret_cast(vptr); + auto dynamicQObject = dynamic_cast(qobject); + QVariantList arguments; for (int i = 0; i < parametersCount; ++i) arguments << *(reinterpret_cast(parameters[i])); + dynamicQObject->emitSignal(QString::fromStdString(name), arguments); } @@ -368,7 +373,8 @@ void dos_qobject_property_create(void* vptr, const char* writeSlot, const char* notifySignal) { - auto dynamicQObject = reinterpret_cast*>(vptr); + auto qobject = reinterpret_cast(vptr); + auto dynamicQObject = dynamic_cast(qobject); dynamicQObject->registerProperty(QString(name), QMetaType::Type(type), QString(readSlot), diff --git a/DOtherSide/DynamicQObject/DynamicQObject.h b/DOtherSide/DynamicQObject/DynamicQObject.h index 5394f06..6f5c3a2 100644 --- a/DOtherSide/DynamicQObject/DynamicQObject.h +++ b/DOtherSide/DynamicQObject/DynamicQObject.h @@ -15,10 +15,8 @@ /// This class implements a QObject to which signals, slots and properties can be added dynamically template -class DynamicQObject : public T +class DynamicQObject : public T, public IDynamicQObject { - typedef void (*Callback)(void*, void*, int, void**); - public: /// Constructor DynamicQObject(); @@ -27,35 +25,31 @@ public: virtual ~DynamicQObject(); /// Sets the function to be called from C++ to D or Nimrod - virtual void setDObjectCallback(Callback callback) { - m_dObjectCallback = callback; - } + virtual void setDObjectCallback(IDynamicQObject::Callback callback) override; /// Sets the D or Nimrod object that owns this DynamicQObject - virtual void setDObjectPointer(void* dObjectPointer) { - m_dObjectPointer = dObjectPointer; - } + virtual void setDObjectPointer(void* dObjectPointer) override; /// Register a new signal virtual bool registerSignal(const QString& name, const QList& argumentsTypes, - int& signalIndex); + int& signalIndex) override; /// Register a new slot virtual bool registerSlot(const QString& name, const QMetaType::Type returnType, const QList& argumentsTypes, - int& slotIndex); + int& slotIndex) override; /// Register a new property virtual bool registerProperty(const QString& name, QMetaType::Type type, const QString& readSlotName, const QString& writeSlotName = "", - const QString& notifySignalName = ""); + const QString& notifySignalName = "") override; /// Emit the signal with the given name and arguments - virtual bool emitSignal(const QString& name, const QList& argumentsValues); + virtual bool emitSignal(const QString& name, const QList& argumentsValues) override; /// Return the QMetaObject for this DynamicQObject virtual const QMetaObject* metaObject() const; @@ -87,7 +81,7 @@ private: QHash m_propertiesByName; QScopedPointer m_metaObject; void* m_dObjectPointer; - Callback m_dObjectCallback; + IDynamicQObject::Callback m_dObjectCallback; }; template @@ -103,6 +97,18 @@ DynamicQObject::DynamicQObject() m_metaObject.reset(builder.toMetaObject()); } +template +void DynamicQObject::setDObjectCallback(IDynamicQObject::Callback callback) +{ + m_dObjectCallback = callback; +} + +template +void DynamicQObject::setDObjectPointer(void* dObjectPointer) +{ + m_dObjectPointer = dObjectPointer; +} + template DynamicQObject::~DynamicQObject() = default; @@ -129,10 +135,10 @@ bool DynamicQObject::registerSlot(const QString& name, methodBuilder.setAttributes(QMetaMethod::Scriptable); }; - auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data() - , afterSignalAdded - , afterSlotAdded - , afterPropertyAdded); + auto newMetaObject = recreateMetaObjectBuilder(m_metaObject.data(), + afterSignalAdded, + afterSlotAdded, + afterPropertyAdded); m_metaObject.reset(newMetaObject); @@ -158,13 +164,13 @@ bool DynamicQObject::registerSignal(const QString& name, const QList::writeProperty(const DynamicProperty& property, void** ar template int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** args) { - if (callType == QMetaObject::InvokeMetaMethod) + switch (callType) { + case QMetaObject::InvokeMetaMethod: { QMetaMethod method = m_metaObject->method(index); if (!method.isValid()) @@ -371,8 +378,8 @@ int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** DynamicSlot slot = m_slotsBySignature[method.methodSignature()]; return executeSlot(slot, args) ? 1 : -1; } - else if (callType == QMetaObject::ReadProperty) - { + + case QMetaObject::ReadProperty: { QMetaProperty metaProperty = m_metaObject->property(index); if (!metaProperty.isValid()) @@ -381,8 +388,8 @@ int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** DynamicProperty dynamicProperty = m_propertiesByName.value(metaProperty.name(), DynamicProperty()); return readProperty(dynamicProperty, args) ? 1 : -1; } - else if (callType == QMetaObject::WriteProperty) - { + + case QMetaObject::WriteProperty: { QMetaProperty metaProperty = m_metaObject->property(index); if (!metaProperty.isValid()) @@ -392,6 +399,10 @@ int DynamicQObject::qt_metacall(QMetaObject::Call callType, int index, void** return writeProperty(dynamicProperty, args) ? 1 : -1; } + default: + return T::qt_metacall(callType, index, args); + } + return -1; } @@ -426,19 +437,19 @@ QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMe metaObjectBuilder.setClassName(currentMetaObject->className()); metaObjectBuilder.setSuperClass(currentMetaObject->superClass()); - foreach (auto& method, signalsList) + for (auto& method : signalsList) metaObjectBuilder.addMethod(method); // Call custom code to be executed after signal have been added afterSignalAdded(metaObjectBuilder); - foreach (auto& method, methodsList) + for (auto& method : methodsList) metaObjectBuilder.addMethod(method); // Call custom code to be executed after slots have been added afterSlotAdded(metaObjectBuilder); - foreach (auto& property, propertiesList) + for (auto& property : propertiesList) metaObjectBuilder.addProperty(property); afterPropertyAdded(metaObjectBuilder); @@ -446,4 +457,4 @@ QMetaObject* DynamicQObject::recreateMetaObjectBuilder(QMetaObject* currentMe return metaObjectBuilder.toMetaObject(); } -#endif \ No newline at end of file +#endif From de533129d21478912c67761260e87dd78bf5c16f Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 2 Feb 2015 22:01:31 +0100 Subject: [PATCH 49/58] Updated the ContactApp for using the QAbstractListModel base class --- Nim/Examples/ContactApp/ApplicationLogic.nim | 6 ++ Nim/Examples/ContactApp/ContactList.nim | 101 ++++++++++++------- Nim/Examples/ContactApp/main.qml | 32 +++--- 3 files changed, 88 insertions(+), 51 deletions(-) diff --git a/Nim/Examples/ContactApp/ApplicationLogic.nim b/Nim/Examples/ContactApp/ApplicationLogic.nim index ed1242d..30cb7e2 100644 --- a/Nim/Examples/ContactApp/ApplicationLogic.nim +++ b/Nim/Examples/ContactApp/ApplicationLogic.nim @@ -29,5 +29,11 @@ QtObject: method onExitTriggered(self: ApplicationLogic) {.slot.} = self.app.quit + method addContact(self: ApplicationLogic, name: string, surname: string) {.slot.} = + self.contactList.add(name, surname) + + method delContact(self: ApplicationLogic, index: int) {.slot.} = + self.contactList.del(index) + QtProperty[QVariant] contactList: read = getContactList diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index 6b0dc04..a4d5abf 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -1,44 +1,73 @@ -## 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 +type + ContactList* = ref object of QAbstractListModel contacts*: seq[Contact] + ContactRoles = enum + FirstNameRole = 0 + SurnameRole = 1 - proc delete*(self: ContactList) = - let qobject = self.QObject - qobject.delete - for contact in self.contacts: - contact.delete - self.contacts = @[] - - proc newContactList*(): ContactList = - new(result) - result.contacts = @[] - result.create() - - method getCount(self: ContactList): int {.slot.} = - return self.contacts.len +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 - method countChanged(self: ContactList) {.signal.} +proc create(self: ContactList) = + var model = self.QAbstractListModel + model.create + self.contacts = @[] + +proc delete(self: ContactList) = + let model = self.QAbstractListModel + model.delete + for contact in self.contacts: + contact.delete + self.contacts = @[] - method add*(self: ContactList, name: string, surname: string) {.slot.} = - let contact = newContact() - contact.firstName = name - contact.surname = surname - self.contacts.add(contact) - self.countChanged() +proc newContactList*(): ContactList = + new(result, delete) + result.create() + +proc isRowValid(self: ContactList, row: cint): bool = + return row >= 0 and row < self.contacts.len + +method rowCount(self: ContactList, index: QModelIndex = nil): cint = + return self.contacts.len + +method data(self: ContactList, index: QModelIndex, role: cint): QVariant = + if not index.isValid: + return + if not self.isRowValid(index.row): + return + if role == FirstNameRole: + return self.contacts[index.row].firstName + elif role == SurnameRole: + return self.contacts[index.row].surname + else: + return + +method roleNames(self: ContactList): Table[cint, cstring] = + result = initTable[cint, cstring]() + result[FirstNameRole] = "firstName" + result[SurnameRole] = "surname" - method get*(self: ContactList, index: int): QObject {.slot.} = - if index < 0 or index >= self.contacts.len: - return nil - result = self.contacts[index].QObject +method add*(self: ContactList, name: string, surname: string) = + let contact = newContact() + contact.firstName = name + contact.surname = surname + self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len) + self.contacts.add(contact) + self.endInsertRows() - method del*(self: ContactList, index: int) {.slot.} = - self.contacts.del(index) - self.countChanged() +method get*(self: ContactList, pos: int): QObject = + if not self.isRowValid(pos): + return nil + result = self.contacts[pos].QObject - QtProperty[int] count: - read = getCount - notify = countChanged +method del*(self: ContactList, pos: int) = + if not self.isRowValid(pos): + return + self.beginRemoveRows(newQModelIndex(), pos, pos) + self.contacts.del(pos) + self.endRemoveRows diff --git a/Nim/Examples/ContactApp/main.qml b/Nim/Examples/ContactApp/main.qml index e4fe7e5..93a3bae 100644 --- a/Nim/Examples/ContactApp/main.qml +++ b/Nim/Examples/ContactApp/main.qml @@ -14,29 +14,31 @@ ApplicationWindow 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 { anchors.fill: parent - - ListView + + ScrollView { 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) } + + ListView + { + model: logic.contactList + spacing: 5 + delegate: RowLayout { + width: ListView.view.width + TextField { Layout.fillWidth: true; text: firstName } + TextField { Layout.fillWidth: true; text: surname } + Button { text: "Delete"; onClicked: logic.delContact(index) } + } } } @@ -46,7 +48,7 @@ ApplicationWindow 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.addContact(nameTextField.text, surnameTextField.text) } } } } From 55341ab3e25d43f8588620b8f805fadc637cafdf Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Tue, 10 Feb 2015 00:40:20 +0100 Subject: [PATCH 50/58] Updated the ContactApp for testing the QAbstractListModel generation of slots and properties --- DOtherSide/DOtherSide/DOtherSide.cpp | 3 + DOtherSide/DOtherSide/DOtherSide.h | 1 + Nim/Examples/ContactApp/ApplicationLogic.nim | 6 - Nim/Examples/ContactApp/ContactList.nim | 115 +++++++++---------- Nim/Examples/ContactApp/main.qml | 23 ++-- Nim/NimQml/NimQml.nim | 55 ++++----- Nim/NimQml/NimQmlTypes.nim | 16 +-- 7 files changed, 97 insertions(+), 122 deletions(-) diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index a1e35c8..c1a4928 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -442,6 +442,7 @@ void dos_qmodelindex_sibling(void* vptr, int row, int column, void* sibling) void dos_qabstractlistmodel_create(void** vptr, void* modelObject, + DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, DataCallback dataCallback, RoleNamesCallback roleNamesCallaback) @@ -450,6 +451,8 @@ void dos_qabstractlistmodel_create(void** vptr, rowCountCallback, dataCallback, roleNamesCallaback); + model->setDObjectPointer(modelObject); + model->setDObjectCallback(dObjectCallback); *vptr = model; } diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 38f2fbe..367ba79 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -122,6 +122,7 @@ void dos_qhash_int_qbytearray_value(QHashIntQByteArrayVoidPtr vptr, int key, cha // QAbstractListModel void dos_qabstractlistmodel_create(void** vptr, void* callbackObject, + DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, DataCallback dataCallback, RoleNamesCallback roleNamesCallback); diff --git a/Nim/Examples/ContactApp/ApplicationLogic.nim b/Nim/Examples/ContactApp/ApplicationLogic.nim index 30cb7e2..ed1242d 100644 --- a/Nim/Examples/ContactApp/ApplicationLogic.nim +++ b/Nim/Examples/ContactApp/ApplicationLogic.nim @@ -29,11 +29,5 @@ QtObject: method onExitTriggered(self: ApplicationLogic) {.slot.} = self.app.quit - method addContact(self: ApplicationLogic, name: string, surname: string) {.slot.} = - self.contactList.add(name, surname) - - method delContact(self: ApplicationLogic, index: int) {.slot.} = - self.contactList.del(index) - QtProperty[QVariant] contactList: read = getContactList diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index a4d5abf..7cef2a3 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -1,73 +1,62 @@ import NimQml, NimQmlMacros, Contact, Tables -type - ContactList* = ref object of QAbstractListModel - contacts*: seq[Contact] - ContactRoles = enum - FirstNameRole = 0 - SurnameRole = 1 +QtObject: + type + ContactList* = ref object of QAbstractListModel + contacts*: seq[Contact] + ContactRoles = enum + FirstNameRole = 0 + SurnameRole = 1 -converter toCInt(value: ContactRoles): cint = return value.cint -converter toCInt(value: int): cint = return value.cint -converter toInt(value: ContactRoles): int = return value.int -converter toInt(value: cint): int = return value.int -converter toQVariant(value: string): QVariant = return value.newQVariant + converter toCInt(value: ContactRoles): cint = return value.cint + converter toCInt(value: int): cint = return value.cint + converter toInt(value: ContactRoles): int = return value.int + converter toInt(value: cint): int = return value.int + converter toQVariant(value: string): QVariant = return value.newQVariant -proc create(self: ContactList) = - var model = self.QAbstractListModel - model.create - self.contacts = @[] - -proc delete(self: ContactList) = - let model = self.QAbstractListModel - model.delete - for contact in self.contacts: - contact.delete - self.contacts = @[] + proc delete(self: ContactList) = + let model = self.QAbstractListModel + model.delete + for contact in self.contacts: + contact.delete + self.contacts = @[] -proc newContactList*(): ContactList = - new(result, delete) - result.create() + proc newContactList*(): ContactList = + new(result, delete) + result.contacts = @[] + result.create -proc isRowValid(self: ContactList, row: cint): bool = - return row >= 0 and row < self.contacts.len - -method rowCount(self: ContactList, index: QModelIndex = nil): cint = - return self.contacts.len + method rowCount(self: ContactList, index: QModelIndex = nil): cint = + return self.contacts.len -method data(self: ContactList, index: QModelIndex, role: cint): QVariant = - if not index.isValid: - return - if not self.isRowValid(index.row): - return - if role == FirstNameRole: - return self.contacts[index.row].firstName - elif role == SurnameRole: - return self.contacts[index.row].surname - else: - return + method data(self: ContactList, index: QModelIndex, role: cint): QVariant = + if not index.isValid: + return + if index.row < 0 or index.row >= self.contacts.len: + return + if role == FirstNameRole: + return self.contacts[index.row].firstName + elif role == SurnameRole: + return self.contacts[index.row].surname + else: + return -method roleNames(self: ContactList): Table[cint, cstring] = - result = initTable[cint, cstring]() - result[FirstNameRole] = "firstName" - result[SurnameRole] = "surname" + method roleNames(self: ContactList): Table[cint, cstring] = + result = initTable[cint, cstring]() + result[FirstNameRole] = "firstName" + result[SurnameRole] = "surname" -method add*(self: ContactList, name: string, surname: string) = - let contact = newContact() - contact.firstName = name - contact.surname = surname - self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len) - self.contacts.add(contact) - self.endInsertRows() + method add*(self: ContactList, name: string, surname: string) {.slot.} = + let contact = newContact() + contact.firstName = name + contact.surname = surname + self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len) + self.contacts.add(contact) + self.endInsertRows() -method get*(self: ContactList, pos: int): QObject = - if not self.isRowValid(pos): - return nil - result = self.contacts[pos].QObject - -method del*(self: ContactList, pos: int) = - if not self.isRowValid(pos): - return - self.beginRemoveRows(newQModelIndex(), pos, pos) - self.contacts.del(pos) - self.endRemoveRows + method del*(self: ContactList, pos: int) {.slot.} = + if pos < 0 or pos >= self.contacts.len: + return + self.beginRemoveRows(newQModelIndex(), pos, pos) + self.contacts.del(pos) + self.endRemoveRows diff --git a/Nim/Examples/ContactApp/main.qml b/Nim/Examples/ContactApp/main.qml index 93a3bae..cad7dc3 100644 --- a/Nim/Examples/ContactApp/main.qml +++ b/Nim/Examples/ContactApp/main.qml @@ -3,16 +3,15 @@ import QtQuick.Controls 1.2 import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 -ApplicationWindow -{ +ApplicationWindow { + width: 400 height: 300 title: "ContactApp" visible: true menuBar: MenuBar { - Menu - { + Menu { title: "&File" MenuItem { text: "&Load"; onTriggered: logic.onLoadTriggered() } MenuItem { text: "&Save"; onTriggered: logic.onSaveTriggered() } @@ -20,35 +19,31 @@ ApplicationWindow } } - ColumnLayout - { + ColumnLayout { anchors.fill: parent - ScrollView - { + ScrollView { Layout.fillWidth: true Layout.fillHeight: true - ListView - { + ListView { model: logic.contactList spacing: 5 delegate: RowLayout { width: ListView.view.width TextField { Layout.fillWidth: true; text: firstName } TextField { Layout.fillWidth: true; text: surname } - Button { text: "Delete"; onClicked: logic.delContact(index) } + Button { text: "Delete"; onClicked: logic.contactList.del(index) } } } } - RowLayout - { + RowLayout { Label { text: "Name" } TextField { id: nameTextField; Layout.fillWidth: true; text: "" } Label { text: "Surname" } TextField { id: surnameTextField; Layout.fillWidth: true; text: "" } - Button { text: "Add"; onClicked: logic.addContact(nameTextField.text, surnameTextField.text) } + Button { text: "Add"; onClicked: logic.contactList.add(nameTextField.text, surnameTextField.text) } } } } diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 9e23e24..8e19769 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -78,7 +78,6 @@ proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {. proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_float(variant: var RawQVariant, value: cfloat) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_create_double(variant: var RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_qabstractlistmodel(variant: var RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -93,7 +92,6 @@ proc dos_qvariant_setFloat(variant: RawQVariant, value: float) {.cdecl, dynlib: proc dos_qvariant_toDouble(variant: RawQVariant, value: var cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setDouble(variant: RawQVariant, value: cdouble) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qvariant_setQObject(variant: RawQVariant, value: RawQObject) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_setQAbstractListModel(variant: RawQVariant, value: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc create*(variant: QVariant) = @@ -118,14 +116,9 @@ proc create*(variant: QVariant, value: string) = proc create*(variant: QVariant, value: QObject) = ## Create a new QVariant given a QObject - dos_qvariant_create_qobject(variant.data, value.data) + dos_qvariant_create_qobject(variant.data, value.data.RawQObject) variant.deleted = false -proc create*(variant: QVariant, value: QAbstractListModel) = - ## Create a new QVariant given a QAbstractListModel - dos_qvariant_create_qabstractlistmodel(variant.data, value.data) - variant.deleted = false - proc create*(variant: QVariant, value: RawQVariant) = ## Create a new QVariant given another QVariant. ## The inner value of the QVariant is copied @@ -175,11 +168,6 @@ proc newQVariant*(value: QObject): QVariant = newWithCondFinalizer(result, delete) result.create(value) -proc newQVariant*(value: QAbstractListModel): QVariant = - ## Return a new QVariant given a QAbstractListModel - newWithCondFinalizer(result, delete) - result.create(value) - proc newQVariant*(value: RawQVariant): QVariant = ## Return a new QVariant given a raw QVariant pointer newWithCondFinalizer(result, delete) @@ -252,11 +240,7 @@ proc `stringVal=`*(variant: QVariant, value: string) = proc `qobjectVal=`*(variant: QVariant, value: QObject) = ## Sets the QVariant qobject value - dos_qvariant_setQObject(variant.data, value.data) - -proc `qabstractListModelVal=`*(variant: QVariant, value: QAbstractListModel) = - ## Sets the QVariant qabstractlistmodel value - dos_qvariant_setQAbstractListModel(variant.data, value.data) + dos_qvariant_setQObject(variant.data, value.data.RawQObject) proc assign*(leftValue: QVariant, rightValue: QVariant) = ## Assign a QVariant with another. The inner value of the QVariant is copied @@ -636,6 +620,7 @@ type RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: Ra proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, modelPtr: ptr QAbstractListModelObj, + qobjectCallback: QObjectCallBack, rowCountCallback: RowCountCallback, dataCallback: DataCallback, roleNamesCallback: RoleNamesCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} @@ -691,18 +676,24 @@ proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashInt proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel debugMsg("QAbstractListModel", "create") - let modelPtr = addr(model[]) - dos_qabstractlistmodel_create(model.data, modelPtr, rowCountCallback, dataCallback, roleNamesCallback) + model.slots = initTable[string,cint]() + model.signals = initTable[string, cint]() + model.properties = initTable[string, cint]() model.deleted = false + let modelPtr = addr(model[]) + dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, dataCallback, roleNamesCallback) + qobjectRegistry[modelPtr] = true proc delete*(model: QAbstractListModel) = ## Delete the given QAbstractListModel if not model.deleted: debugMsg("QAbstractListModel", "delete") - dos_qabstractlistmodel_delete(model.data) - model.data = nil.RawQAbstractListModel + let modelPtr = addr(model[]) + qobjectRegistry.del modelPtr + dos_qabstractlistmodel_delete(model.data.RawQAbstractListModel) + model.data = nil.RawQObject model.deleted = true - + proc newQAbstractListModel*(): QAbstractListModel = ## Return a new QAbstractListModel newWithCondFinalizer(result, delete) @@ -710,32 +701,32 @@ proc newQAbstractListModel*(): QAbstractListModel = proc beginInsertRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = ## Notify the view that the model is about to inserting the given number of rows - dos_qabstractlistmodel_beginInsertRows(model.data, parentIndex.data, first.cint, last.cint) + dos_qabstractlistmodel_beginInsertRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint) proc endInsertRows*(model: QAbstractListModel) = ## Notify the view that the rows have been inserted - dos_qabstractlistmodel_endInsertRows(model.data) + dos_qabstractlistmodel_endInsertRows(model.data.RawQAbstractListModel) proc beginRemoveRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) = ## Notify the view that the model is about to remove the given number of rows - dos_qabstractlistmodel_beginRemoveRows(model.data, parentIndex.data, first.cint, last.cint) + dos_qabstractlistmodel_beginRemoveRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint) proc endRemoveRows*(model: QAbstractListModel) = ## Notify the view that the rows have been removed - dos_qabstractlistmodel_endRemoveRows(model.data) + dos_qabstractlistmodel_endRemoveRows(model.data.RawQAbstractListModel) proc beginResetModel*(model: QAbstractListModel) = ## Notify the view that the model is about to resetting - dos_qabstractlistmodel_beginResetModel(model.data) + dos_qabstractlistmodel_beginResetModel(model.data.RawQAbstractListModel) proc endResetModel*(model: QAbstractListModel) = ## Notify the view that model has finished resetting - dos_qabstractlistmodel_endResetModel(model.data) + dos_qabstractlistmodel_endResetModel(model.data.RawQAbstractListModel) proc dataChanged*(model: QAbstractListModel, topLeft: QModelIndex, bottomRight: QModelIndex, - roles: seq[cint]) = + roles: var seq[cint]) = ## Notify the view that the model data changed - var temp = roles - dos_qabstractlistmodel_dataChanged(model.data, topLeft.data, bottomRight.data, temp[0].addr, temp.len.cint) + dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, roles[0].addr, roles.len.cint) + diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 0f9c59d..8902170 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -24,8 +24,16 @@ type signals: Table[string, cint] properties: Table[string, cint] deleted: bool - QObject* = ref QObjectObj ## A QObject + QObject* = ref QObjectObj + RawBaseQObjectObj = distinct pointer + BaseQObjectObj = object of QObjectObj + BaseQObject* = ref BaseQObjectObj ## A QObject + + RawQAbstractListModel = distinct pointer + QAbstractListModelObj = object of QObjectObj + QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel + RawQQuickView = distinct pointer QQuickView = ref object of RootObj ## A QQuickView data: RawQQuickView @@ -38,12 +46,6 @@ type data: RawQModelIndex deleted: bool - RawQAbstractListModel = distinct pointer - QAbstractListModelObj = object of RootObj - data: RawQAbstractListModel - deleted: bool - QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel - RawQHashIntByteArray = distinct pointer QHashIntByteArrayObj = object of RootObj data: RawQHashIntByteArray From 23c73e4e7580a85507b6f3482a5b46ec628bc17a Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 2 Feb 2015 22:05:44 +0100 Subject: [PATCH 51/58] Updated the gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 39352d7..8b778ba 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ build *.o .directory #*# -nimcache \ No newline at end of file +nimcache +*.kdev4 \ No newline at end of file From 84c58761ad61b47033524d6c1272a20a8f85b3ef Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sat, 14 Feb 2015 15:45:04 +0100 Subject: [PATCH 52/58] Added support for setData and flags methods --- .../DOtherSide/BaseQAbstractListModel.h | 40 ++++++++++++++-- DOtherSide/DOtherSide/DOtherSide.cpp | 8 +++- DOtherSide/DOtherSide/DOtherSide.h | 17 ++++--- DOtherSide/DOtherSide/DOtherSideTypes.h | 4 +- Nim/Examples/ContactApp/ContactList.nim | 46 ++++++++++++++----- Nim/NimQml/NimQml.nim | 33 +++++++++++-- Nim/NimQml/NimQmlTypes.nim | 13 ++++++ 7 files changed, 132 insertions(+), 29 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index cf40dc2..1089be0 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -13,14 +13,22 @@ public: BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback, DataCallback dataCallback, - RoleNamesCallback roleNamesCallback); + SetDataCallback setDataCallback, + RoleNamesCallback roleNamesCallback, + FlagsCallback flagsCallback); /// Return the model's row count virtual int rowCount(const QModelIndex& index = 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 dModelPointer void* modelObject(); @@ -54,17 +62,23 @@ private: void* m_modelObject; RowCountCallback m_rowCountCallback; DataCallback m_dataCallback; + SetDataCallback m_setDataCallback; RoleNamesCallback m_roleNamesCallback; + FlagsCallback m_flagsCallback; }; BaseQAbstractListModel::BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback, DataCallback dataCallback, - RoleNamesCallback roleNamesCallback) + SetDataCallback setDataCallback, + RoleNamesCallback roleNamesCallback, + FlagsCallback flagsCallback) : m_modelObject(modelObject) , m_rowCountCallback(rowCountCallback) , m_dataCallback(dataCallback) + , m_setDataCallback(setDataCallback) , m_roleNamesCallback(roleNamesCallback) + , m_flagsCallback(flagsCallback) { } @@ -86,6 +100,26 @@ QVariant BaseQAbstractListModel::data(const QModelIndex& index, int role) const 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); +} + void* BaseQAbstractListModel::modelObject() { return m_modelObject; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index c1a4928..5766bf7 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -445,12 +445,16 @@ void dos_qabstractlistmodel_create(void** vptr, DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, DataCallback dataCallback, - RoleNamesCallback roleNamesCallaback) + SetDataCallback setDataCallback, + RoleNamesCallback roleNamesCallaback, + FlagsCallback flagsCallback) { auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, dataCallback, - roleNamesCallaback); + setDataCallback, + roleNamesCallaback, + flagsCallback); model->setDObjectPointer(modelObject); model->setDObjectCallback(dObjectCallback); *vptr = model; diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 367ba79..472df10 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -125,16 +125,19 @@ void dos_qabstractlistmodel_create(void** vptr, DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, DataCallback dataCallback, - RoleNamesCallback roleNamesCallback); + SetDataCallback setDataCallback, + RoleNamesCallback roleNamesCallback, + FlagsCallback FlagsCallback + ); void dos_qabstractlistmodel_beginInsertRows(void* vptr, - QModelIndexVoidPtr parentIndex, - int first, - int last); + QModelIndexVoidPtr parentIndex, + int first, + int last); void dos_qabstractlistmodel_endInsertRows(void* vptr); void dos_qabstractlistmodel_beginRemoveRows(void* vptr, - QModelIndexVoidPtr parentIndex, - int first, - int last); + QModelIndexVoidPtr parentIndex, + int first, + int last); void dos_qabstractlistmodel_endRemoveRows(void* vptr); void dos_qabstractlistmodel_beginResetModel(void* vptr); void dos_qabstractlistmodel_endResetModel(void* vptr); diff --git a/DOtherSide/DOtherSide/DOtherSideTypes.h b/DOtherSide/DOtherSide/DOtherSideTypes.h index 16a88d9..d4a8407 100644 --- a/DOtherSide/DOtherSide/DOtherSideTypes.h +++ b/DOtherSide/DOtherSide/DOtherSideTypes.h @@ -2,6 +2,7 @@ #define DOTHERSIDETYPES_H // Raw data types +typedef bool* BoolPtr; typedef int* IntPtr; typedef char* CharPtr; typedef const char* ConstCharPtr; @@ -18,6 +19,7 @@ typedef void (*Function)(void*); typedef void (*DObjectCallback)(void*, void*, int, void**); typedef void (*RowCountCallback)(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); #endif \ No newline at end of file diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index 7cef2a3..eb127fe 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -4,9 +4,9 @@ QtObject: type ContactList* = ref object of QAbstractListModel contacts*: seq[Contact] - ContactRoles = enum - FirstNameRole = 0 - SurnameRole = 1 + ContactRoles {.pure.} = enum + FirstName = 0 + Surname = 1 converter toCInt(value: ContactRoles): cint = return value.cint converter toCInt(value: int): cint = return value.cint @@ -34,17 +34,41 @@ QtObject: return if index.row < 0 or index.row >= self.contacts.len: return - if role == FirstNameRole: - return self.contacts[index.row].firstName - elif role == SurnameRole: - return self.contacts[index.row].surname - else: - return + 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 setData(self: ContactList, index: QModelIndex, value: QVariant, role: cint): bool = + result = false + if not index.isValid: + return + if index.row < 0 or index.row >= self.contacts.len: + return + if value.isNull: + return + var contact = self.contacts[index.row] + let contactRole = role.ContactRoles + case contactRole: + of ContactRoles.FirstName: + contact.firstName = value.stringVal + self.dataChanged(index, index, @[role]) + result = true + of ContactRoles.Surname: + contact.surname = value.stringVal + self.dataChanged(index, index, @[role]) + result = true + else: discard() + + method flags(self: ContactList): QItemFlag = + return QItemFlag.IsEditable + method roleNames(self: ContactList): Table[cint, cstring] = result = initTable[cint, cstring]() - result[FirstNameRole] = "firstName" - result[SurnameRole] = "surname" + result[ContactRoles.FirstName] = "firstName" + result[ContactRoles.Surname] = "surname" method add*(self: ContactList, name: string, surname: string) {.slot.} = let contact = newContact() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 8e19769..8978fe1 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -616,14 +616,18 @@ proc newQHashIntQByteArray*(): QHashIntByteArray = # QAbstractListModel type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.} type DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.} +type SetDataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, value: RawQVariant, role: cint, result: var bool) {.cdecl.} type RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: RawQHashIntByteArray) {.cdecl.} +type FlagsCallback = proc(modelObject: ptr QAbstractListModelObj, index: RawQModelIndex, result: var cint) {.cdecl.} proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel, modelPtr: ptr QAbstractListModelObj, qobjectCallback: QObjectCallBack, rowCountCallback: RowCountCallback, dataCallback: DataCallback, - roleNamesCallback: RoleNamesCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} + setDataCallback: SetDataCallBack, + roleNamesCallback: RoleNamesCallback, + flagsCallback: FlagsCallback) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:"libDOtherSide.so", importc.} proc dos_qabstractlistmodel_beginInsertRows(model: RawQAbstractListModel, parentIndex: RawQModelIndex, @@ -664,6 +668,16 @@ proc dataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelInd 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.} = + 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] = result = initTable[cint, cstring]() @@ -672,7 +686,15 @@ proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashInt 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): QItemFlag = + return QItemFlag.None + +proc flagsCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} = + let model = cast[QAbstractListModel](modelObject) + let index = newQModelIndex(rawIndex) + result = model.flags(index).cint + proc create*(model: var QAbstractListModel) = ## Create a new QAbstractListModel debugMsg("QAbstractListModel", "create") @@ -681,7 +703,7 @@ proc create*(model: var QAbstractListModel) = model.properties = initTable[string, cint]() model.deleted = false let modelPtr = addr(model[]) - dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, dataCallback, roleNamesCallback) + dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, dataCallback, setDataCallback, roleNamesCallback, flagsCallback) qobjectRegistry[modelPtr] = true proc delete*(model: QAbstractListModel) = @@ -726,7 +748,8 @@ proc endResetModel*(model: QAbstractListModel) = proc dataChanged*(model: QAbstractListModel, topLeft: QModelIndex, bottomRight: QModelIndex, - roles: var seq[cint]) = + roles: seq[cint]) = ## Notify the view that the model data changed - dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, roles[0].addr, roles.len.cint) + var copy = roles + dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, copy[0].addr, copy.len.cint) diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index 8902170..ae9088e 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -51,3 +51,16 @@ type data: RawQHashIntByteArray deleted: bool QHashIntByteArray* = ref QHashIntByteArrayObj ## A QHash + + QItemFlag* {.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 + + From 99359968de2425a4bc9912c7fbf5b535782583e1 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 12:59:42 +0100 Subject: [PATCH 53/58] Added support for headerData and columnsCount methods --- .../DOtherSide/BaseQAbstractListModel.h | 44 ++++++++++-- DOtherSide/DOtherSide/DOtherSide.cpp | 8 ++- DOtherSide/DOtherSide/DOtherSide.h | 5 +- DOtherSide/DOtherSide/DOtherSideTypes.h | 2 + Nim/Examples/ContactApp/ContactList.nim | 6 +- Nim/Examples/ContactApp/main.qml | 72 +++++++++++++++---- Nim/NimQml/NimQml.nim | 56 ++++++++++++--- Nim/NimQml/NimQmlTypes.nim | 6 +- 8 files changed, 158 insertions(+), 41 deletions(-) diff --git a/DOtherSide/DOtherSide/BaseQAbstractListModel.h b/DOtherSide/DOtherSide/BaseQAbstractListModel.h index 1089be0..85448c7 100644 --- a/DOtherSide/DOtherSide/BaseQAbstractListModel.h +++ b/DOtherSide/DOtherSide/BaseQAbstractListModel.h @@ -12,13 +12,18 @@ public: /// Constructor BaseQAbstractListModel(void* modelObject, RowCountCallback rowCountCallback, + ColumnCountCallback columnCountCallback, DataCallback dataCallback, SetDataCallback setDataCallback, RoleNamesCallback roleNamesCallback, - FlagsCallback flagsCallback); + FlagsCallback flagsCallback, + HeaderDataCallback headerDataCallback); /// Return the model's row count - virtual int rowCount(const QModelIndex& index = QModelIndex()) const override; + 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; @@ -29,6 +34,9 @@ public: /// 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(); @@ -61,33 +69,48 @@ public: 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) + 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& index) const +int BaseQAbstractListModel::rowCount(const QModelIndex& parent) const { - auto newIndex = new QModelIndex(); - *newIndex = index; + auto parentIndex = new QModelIndex(); + *parentIndex = parent; int result; - m_rowCountCallback(m_modelObject, newIndex, &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; } @@ -120,6 +143,13 @@ Qt::ItemFlags BaseQAbstractListModel::flags(const QModelIndex& index) const 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; diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index 5766bf7..d75b07d 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -444,17 +444,21 @@ void dos_qabstractlistmodel_create(void** vptr, void* modelObject, DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, + ColumnCountCallback columnCountCallback, DataCallback dataCallback, SetDataCallback setDataCallback, RoleNamesCallback roleNamesCallaback, - FlagsCallback flagsCallback) + FlagsCallback flagsCallback, + HeaderDataCallback headerDataCallback) { auto model = new BaseQAbstractListModel(modelObject, rowCountCallback, + columnCountCallback, dataCallback, setDataCallback, roleNamesCallaback, - flagsCallback); + flagsCallback, + headerDataCallback); model->setDObjectPointer(modelObject); model->setDObjectCallback(dObjectCallback); *vptr = model; diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 472df10..54a90ea 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -124,11 +124,12 @@ void dos_qabstractlistmodel_create(void** vptr, void* callbackObject, DObjectCallback dObjectCallback, RowCountCallback rowCountCallback, + ColumnCountCallback columnCountCallback, DataCallback dataCallback, SetDataCallback setDataCallback, RoleNamesCallback roleNamesCallback, - FlagsCallback FlagsCallback - ); + FlagsCallback flagsCallback, + HeaderDataCallback headerDataCallback); void dos_qabstractlistmodel_beginInsertRows(void* vptr, QModelIndexVoidPtr parentIndex, int first, diff --git a/DOtherSide/DOtherSide/DOtherSideTypes.h b/DOtherSide/DOtherSide/DOtherSideTypes.h index d4a8407..0eb6a40 100644 --- a/DOtherSide/DOtherSide/DOtherSideTypes.h +++ b/DOtherSide/DOtherSide/DOtherSideTypes.h @@ -18,8 +18,10 @@ typedef void* QHashIntQByteArrayVoidPtr; 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 \ No newline at end of file diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index eb127fe..0f07295 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -28,7 +28,7 @@ QtObject: method rowCount(self: ContactList, index: QModelIndex = nil): cint = return self.contacts.len - + method data(self: ContactList, index: QModelIndex, role: cint): QVariant = if not index.isValid: return @@ -62,8 +62,8 @@ QtObject: result = true else: discard() - method flags(self: ContactList): QItemFlag = - return QItemFlag.IsEditable + method flags(self: ContactList): QtItemFlag = + return QtItemFlag.IsEditable method roleNames(self: ContactList): Table[cint, cstring] = result = initTable[cint, cstring]() diff --git a/Nim/Examples/ContactApp/main.qml b/Nim/Examples/ContactApp/main.qml index cad7dc3..e9c73c1 100644 --- a/Nim/Examples/ContactApp/main.qml +++ b/Nim/Examples/ContactApp/main.qml @@ -5,7 +5,7 @@ import QtQuick.Window 2.1 ApplicationWindow { - width: 400 + width: 500 height: 300 title: "ContactApp" visible: true @@ -22,28 +22,72 @@ ApplicationWindow { ColumnLayout { anchors.fill: parent - ScrollView { - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - model: logic.contactList - spacing: 5 - delegate: RowLayout { - width: ListView.view.width - TextField { Layout.fillWidth: true; text: firstName } - TextField { Layout.fillWidth: true; text: surname } - Button { text: "Delete"; onClicked: logic.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 + } } } } + 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 !== "" + } } } } diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 8978fe1..a9f8914 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -614,20 +614,25 @@ proc newQHashIntQByteArray*(): QHashIntByteArray = result.create() # QAbstractListModel -type RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.} -type DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.} -type SetDataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, value: RawQVariant, role: cint, result: var bool) {.cdecl.} -type RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: RawQHashIntByteArray) {.cdecl.} -type FlagsCallback = proc(modelObject: ptr QAbstractListModelObj, index: RawQModelIndex, result: var cint) {.cdecl.} +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) {.cdecl, dynlib:"libDOtherSide.so", importc.} + 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, @@ -652,15 +657,27 @@ method rowCount*(model: QAbstractListModel, index: QModelIndex): cint = 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 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) @@ -673,27 +690,44 @@ method setData*(model: QAbstractListModel, index: QModelIndex, value: QVariant, 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] = +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): QItemFlag = - return QItemFlag.None +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 @@ -703,7 +737,7 @@ proc create*(model: var QAbstractListModel) = model.properties = initTable[string, cint]() model.deleted = false let modelPtr = addr(model[]) - dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, dataCallback, setDataCallback, roleNamesCallback, flagsCallback) + dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, columnCountCallback, dataCallback, setDataCallback, roleNamesCallback, flagsCallback, headerDataCallback) qobjectRegistry[modelPtr] = true proc delete*(model: QAbstractListModel) = diff --git a/Nim/NimQml/NimQmlTypes.nim b/Nim/NimQml/NimQmlTypes.nim index ae9088e..f7cc580 100644 --- a/Nim/NimQml/NimQmlTypes.nim +++ b/Nim/NimQml/NimQmlTypes.nim @@ -52,7 +52,7 @@ type deleted: bool QHashIntByteArray* = ref QHashIntByteArrayObj ## A QHash - QItemFlag* {.pure.} = enum + QtItemFlag* {.pure.} = enum None = 0.cint, IsSelectable = 1.cint, IsEditable = 2.cint, @@ -63,4 +63,6 @@ type IsTristate = 64.cint, NeverHasChildren = 128.cint - + QtOrientation {.pure.} = enum + Horizontal = 1.cint, + Vertical = 2.cint From 0b1ec5206042b0edd0056ec1d6eb8ace87d882e5 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 14:12:45 +0100 Subject: [PATCH 54/58] Simplified the ContactApp example --- Nim/Examples/ContactApp/ContactList.nim | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/Nim/Examples/ContactApp/ContactList.nim b/Nim/Examples/ContactApp/ContactList.nim index 0f07295..c1ccb7e 100644 --- a/Nim/Examples/ContactApp/ContactList.nim +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -41,30 +41,6 @@ QtObject: of ContactRoles.Surname: return contact.surname else: return - method setData(self: ContactList, index: QModelIndex, value: QVariant, role: cint): bool = - result = false - if not index.isValid: - return - if index.row < 0 or index.row >= self.contacts.len: - return - if value.isNull: - return - var contact = self.contacts[index.row] - let contactRole = role.ContactRoles - case contactRole: - of ContactRoles.FirstName: - contact.firstName = value.stringVal - self.dataChanged(index, index, @[role]) - result = true - of ContactRoles.Surname: - contact.surname = value.stringVal - self.dataChanged(index, index, @[role]) - result = true - else: discard() - - method flags(self: ContactList): QtItemFlag = - return QtItemFlag.IsEditable - method roleNames(self: ContactList): Table[cint, cstring] = result = initTable[cint, cstring]() result[ContactRoles.FirstName] = "firstName" From 6873425d58c929e9195e7353e8e2f13cadfef2be Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 14:18:36 +0100 Subject: [PATCH 55/58] Updated the doc with the ContactApp example --- Nim/Docs/NimQml.txt | 59 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/Nim/Docs/NimQml.txt b/Nim/Docs/NimQml.txt index ec1e322..e330f2f 100644 --- a/Nim/Docs/NimQml.txt +++ b/Nim/Docs/NimQml.txt @@ -2,8 +2,8 @@ Filippo Cucchetto Will Szumski -:Version: 0.2.0 -:Date: 2015/01/02 +:Version: 0.3.0 +:Date: 2015/02/15 Introduction ----------- @@ -126,6 +126,7 @@ At the time of writing the QVariant class support the following types: * int * string * bool +* float * QObject derived classes Example 3: exposing complex data and procedures to Qml @@ -247,3 +248,57 @@ The ``QtProperty`` macro has the following syntax .. code-block:: nim QtProperty[typeOfProperty] nameOfProperty +Example 5: ContactApp +------------------------- +The last example tries to show you all the stuff presented +in the previous chapters and gives you an introduction to how +to expose lists to qml. + +Qt models are a huge topic and explaining how they work is +out of scope. For further information please read the official +Qt documentation. + +The main file follows the basic logic of creating a qml +engine and exposing a QObject derived object "ApplicationLogic" +through a global "logic" property + +``Examples/ContactApp/main.nim`` + +.. code-block:: nim + :file: ../Examples/ContactApp/main.nim + +The qml file shows a simple app with a central tableview + +``Examples/ContactApp/main.qml`` + +.. code-block:: qml + :file: ../Examples/ContactApp/main.qml + +The important things to notice are: +1. The menubar load, save and exit items handlers call the logic load, save and exit slots +2. The TableView model is retrieved by the logic.contactList property +3. The delete and add buttons call the del and add slots of the logic.contactList model + +The ApplicationLogic object is as follows: + +``Examples/ContactApp/ApplicationLogic.nim`` + +.. code-block:: nim + :file: ../Examples/ContactApp/ApplicationLogic.nim + +The ApplicationLogic object, +1. expose some slots for handling the qml menubar triggered signals +2. expose a contactList property that return a QAbstractListModel derived object that manage the list of contacts + +The ContactList object is as follows: + +``Examples/ContactApp/ContactList.nim`` + +.. code-block:: nim + :file: ../Examples/ContactApp/ContactList.nim + +The ContactList object: +1. overrides the ``rowCount`` method for returning the number of rows stored in the model +2. overrides the ``data`` method for returning the value for the exported roles +3. overrides the ``roleNames`` method for returning the names of the roles of the model. This name are then available in the qml item delegates +4. defines two slots ``add`` and ``del`` that add or delete a Contact. During this operations the model execute the ``beginInsertRows`` and ``beginRemoveRows`` for notifing the view of an upcoming change. Once the add or delete operations are done the model execute the ``endInsertRows`` and ``endRemoveRows``. From 4978afdfab4d26d3512a26d72c04608ad3ba254c Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 14:34:20 +0100 Subject: [PATCH 56/58] Added change log --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7b6e417 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Version 3.0 +* [NimQml] Added support for QAbstractListModel subclasses +* [NimQml] Fixed QtObject macro wrong reorder of the methods and proc declaration (thanks to Will) +* [NimQml] Added new ContactApp example +* [NimQml] Added optional support for finalizers +* [DOtherSide] Added support for injecting the DynamicQObject as behaviour to QObject subclasses +* [DotherSide] Added support for QAbstractListModel subclasses + +# Version 2.0 +* [DQml] Initial support for properties creation +* [NimQml] Added new macro syntax for creating QObject derived object (thanks to Will) + +# Version 1.0 +* [DOtherSide] Initial version with support for QObject Slot, Signal and Properties creation +* [DQml] Initial support for Slot and Signal creation +* [NimQml] Initial support for Slot, Signal and Properties creation \ No newline at end of file From d31f47d71bf5e43b3911f8659bf6b27aa7fc6252 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 14:34:38 +0100 Subject: [PATCH 57/58] Updated the readme for linking the changelog --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b74beba..19b1cb7 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ THIS IS UNSTABLE AND ALPHA SOFTWARE ## Description Qml bindings for both D and Nim programming languages +## Change log +The project change log can be read [here](./CHANGELOG.md). + ## Documentation The documentation for the Nim programming language can be read [here](http://filcuc.github.io/DOtherSide/ ""). From 740257d7442a285ca803995462798ed2be41d915 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Sun, 15 Feb 2015 14:46:00 +0100 Subject: [PATCH 58/58] Updated the .nimble file --- Nim/NimQml/NimQml.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nim/NimQml/NimQml.nimble b/Nim/NimQml/NimQml.nimble index ef79830..ab57634 100644 --- a/Nim/NimQml/NimQml.nimble +++ b/Nim/NimQml/NimQml.nimble @@ -1,6 +1,6 @@ [Package] name = "NimQml" -version = "0.2.0" +version = "0.3.0" author = "Filippo Cucchetto, Will Szumski" description = "QML bindings for Nimrod" license = "GPLv3"