Finish finalizers feature
This commit is contained in:
commit
e8e95acd34
|
@ -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)
|
|
@ -1,5 +1,6 @@
|
|||
#include "DOtherSide.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QtQml/QQmlContext>
|
||||
|
@ -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<QVariant*>(other);
|
||||
*newQVariant = *otherQVariant;
|
||||
*vptr = newQVariant;
|
||||
}
|
||||
|
||||
void dos_qvariant_create_qobject(void **vptr, void* value)
|
||||
{
|
||||
auto qobject = reinterpret_cast<QObject*>(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<QVariant*>(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<QVariant*>(vptr);
|
||||
auto rightQVariant = reinterpret_cast<QVariant*>(other);
|
||||
*leftQVariant = *rightQVariant;
|
||||
}
|
||||
|
||||
void dos_qvariant_toInt(void* vptr, int& value)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(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<QVariant*>(vptr);
|
||||
value = variant->toFloat();
|
||||
}
|
||||
|
||||
void dos_qvariant_toDouble(void* vptr, double& value)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(vptr);
|
||||
value = variant->toDouble();
|
||||
}
|
||||
|
||||
void dos_qvariant_toString(void* vptr, CharPtr& ptr, int& size)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(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<QVariant*>(vptr);
|
||||
*variant = value;
|
||||
}
|
||||
|
||||
void dos_qvariant_setDouble(void* vptr, double value)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(vptr);
|
||||
*variant = value;
|
||||
}
|
||||
|
||||
void dos_qvariant_setString(void* vptr, const char* value)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(vptr);
|
||||
*variant = value;
|
||||
}
|
||||
|
||||
void dos_qvariant_setQObject(void* vptr, void* value)
|
||||
{
|
||||
auto variant = reinterpret_cast<QVariant*>(vptr);
|
||||
auto qobject = reinterpret_cast<QObject*>(value);
|
||||
variant->setValue<QObject*>(qobject);
|
||||
}
|
||||
|
||||
void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback)
|
||||
{
|
||||
auto dynamicQObject = new DynamicQObject();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
add_subdirectory(HelloWorld)
|
||||
add_subdirectory(SimpleData)
|
||||
add_subdirectory(SlotsAndProperties)
|
||||
add_subdirectory(QtObjectMacro)
|
||||
add_subdirectory(QtObjectMacro)
|
||||
add_subdirectory(ContactApp)
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -16,5 +16,6 @@ ApplicationWindow
|
|||
SpinBox { value: qVar1}
|
||||
TextField { text: qVar2}
|
||||
CheckBox { checked: qVar3}
|
||||
SpinBox { value: qVar4; decimals: 1 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
discard()
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.. <params.len:
|
||||
let pType = getArgType params[i]
|
||||
# function that maps Qvariant type to nim type
|
||||
let mapper = nimFromQtVariant[$pType]
|
||||
let argAccess = newNimNode(nnkBracketExpr)
|
||||
.add (ident "args")
|
||||
.add newIntLitNode(i-1)
|
||||
let dot = newDotExpr(argAccess, ident mapper)
|
||||
args.add dot
|
||||
.add (ident "args")
|
||||
.add newIntLitNode(i-1)
|
||||
if $pType == "QVariant":
|
||||
args.add argAccess
|
||||
else:
|
||||
# function that maps QVariant type to nim type
|
||||
let mapper = nimFromQtVariant[$pType]
|
||||
let dot = newDotExpr(argAccess, ident mapper)
|
||||
args.add dot
|
||||
var call = newCall(ident slotName, args)
|
||||
if hasReturn:
|
||||
# eg: args[0].strVal = getName(myQObject)
|
||||
let retType = params[0]
|
||||
let mapper = nimFromQtVariant[$retType]
|
||||
let argAccess = newNimNode(nnkBracketExpr)
|
||||
.add (ident "args")
|
||||
.add newIntLitNode(0)
|
||||
let dot = newDotExpr(argAccess, ident mapper)
|
||||
call = newAssignment(dot, call)
|
||||
if $retType == "QVariant":
|
||||
# eg: args[0].assign(getName(myQObject))
|
||||
let dot = newDotExpr(argAccess, ident "assign")
|
||||
call = newCall(dot, call)
|
||||
else:
|
||||
# eg: args[0].strVal = getName(myQObject)
|
||||
let mapper = nimFromQtVariant[$retType]
|
||||
let dot = newDotExpr(argAccess, ident mapper)
|
||||
call = newAssignment(dot, call)
|
||||
branchStmts.add call
|
||||
ofBranch.add branchStmts
|
||||
caseStmt.add ofBranch
|
||||
|
|
|
@ -1,17 +1,35 @@
|
|||
import tables
|
||||
|
||||
type
|
||||
QVariant* = distinct pointer ## A QVariant
|
||||
QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine
|
||||
RawQVariant = distinct pointer
|
||||
QVariant* = ref object of RootObj ## A QVariant
|
||||
data: RawQVariant
|
||||
deleted: bool
|
||||
|
||||
RawQQmlApplicationEngine = distinct pointer
|
||||
QQmlApplicationEngine* = ref object of RootObj ## A QQmlApplicationEngine
|
||||
data: RawQQmlApplicationEngine
|
||||
deleted: bool
|
||||
|
||||
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
|
||||
data: RawQObject
|
||||
slots: Table[string, cint]
|
||||
signals: Table[string, cint]
|
||||
properties: Table[string, cint]
|
||||
deleted: bool
|
||||
QObject* = ref QObjectObj ## A QObject
|
||||
|
||||
RawQQuickView = distinct pointer
|
||||
QQuickView = ref object of RootObj ## A QQuickView
|
||||
data: RawQQuickView
|
||||
deleted: bool
|
||||
|
||||
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]
|
||||
QObject* = ref QObjectObj
|
||||
QQuickView* = distinct pointer ## A QQuickView
|
||||
|
||||
|
|
Loading…
Reference in New Issue