From 685236d11e910c16d7729dbee283549e80c1014a Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Thu, 8 Jan 2015 23:34:17 +0100 Subject: [PATCH 01/22] 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 02/22] 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 03/22] 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 04/22] 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 05/22] 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 06/22] 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 07/22] 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 08/22] 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 09/22] 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 10/22] 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 11/22] 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 12/22] 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 13/22] 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 14/22] 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 15/22] 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 16/22] 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 17/22] 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 18/22] 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 19/22] 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 20/22] 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 21/22] 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 22/22] 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"