Finish 0.2.0
This commit is contained in:
commit
fd9b05b904
|
@ -2,12 +2,12 @@
|
||||||
Filippo Cucchetto <filippocucchetto@gmail.com>
|
Filippo Cucchetto <filippocucchetto@gmail.com>
|
||||||
|
|
||||||
Will Szumski <will@cowboycoders.org>
|
Will Szumski <will@cowboycoders.org>
|
||||||
:Version: 0.1.0
|
:Version: 0.2.0
|
||||||
:Date: 2015/01/02
|
:Date: 2015/01/02
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
-----------
|
-----------
|
||||||
The NimQml module add Qt Qml bindings to the Nim programming language
|
The NimQml module adds Qt Qml bindings to the Nim programming language
|
||||||
allowing you to create new modern UI by mixing the Qml declarative syntax
|
allowing you to create new modern UI by mixing the Qml declarative syntax
|
||||||
and the Nim imperative language.
|
and the Nim imperative language.
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ the libDOtherSide exported symbols in Nim
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
At the time of writing the DOtherSide C++ library must be compiled
|
At the time of writing the DOtherSide C++ library must be compiled
|
||||||
installed manually from source.
|
and installed manually from source.
|
||||||
|
|
||||||
First clone the DOtherSide git repo
|
First clone the DOtherSide git repo
|
||||||
::
|
::
|
||||||
|
@ -36,7 +36,7 @@ than you can proceed with the common CMake build steps
|
||||||
cmake ..
|
cmake ..
|
||||||
make
|
make
|
||||||
|
|
||||||
If everything goes correctly you'll have build both
|
If everything goes correctly, you'll have built both
|
||||||
the DOtherSide C++ library and the Nim examples
|
the DOtherSide C++ library and the Nim examples
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
@ -49,7 +49,11 @@ the built Nim example in the following way
|
||||||
export LD_LIBRARY_PATH=path/to/libDOtherSide.so
|
export LD_LIBRARY_PATH=path/to/libDOtherSide.so
|
||||||
./HelloWorld
|
./HelloWorld
|
||||||
|
|
||||||
Given this, you can procede with the installation of the C++ library
|
The DOtherSide project is made of two components
|
||||||
|
1. The DOtherSide C++ lib
|
||||||
|
2. The NimQml module
|
||||||
|
|
||||||
|
You can procede with the installation of the C++ library
|
||||||
in the following way
|
in the following way
|
||||||
::
|
::
|
||||||
cd to/build/dir
|
cd to/build/dir
|
||||||
|
@ -58,12 +62,22 @@ or by manually copying the library in your system lib directory
|
||||||
::
|
::
|
||||||
sudo cp build/dir/path/DOtherSide/libDOtherSide.so /usr/lib
|
sudo cp build/dir/path/DOtherSide/libDOtherSide.so /usr/lib
|
||||||
|
|
||||||
|
For the NimQml module you can use the ``nimble`` package manager
|
||||||
|
::
|
||||||
|
nimble install NimQml
|
||||||
|
|
||||||
|
or
|
||||||
|
::
|
||||||
|
cd to/build/dir/Nim/NimQml
|
||||||
|
nimble install
|
||||||
|
|
||||||
|
|
||||||
Example 1: HelloWorld
|
Example 1: HelloWorld
|
||||||
----------
|
----------
|
||||||
As usual lets start with an HelloWorld example.
|
As usual lets start with an HelloWorld example.
|
||||||
Most of the NimQml projects are made by one or more nim and qml
|
Most of the NimQml projects are made by one or more nim and qml
|
||||||
files. Usually the .nim files contains your app logic and data
|
files. Usually the .nim files contains your app logic and data
|
||||||
layer. The qml files contains the presentation layer and expose
|
layer. The qml files contain the presentation layer and expose
|
||||||
the data in your nim files.
|
the data in your nim files.
|
||||||
|
|
||||||
``Examples/HelloWorld/main.nim``
|
``Examples/HelloWorld/main.nim``
|
||||||
|
@ -87,8 +101,8 @@ Example 2: exposing data to Qml
|
||||||
The previous example shown you how to create a simple application
|
The previous example shown you how to create a simple application
|
||||||
window and how to startup the Qt event loop.
|
window and how to startup the Qt event loop.
|
||||||
|
|
||||||
Is time to explore how to pass to to Qml, but first lets see the
|
It's time to explore how to pass data to Qml, but lets see the
|
||||||
example code:
|
example code first:
|
||||||
|
|
||||||
``Examples/SimpleData/main.nim``
|
``Examples/SimpleData/main.nim``
|
||||||
|
|
||||||
|
@ -100,13 +114,13 @@ example code:
|
||||||
.. code-block:: qml
|
.. code-block:: qml
|
||||||
:file: ../Examples/SimpleData/main.qml
|
:file: ../Examples/SimpleData/main.qml
|
||||||
|
|
||||||
The following example shows how to expose simple data to Qml:
|
The following example shows how to expose simple data types to Qml:
|
||||||
1. Create a QVariant and sets the its internal value.
|
1. Create a QVariant and set its internal value.
|
||||||
2. Create a property in the Qml root context with a given name.
|
2. Create a property in the Qml root context with a given name.
|
||||||
|
|
||||||
Once a a property is set through the ``setContextProperty`` proc its available
|
Once a property is set through the ``setContextProperty`` proc, it's available
|
||||||
globally in all the Qml script loaded by the current engine (see the Qt doc
|
globally in all the Qml script loaded by the current engine (see the official Qt
|
||||||
for more details about engine and context)
|
documentation for more details about the engine and context objects)
|
||||||
|
|
||||||
At the time of writing the QVariant class support the following types:
|
At the time of writing the QVariant class support the following types:
|
||||||
* int
|
* int
|
||||||
|
@ -116,21 +130,21 @@ At the time of writing the QVariant class support the following types:
|
||||||
|
|
||||||
Example 3: exposing complex data and procedures to Qml
|
Example 3: exposing complex data and procedures to Qml
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
As seen by the second example simple data is fine. However most
|
As seen by the second example, simple data is fine. However most
|
||||||
applications need to expose complex data, functions and
|
applications need to expose complex data, functions and
|
||||||
update the view when something change in the data layer.
|
update the view when something changes in the data layer.
|
||||||
This is achieved by creating an object that derives from QObject.
|
This is achieved by creating an object that derives from QObject.
|
||||||
|
|
||||||
A QObject is made of :
|
A QObject is made of :
|
||||||
1. ``Slots``: slots are function that could both be called from the qml engine and connected to Qt signals
|
1. ``Slots``: slots are functions that could be called from the qml engine and/or connected to Qt signals
|
||||||
2. ``Signals``: signals allow the sending of events and be connected to slots
|
2. ``Signals``: signals allow the sending of events and be connected to slots
|
||||||
3. ``Properties``: properties allows the passing of data to
|
3. ``Properties``: properties allow the passing of data to
|
||||||
the Qml view and make it aware of changes in the data layer
|
the Qml view and make it aware of changes in the data layer
|
||||||
|
|
||||||
A QObject property is made of three things:
|
A QObject property is made of three things:
|
||||||
* a read slot, a method that return the current value of the property
|
* a read slot: a method that returns the current value of the property
|
||||||
* a write slot, a method that set the value of the property
|
* a write slot: a method that sets the value of the property
|
||||||
* a notify signal for telling that the current value of the property has been changed
|
* a notify signal: emitted when the current value of the property is changed
|
||||||
|
|
||||||
We'll start by looking at the main.nim file
|
We'll start by looking at the main.nim file
|
||||||
|
|
||||||
|
@ -139,24 +153,25 @@ We'll start by looking at the main.nim file
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
:file: ../Examples/SlotsAndProperties/main.nim
|
:file: ../Examples/SlotsAndProperties/main.nim
|
||||||
|
|
||||||
Here's nothing special happen except:
|
Here, nothing special happens except:
|
||||||
1. The creation of Contact object
|
1. The creation of Contact object
|
||||||
2. The injection of the Contact object to the Qml root context
|
2. The injection of the Contact object to the Qml root context
|
||||||
using the ``setContextProperty`` as seen in the previous
|
using the ``setContextProperty`` as seen in the previous
|
||||||
example
|
example
|
||||||
|
|
||||||
The Qml file is as follow:
|
The Qml file is as follows:
|
||||||
|
|
||||||
``Examples/SlotsAndProperties/main.qml``
|
``Examples/SlotsAndProperties/main.qml``
|
||||||
|
|
||||||
.. code-block:: qml
|
.. code-block:: qml
|
||||||
:file: ../Examples/SlotsAndProperties/main.qml
|
:file: ../Examples/SlotsAndProperties/main.qml
|
||||||
|
|
||||||
The qml is made by a Label, a TextInput and a button.
|
The qml is made up of: a Label, a TextInput widget, and a button.
|
||||||
The label display the contact name and automatically udpates when
|
The label displays the contact name - this automatically updates when
|
||||||
the concat name changes.
|
the contact name changes.
|
||||||
|
|
||||||
The button update the contact name with the TextInput text when clicked.
|
When clicked, the button updates the contact name with the text from
|
||||||
|
the TextInput widget.
|
||||||
|
|
||||||
So where's the magic?
|
So where's the magic?
|
||||||
|
|
||||||
|
@ -167,37 +182,37 @@ The magic is in the Contact.nim file
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
:file: ../Examples/SlotsAndProperties/Contact.nim
|
:file: ../Examples/SlotsAndProperties/Contact.nim
|
||||||
|
|
||||||
What First we declare a QObject subclass and provide a simple
|
First we declare a QObject subclass and provide a simple
|
||||||
new method where:
|
new method where we:
|
||||||
1. invoke the ``create()`` procedure. This invoke the C++ bridge and allocate
|
1. invoke the ``create()`` procedure. This invoke the C++ bridge and allocate
|
||||||
a QObject instance
|
a QObject instance
|
||||||
2. register a slot ``getName`` for reading the Contact name field
|
2. register a slot ``getName`` for reading the Contact name field
|
||||||
3. register a slot `` setName`` for writing the Contact name
|
3. register a slot ``setName`` for writing the Contact name
|
||||||
4. register a signal ``nameChanged`` for notify the contact name changes
|
4. register a signal ``nameChanged`` for notify the contact name changes
|
||||||
5. register a property called ``name`` of type ``QString`` with the given
|
5. register a property called ``name`` of type ``QString`` with the given
|
||||||
read, write slots and notify signal
|
read, write slots and notify signal
|
||||||
|
|
||||||
The two slots method implementation are trivial and consist in standard
|
Looking at the ``getName`` and ``setName`` methods, you can see that slots, as defined in Nim,
|
||||||
nim methods. However ``setName`` slot method shows how to emit a signal
|
are nothing more than standard methods. The method corresponding to the ``setName`` slot
|
||||||
by using the ``emit`` method.
|
demonstrates how to use the ``emit`` method to emit a signal.
|
||||||
|
|
||||||
The last thing to condider is the override of the ``onSlotCalled`` method.
|
The last thing to consider is the override of the ``onSlotCalled`` method.
|
||||||
This method is called by the NimQml library when an invokation occur from
|
This method is called by the NimQml library when an invocation occurs from
|
||||||
the Qml side for one of the QObject slot.
|
the Qml side for one of the slots belonging to the QObject.
|
||||||
The usual implementation for the onSlotCalled method consists in a
|
The usual implementation for the onSlotCalled method consists of a
|
||||||
switch statement that forward the arguments to the correct slot.
|
switch statement that forwards the arguments to the correct slot.
|
||||||
If the invoked slot has a return value this is always in the index position
|
If the invoked slot has a return value, this is always in the index position
|
||||||
0 of the args array.
|
0 of the args array.
|
||||||
|
|
||||||
|
|
||||||
Example 4: QtObject macro
|
Example 4: QtObject macro
|
||||||
-------------------------
|
-------------------------
|
||||||
The previous example shows how to create simple QObject however writing
|
The previous example shows how to create a simple QObject, however writing
|
||||||
all those ``register`` procs and writing the ``onSlotCalled`` method
|
all those ``register`` procs and writing the ``onSlotCalled`` method
|
||||||
become boring pretty soon.
|
becomes boring pretty soon.
|
||||||
|
|
||||||
Furthermore all this information can be automatically generated.
|
Furthermore all this information can be automatically generated.
|
||||||
For this purpose you can import the NimQmlMacros module that provide
|
For this purpose you can import the NimQmlMacros module that provides
|
||||||
the QtObject macro.
|
the QtObject macro.
|
||||||
|
|
||||||
Let's begin as usual with both the main.nim and main.qml files
|
Let's begin as usual with both the main.nim and main.qml files
|
||||||
|
@ -213,8 +228,8 @@ Let's begin as usual with both the main.nim and main.qml files
|
||||||
.. code-block:: qml
|
.. code-block:: qml
|
||||||
:file: ../Examples/QtObjectMacro/main.qml
|
:file: ../Examples/QtObjectMacro/main.qml
|
||||||
|
|
||||||
Nothing new in both the ``main.nim`` and ``main.qml`` in respect to
|
Nothing is new in both the ``main.nim`` and ``main.qml`` with respect to
|
||||||
the previous example. What changed is the Contact object
|
the previous example. What changed is the Contact object:
|
||||||
|
|
||||||
``Examples/QtObjectMacro/Contact.nim``
|
``Examples/QtObjectMacro/Contact.nim``
|
||||||
|
|
||||||
|
@ -223,12 +238,12 @@ the previous example. What changed is the Contact object
|
||||||
|
|
||||||
In details:
|
In details:
|
||||||
1. Each QObject is defined inside the QtObject macro
|
1. Each QObject is defined inside the QtObject macro
|
||||||
2. Each slot is annotated with the ``{.slot.}`` macro
|
2. Each slot is annotated with the ``{.slot.}`` pragma
|
||||||
3. Each signal is annotated with the ``{.signal.}`` macro
|
3. Each signal is annotated with the ``{.signal.}`` pragma
|
||||||
4. Each property is created with the ``QtProperty`` macro
|
4. Each property is created with the ``QtProperty`` macro
|
||||||
|
|
||||||
The ``QtProperty`` macro has the following syntax
|
The ``QtProperty`` macro has the following syntax
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
QtProperty nameOfProperty of typeOfProperty
|
QtProperty[typeOfProperty] nameOfProperty
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import NimQml, NimQmlMacros
|
import NimQml, NimQmlMacros
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type Contact = ref object of QObject
|
type Contact* = ref object of QObject
|
||||||
m_name: string
|
m_name: string
|
||||||
|
|
||||||
template newContact*(): Contact =
|
template newContact*(): Contact =
|
||||||
|
@ -21,7 +21,7 @@ QtObject:
|
||||||
contact.m_name = name
|
contact.m_name = name
|
||||||
contact.nameChanged()
|
contact.nameChanged()
|
||||||
|
|
||||||
QtProperty name of string:
|
QtProperty[string] name:
|
||||||
read = getName
|
read = getName
|
||||||
write = setName
|
write = setName
|
||||||
notify = nameChanged
|
notify = nameChanged
|
|
@ -1,7 +1,7 @@
|
||||||
[Package]
|
[Package]
|
||||||
name = "NimQml"
|
name = "NimQml"
|
||||||
version = "0.01"
|
version = "0.2.0"
|
||||||
author = "Filippo Cucchetto"
|
author = "Filippo Cucchetto, Will Szumski"
|
||||||
description = "QML bindings for Nimrod"
|
description = "QML bindings for Nimrod"
|
||||||
license = "GPLv3"
|
license = "GPLv3"
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ let nimFromQtVariant {.compileTime.} = {
|
||||||
|
|
||||||
let nim2QtMeta {.compileTime.} = {
|
let nim2QtMeta {.compileTime.} = {
|
||||||
"bool": "Bool",
|
"bool": "Bool",
|
||||||
"int " : "Int",
|
"int" : "Int",
|
||||||
"string" : "QString",
|
"string" : "QString",
|
||||||
"pointer" : "VoidStar",
|
"pointer" : "VoidStar",
|
||||||
"QVariant": "QVariant",
|
"QVariant": "QVariant",
|
||||||
|
@ -91,7 +91,8 @@ proc newTemplate*(name = newEmptyNode();
|
||||||
newEmptyNode(),
|
newEmptyNode(),
|
||||||
body)
|
body)
|
||||||
|
|
||||||
template declareSuperTemplate*(parent: typedesc, typ: typedesc): typedesc =
|
#FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874
|
||||||
|
template declareSuperTemplate*(parent: expr, typ: expr): stmt =
|
||||||
template superType*(ofType: typedesc[typ]): typedesc[parent] =
|
template superType*(ofType: typedesc[typ]): typedesc[parent] =
|
||||||
parent
|
parent
|
||||||
|
|
||||||
|
@ -108,6 +109,34 @@ proc getTypeName*(a: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
elif testee[0].kind in {nnkPostfix}:
|
elif testee[0].kind in {nnkPostfix}:
|
||||||
return testee[0][1]
|
return testee[0][1]
|
||||||
|
|
||||||
|
proc isExported(def: PNimrodNode): bool {.compileTime.} =
|
||||||
|
## given a type definition, ``typedef``, determines whether or
|
||||||
|
## not the type is exported with a '*'
|
||||||
|
assert def.kind in {nnkTypeDef, nnkProcDef, nnkMethodDef, nnkTemplateDef},
|
||||||
|
"unsupported type: " & $def.kind
|
||||||
|
if def[0].kind == nnkPostfix:
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc exportDef(def: PNimrodNode) {.compileTime.} =
|
||||||
|
## Exports exportable definitions. Currently only supports
|
||||||
|
## templates, methods and procedures and types.
|
||||||
|
if def.kind in {nnkProcDef, nnkMethodDef, nnkTemplateDef, nnkTypeDef}:
|
||||||
|
if def.isExported:
|
||||||
|
return
|
||||||
|
def[0] = postfix(def[0], "*")
|
||||||
|
else:
|
||||||
|
error("node: " & $def.kind & " not supported")
|
||||||
|
|
||||||
|
proc unexportDef(def: PNimrodNode) {.compileTime.} =
|
||||||
|
## unexports exportable definitions. Currently only supports
|
||||||
|
## templates, methods and procedures and types.
|
||||||
|
if def.kind in {nnkProcDef, nnkMethodDef, nnkTemplateDef, nnkTypeDef}:
|
||||||
|
if not def.isExported:
|
||||||
|
return
|
||||||
|
def[0] = ident unpackPostfix(def[0])[1]
|
||||||
|
else:
|
||||||
|
error("node: " & $def.kind & " not supported")
|
||||||
|
|
||||||
proc genSuperTemplate*(typeDecl: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc genSuperTemplate*(typeDecl: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## generates a template, with name: superType, that returns the super type
|
## generates a template, with name: superType, that returns the super type
|
||||||
## of the object defined in the type defintion, ``typeDecl``. ``typeDecl``
|
## of the object defined in the type defintion, ``typeDecl``. ``typeDecl``
|
||||||
|
@ -120,7 +149,11 @@ proc genSuperTemplate*(typeDecl: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
let superType = if inheritStmt[0].kind == nnkIdent: inheritStmt[0]
|
let superType = if inheritStmt[0].kind == nnkIdent: inheritStmt[0]
|
||||||
else: inheritStmt[0].getNodeOf(nnkIdent)
|
else: inheritStmt[0].getNodeOf(nnkIdent)
|
||||||
let superTemplate = getAst declareSuperTemplate(superType, typeName)
|
let superTemplate = getAst declareSuperTemplate(superType, typeName)
|
||||||
return superTemplate[0]
|
result = superTemplate[0]
|
||||||
|
if typeDecl.isExported():
|
||||||
|
result.exportDef()
|
||||||
|
else:
|
||||||
|
result.unexportDef()
|
||||||
|
|
||||||
proc getSuperType*(typeDecl: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc getSuperType*(typeDecl: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## returns ast containing superType info, may not be an ident if generic
|
## returns ast containing superType info, may not be an ident if generic
|
||||||
|
@ -192,11 +225,13 @@ proc addSignalBody(signal: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
args.add getArgName params[i]
|
args.add getArgName params[i]
|
||||||
result.add newCall("emit", args)
|
result.add newCall("emit", args)
|
||||||
|
|
||||||
template declareOnSlotCalled(typ: typedesc): stmt =
|
#FIXME: changed typ from typedesc to expr to workaround Nim issue #1874
|
||||||
|
template declareOnSlotCalled(typ: expr): stmt =
|
||||||
method onSlotCalled(myQObject: typ, slotName: string, args: openarray[QVariant]) =
|
method onSlotCalled(myQObject: typ, slotName: string, args: openarray[QVariant]) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
template prototypeCreate(typ: typedesc): stmt =
|
#FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874
|
||||||
|
template prototypeCreate(typ: expr): stmt =
|
||||||
template create*(myQObject: var typ) =
|
template create*(myQObject: var typ) =
|
||||||
var super = (typ.superType())(myQObject)
|
var super = (typ.superType())(myQObject)
|
||||||
procCall create(super)
|
procCall create(super)
|
||||||
|
@ -269,9 +304,10 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
||||||
#let superName = if superType.kind == nnkIdent: superType
|
#let superName = if superType.kind == nnkIdent: superType
|
||||||
# else: superType.getNodeOf(nnkIdent)
|
# else: superType.getNodeOf(nnkIdent)
|
||||||
if typ != nil:
|
if typ != nil:
|
||||||
error("only support one type declaration")
|
error("you may not define more than one type " &
|
||||||
|
"within the code block passed to this macro")
|
||||||
else: # without this else, it fails to compile
|
else: # without this else, it fails to compile
|
||||||
typ = typeDecl.getTypeName
|
typ = typeDecl
|
||||||
result.add it
|
result.add it
|
||||||
result.add genSuperTemplate(typeDecl)
|
result.add genSuperTemplate(typeDecl)
|
||||||
elif it.kind == nnkMethodDef:
|
elif it.kind == nnkMethodDef:
|
||||||
|
@ -291,7 +327,13 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
||||||
elif it.kind == nnkProcDef:
|
elif it.kind == nnkProcDef:
|
||||||
userDefined.add it
|
userDefined.add it
|
||||||
elif it.kind == nnkCommand:
|
elif it.kind == nnkCommand:
|
||||||
let cmdIdent = it[0]
|
let bracket = it[0]
|
||||||
|
if bracket.kind != nnkBracketExpr:
|
||||||
|
error("do not know how to handle: \n" & repr(it))
|
||||||
|
# BracketExpr
|
||||||
|
# Ident !"QtProperty"
|
||||||
|
# Ident !"string"
|
||||||
|
let cmdIdent = bracket[0]
|
||||||
if cmdIdent == nil or cmdIdent.kind != nnkIdent or
|
if cmdIdent == nil or cmdIdent.kind != nnkIdent or
|
||||||
($cmdIdent).toLower() != "qtproperty":
|
($cmdIdent).toLower() != "qtproperty":
|
||||||
error("do not know how to handle: \n" & repr(it))
|
error("do not know how to handle: \n" & repr(it))
|
||||||
|
@ -299,9 +341,12 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
||||||
else:
|
else:
|
||||||
# everything else should pass through unchanged
|
# everything else should pass through unchanged
|
||||||
result.add it
|
result.add it
|
||||||
|
if typ == nil:
|
||||||
|
error("you must declare an object that inherits from QObject")
|
||||||
|
let typeName = typ.getTypeName()
|
||||||
|
|
||||||
## define onSlotCalled
|
## define onSlotCalled
|
||||||
var slotProto = (getAst declareOnSlotCalled(typ))[0]
|
var slotProto = (getAst declareOnSlotCalled(typeName))[0]
|
||||||
var caseStmt = newNimNode(nnkCaseStmt)
|
var caseStmt = newNimNode(nnkCaseStmt)
|
||||||
caseStmt.add ident("slotName")
|
caseStmt.add ident("slotName")
|
||||||
for slot in slots:
|
for slot in slots:
|
||||||
|
@ -344,9 +389,13 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
||||||
result.add slotProto
|
result.add slotProto
|
||||||
|
|
||||||
# generate create method
|
# generate create method
|
||||||
var createProto = (getAst prototypeCreate(typ))[0]
|
var createProto = (getAst prototypeCreate(typeName))[0]
|
||||||
# the template creates loads of openSyms - replace these with idents
|
# the template creates loads of openSyms - replace these with idents
|
||||||
createProto = doRemoveOpenSym(createProto)
|
createProto = doRemoveOpenSym(createProto)
|
||||||
|
if typ.isExported:
|
||||||
|
createProto.exportDef()
|
||||||
|
else:
|
||||||
|
createProto.unexportDef()
|
||||||
var createBody = createProto.templateBody
|
var createBody = createProto.templateBody
|
||||||
for slot in slots:
|
for slot in slots:
|
||||||
let params = slot.params
|
let params = slot.params
|
||||||
|
@ -363,19 +412,19 @@ macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
||||||
let call = newCall(regSigDot, newLit name, argTypesArray)
|
let call = newCall(regSigDot, newLit name, argTypesArray)
|
||||||
createBody.add call
|
createBody.add call
|
||||||
for property in properties:
|
for property in properties:
|
||||||
#echo treeRepr property
|
let bracket = property[0]
|
||||||
let infix = property[1]
|
expectKind bracket, nnkBracketExpr
|
||||||
expectKind infix, nnkInfix
|
#Command
|
||||||
# Infix
|
# BracketExpr
|
||||||
# Ident !"of"
|
# Ident !"QtProperty"
|
||||||
# Ident !"name"
|
|
||||||
# Ident !"string"
|
# Ident !"string"
|
||||||
|
# Ident !"name"
|
||||||
let nimPropType = infix[2]
|
# StmtList
|
||||||
|
let nimPropType = bracket[1]
|
||||||
let qtPropMeta = nim2QtMeta[$nimPropType]
|
let qtPropMeta = nim2QtMeta[$nimPropType]
|
||||||
if qtPropMeta == nil: error($nimPropType & " not supported")
|
if qtPropMeta == nil: error($nimPropType & " not supported")
|
||||||
let metaDot = newDotExpr(ident "QMetaType", ident qtPropMeta)
|
let metaDot = newDotExpr(ident "QMetaType", ident qtPropMeta)
|
||||||
let propertyName = infix[1]
|
let propertyName = property[1]
|
||||||
var read, write, notify: PNimrodNode
|
var read, write, notify: PNimrodNode
|
||||||
let stmtList = property[2]
|
let stmtList = property[2]
|
||||||
# fields
|
# fields
|
||||||
|
|
|
@ -4,6 +4,13 @@ THIS IS UNSTABLE AND ALPHA SOFTWARE
|
||||||
## Description
|
## Description
|
||||||
Qml bindings for both D and Nim programming languages
|
Qml bindings for both D and Nim programming languages
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
The documentation for the Nim programming language can be
|
||||||
|
read [here](http://filcuc.github.io/DOtherSide/ "").
|
||||||
|
|
||||||
|
For the D programming language is an on going project
|
||||||
|
and pull request are accepted.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
You need the following software:
|
You need the following software:
|
||||||
* Qt 5.3
|
* Qt 5.3
|
||||||
|
|
Loading…
Reference in New Issue