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 8bbbc3d..7c0f32a 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -1,5 +1,6 @@ #include "DOtherSide.h" +#include #include #include #include @@ -34,6 +35,34 @@ void dos_qguiapplication_exec() qApp->exec(); } +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(); @@ -146,6 +175,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); @@ -154,6 +191,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); @@ -166,6 +213,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); @@ -178,6 +232,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); @@ -196,12 +262,31 @@ 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); *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 cb1abe7..5b66cc5 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -13,9 +13,16 @@ extern "C" // QGuiApplication void dos_qguiapplication_create(); void dos_qguiapplication_exec(); + void dos_qguiapplication_quit(); void dos_qguiapplication_delete(); - /// QQmlApplicationEngine + // QApplication + void dos_qapplication_create(); + void dos_qapplication_exec(); + void dos_qapplication_quit(); + void dos_qapplication_delete(); + + // QQmlApplicationEngine void dos_qqmlapplicationengine_create(void** vptr); void dos_qqmlapplicationengine_load(void* vptr, const char* filename); void dos_qqmlapplicationengine_context(void* vptr, void** context); @@ -43,14 +50,23 @@ 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_create_float(void **vptr, float value); + void dos_qvariant_create_double(void **vptr, double value); void dos_qvariant_toInt(void* vptr, int& value); void dos_qvariant_setInt(void* vptr, int value); void dos_qvariant_toBool(void* vptr, bool& value); void dos_qvariant_setBool(void* vptr, bool value); + void dos_qvariant_toFloat(void* vptr, float& value); + void dos_qvariant_setFloat(void* vptr, float value); + void dos_qvariant_toDouble(void* vptr, double& value); + void dos_qvariant_setDouble(void* vptr, double value); void dos_qvariant_toString(void* vptr, CharPtr& ptr, int& size); void dos_qvariant_setString(void* vptr, const char* value); + void dos_qvariant_setQObject(void* vptr, void* value); void dos_qvariant_isnull(void *vptr, bool& isNull); void dos_qvariant_delete(void *vptr); + void dos_qvariant_assign(void* vptr, void* other); // QObject void dos_qobject_create(void **vptr, 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() 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..ed1242d --- /dev/null +++ b/Nim/Examples/ContactApp/ApplicationLogic.nim @@ -0,0 +1,33 @@ +import NimQml, NimQmlMacros, ContactList + +QtObject: + type ApplicationLogic* = ref object of QObject + contactList: ContactList + app: QApplication + + proc delete*(self: ApplicationLogic) = + let qobject = self.QObject + qobject.delete + self.contactList.delete + + proc newApplicationLogic*(app: QApplication): ApplicationLogic = + new(result) + 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 diff --git a/Nim/Examples/ContactApp/CMakeLists.txt b/Nim/Examples/ContactApp/CMakeLists.txt new file mode 100644 index 0000000..a6c189e --- /dev/null +++ b/Nim/Examples/ContactApp/CMakeLists.txt @@ -0,0 +1,2 @@ +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.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..ec5f2b2 --- /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) + result.name = "" + result.create + + method firstName*(self: Contact): string {.slot.} = + result = self.name + + method firstNameChanged*(self: Contact) {.signal.} + + method setFirstName(self: Contact, name: string) {.slot.} = + if self.name != name: + self.name = name + self.firstNameChanged() + + proc `firstName=`*(self: Contact, name: string) = self.setFirstName(name) + + QtProperty[string] firstName: + read = firstName + write = setFirstName + notify = firstNameChanged + + 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..6b0dc04 --- /dev/null +++ b/Nim/Examples/ContactApp/ContactList.nim @@ -0,0 +1,44 @@ +## 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 + for contact in self.contacts: + contact.delete + self.contacts = @[] + + proc newContactList*(): ContactList = + new(result) + result.contacts = @[] + result.create() + + method getCount(self: ContactList): int {.slot.} = + return self.contacts.len + + method countChanged(self: ContactList) {.signal.} + + method add*(self: ContactList, name: string, surname: string) {.slot.} = + let contact = newContact() + contact.firstName = name + contact.surname = surname + self.contacts.add(contact) + self.countChanged() + + method get*(self: ContactList, index: int): QObject {.slot.} = + if index < 0 or index >= self.contacts.len: + return nil + result = self.contacts[index].QObject + + method del*(self: ContactList, index: int) {.slot.} = + self.contacts.del(index) + self.countChanged() + + QtProperty[int] count: + read = getCount + notify = countChanged diff --git a/Nim/Examples/ContactApp/main.nim b/Nim/Examples/ContactApp/main.nim new file mode 100644 index 0000000..d5761fb --- /dev/null +++ b/Nim/Examples/ContactApp/main.nim @@ -0,0 +1,17 @@ +import NimQml, ApplicationLogic + +proc mainProc() = + let app = newQApplication() + defer: app.delete + let logic = newApplicationLogic(app) + defer: logic.delete + let engine = newQQmlApplicationEngine() + defer: engine.delete + let logicVariant = newQVariant(logic) + defer: logicVariant.delete + engine.rootContext.setContextProperty("logic", logicVariant) + 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..e4fe7e5 --- /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.firstName } + 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) } + } + } +} diff --git a/Nim/Examples/HelloWorld/main.nim b/Nim/Examples/HelloWorld/main.nim index 897a160..1936404 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") @@ -16,4 +14,5 @@ proc mainProc() = when isMainModule: mainProc() + GC_fullcollect() diff --git a/Nim/Examples/QtObjectMacro/Contact.nim b/Nim/Examples/QtObjectMacro/Contact.nim index 7b9c79e..380d18b 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..784a67d 100644 --- a/Nim/Examples/QtObjectMacro/main.nim +++ b/Nim/Examples/QtObjectMacro/main.nim @@ -2,26 +2,22 @@ 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() when isMainModule: mainProc() - + GC_fullcollect() diff --git a/Nim/Examples/SimpleData/main.nim b/Nim/Examples/SimpleData/main.nim index 01f5eb9..d20e464 100644 --- a/Nim/Examples/SimpleData/main.nim +++ b/Nim/Examples/SimpleData/main.nim @@ -3,36 +3,32 @@ 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: 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 + + var qVar4 = newQVariant(3.5.float) + defer: qVar4.delete() engine.rootContext.setContextProperty("qVar1", qVar1) engine.rootContext.setContextProperty("qVar2", qVar2) - engine.rootContext.setContextProperty("qVar3", qVar2) - + engine.rootContext.setContextProperty("qVar3", qVar3) + engine.rootContext.setContextProperty("qVar4", qVar4) engine.load("main.qml") app.exec() when isMainModule: mainProc() + GC_fullcollect() 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 } } } diff --git a/Nim/Examples/SlotsAndProperties/Contact.nim b/Nim/Examples/SlotsAndProperties/Contact.nim index 797d82c..3310b0b 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..e395a41 100644 --- a/Nim/Examples/SlotsAndProperties/main.nim +++ b/Nim/Examples/SlotsAndProperties/main.nim @@ -2,26 +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: 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() when isMainModule: mainProc() + GC_fullcollect() diff --git a/Nim/NimQml/NimQml.nim b/Nim/NimQml/NimQml.nim index 9c008ea..5f20fb3 100644 --- a/Nim/NimQml/NimQml.nim +++ b/Nim/NimQml/NimQml.nim @@ -1,13 +1,14 @@ -import NimQmlTypes -import tables +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 +## +## 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 @@ -19,10 +20,11 @@ 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, QObject]() +var qobjectRegistry = initTable[ptr QObjectObj, bool]() proc debugMsg(message: string) = echo "NimQml: ", message @@ -41,179 +43,372 @@ 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 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: 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.} +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_qvariant_assign(leftValue: RawQVariant, rightValue: RawQVariant) {.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: 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 create*(variant: QVariant, value: RawQVariant) = + ## 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 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) = ## Delete a QVariant - debugMsg("QVariant", "delete") - dos_qvariant_delete(variant) + 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 + newWithCondFinalizer(result, delete) + result.create() + +proc newQVariant*(value: cint): QVariant = + ## Return a new QVariant given a cint + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: bool): QVariant = + ## Return a new QVariant given a bool + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: string): QVariant = + ## Return a new QVariant given a string + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: QObject): QVariant = + ## Return a new QVariant given a QObject + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: RawQVariant): QVariant = + ## Return a new QVariant given a raw QVariant pointer + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: QVariant): QVariant = + ## Return a new QVariant given another QVariant + newWithCondFinalizer(result, delete) + result.create(value) + +proc newQVariant*(value: float): QVariant = + ## Return a new QVariant given a float + newWithCondFinalizer(result, delete) + result.create(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 floatVal*(variant: QVariant): float = + ## Return the QVariant value as float + var rawValue: cfloat + dos_qvariant_toFloat(variant.data, rawValue) + result = rawValue.cfloat + +proc `floatVal=`*(variant: QVariant, value: float) = + ## Sets the QVariant float value + 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.data, rawValue) + result = rawValue + +proc `doubleVal=`*(variant: QVariant, value: cdouble) = + ## Sets the QVariant double value + dos_qvariant_setDouble(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) +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) # 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 + newWithCondFinalizer(result, delete) + result.create() # 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.} -proc dos_qguiapplication_exec() {.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_qapplication_quit() + proc delete*(application: QApplication) = ## Delete the given QApplication - dos_qguiapplication_delete() + if not application.deleted: + debugMsg("QApplication", "delete") + dos_qapplication_delete() + application.deleted = true +proc newQApplication*(): QApplication = + ## Return a new QApplication + newWithCondFinalizer(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 + newWithCondFinalizer(result, delete) + result.create() + # QObject -type QVariantArray {.unchecked.} = array[0..0, QVariant] -type QVariantArrayPtr = ptr QVariantArray +type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant] +type RawQVariantArrayPtr = ptr RawQVariantArray +type RawQVariantSeq = seq[RawQVariant] -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 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 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.} -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 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]) = ## Called from the NimQml bridge when a slot is called from Qml. ## Subclasses can override the given method for handling the slot call discard() -proc qobjectCallback(nimobject: 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 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 - let internalRef = qobject - let qobjectPtr = addr(qobject[]) - qobjectRegistry[qobjectPtr] = internalRef - qobject.name = "QObject" + debugMsg("QObject", "create") + 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 - let qobjectPtr = addr(qobject[]) - qobjectRegistry.del qobjectPtr - dos_qobject_delete(qobject.data) + if not qobject.deleted: + debugMsg("QObject", "delete") + let qobjectPtr = addr(qobject[]) + qobjectRegistry.del qobjectPtr + dos_qobject_delete(qobject.data) + qobject.data = nil.RawQObject + qobject.deleted = true + +proc newQObject*(): QObject = + ## Return a new QObject + newWithCondFinalizer(result, delete) + result.create() proc registerSlot*(qobject: QObject, slotName: string, @@ -244,41 +439,55 @@ 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 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) # 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 + newWithCondFinalizer(result, delete) + result.create() diff --git a/Nim/NimQml/NimQmlMacros.nim b/Nim/NimQml/NimQmlMacros.nim index 40372d7..cd902e0 100644 --- a/Nim/NimQml/NimQmlMacros.nim +++ b/Nim/NimQml/NimQmlMacros.nim @@ -17,6 +17,8 @@ let nimFromQtVariant {.compileTime.} = { "int" : "intVal", "string" : "stringVal", "bool" : "boolVal", + "float" : "floatVal", + "QObject" : "qobjectVal", }.toTable let nim2QtMeta {.compileTime.} = { @@ -24,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 @@ -362,23 +365,31 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} = args.add ident "myQObject" for i in 2..