mirror of
https://github.com/status-im/dotherside.git
synced 2025-02-12 04:26:43 +00:00
Initial work for writing a nice initial documentation and improving the examples
This commit is contained in:
parent
fbda8a0618
commit
c6960df455
87
Nim/Docs/NimQml.txt
Normal file
87
Nim/Docs/NimQml.txt
Normal file
@ -0,0 +1,87 @@
|
||||
:Authors:
|
||||
Filippo Cucchetto <filippocucchetto@gmail.com>
|
||||
:Version: 0.1.0
|
||||
:Date: 2015/01/02
|
||||
|
||||
Introduction
|
||||
-----------
|
||||
The NimQml module add Qt Qml bindings to the Nim programming language
|
||||
allowing you to create new modern UI by mixing the Qml declarative syntax
|
||||
and the Nim imperative language.
|
||||
|
||||
The NimQml is made by two components:
|
||||
* The DOtherSide C++ shared library
|
||||
* The NimQml Nim module
|
||||
|
||||
This first component implements the glue code necessary for
|
||||
communicating with the Qt C++ library, the latter module wraps
|
||||
the libDOtherSide exported symbols in Nim
|
||||
|
||||
Building
|
||||
--------
|
||||
At the time of writing the DOtherSide C++ library must be compiled
|
||||
installed manually from source.
|
||||
|
||||
First clone the DOtherSide git repo
|
||||
::
|
||||
git clone https://github.com/filcuc/DOtherSide
|
||||
|
||||
than you can proceed with the common CMake build steps
|
||||
|
||||
::
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
If everything goes correctly you'll have build both
|
||||
the DOtherSide C++ library and the Nim examples
|
||||
|
||||
Installation
|
||||
----------
|
||||
The installation is not mandatory, in fact you could try
|
||||
the built Nim example in the following way
|
||||
::
|
||||
cd path/to/build/dir
|
||||
cd Nim/Examples/HelloWorld
|
||||
export LD_LIBRARY_PATH=path/to/libDOtherSide.so
|
||||
./HelloWorld
|
||||
|
||||
Given this, you can procede with the installation of the C++ library
|
||||
in the following way
|
||||
::
|
||||
cd to/build/dir
|
||||
make install
|
||||
or by manually copying the library in your system lib directory
|
||||
::
|
||||
sudo cp build/dir/path/DOtherSide/libDOtherSide.so /usr/lib
|
||||
|
||||
First example: HelloWorld
|
||||
----------
|
||||
As usual lets start with theHelloWorld example.
|
||||
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
|
||||
layer. The qml files contains the presentation layer and expose
|
||||
the data in your nim files.
|
||||
|
||||
Here's the ``main.nim`` file
|
||||
|
||||
.. code-block:: nim
|
||||
:file: ../Examples/HelloWorld/main.nim
|
||||
|
||||
and here the ``main.qml`` file
|
||||
|
||||
.. code-block:: qml
|
||||
:file: ../Examples/HelloWorld/main.qml
|
||||
|
||||
The following examples show the basic steps of each NimQml app
|
||||
1. Create the QApplication for initializing the Qt runtime
|
||||
2. Create the QQmlApplicationEngine and load your main .qml file
|
||||
3. Call the ``exec`` proc of the QApplication instance for starting
|
||||
the Qt event loop
|
||||
|
||||
Second example: exposing data to Qml
|
||||
------------------------------------
|
||||
|
||||
Third example: databinding
|
||||
--------------------------
|
@ -1 +1,2 @@
|
||||
add_subdirectory(HelloWorld)
|
||||
add_subdirectory(Simple)
|
2
Nim/Examples/HelloWorld/CMakeLists.txt
Normal file
2
Nim/Examples/HelloWorld/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_nim_executable(TARGET HelloWorld SOURCES main.nim PATHS ../../NimQml)
|
19
Nim/Examples/HelloWorld/main.nim
Normal file
19
Nim/Examples/HelloWorld/main.nim
Normal file
@ -0,0 +1,19 @@
|
||||
import NimQml
|
||||
import macros
|
||||
import typeinfo
|
||||
|
||||
proc mainProc() =
|
||||
var app: QApplication
|
||||
app.create()
|
||||
defer: app.delete()
|
||||
|
||||
var engine: QQmlApplicationEngine
|
||||
engine.create()
|
||||
defer: engine.delete()
|
||||
|
||||
engine.load("main.qml")
|
||||
app.exec()
|
||||
|
||||
when isMainModule:
|
||||
mainProc()
|
||||
|
12
Nim/Examples/HelloWorld/main.qml
Normal file
12
Nim/Examples/HelloWorld/main.qml
Normal file
@ -0,0 +1,12 @@
|
||||
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: "Hello World"
|
||||
Component.onCompleted: visible = true
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_nim_executable(TARGET Main SOURCES main.nim PATHS ../../NimQml)
|
||||
add_nim_executable(TARGET Simple SOURCES main.nim PATHS ../../NimQml)
|
@ -1,13 +1,19 @@
|
||||
import NimQmlTypes
|
||||
import tables
|
||||
|
||||
## NimQml aims to provide binding to the QML for the Nim programming language
|
||||
|
||||
export QObject
|
||||
export QApplication
|
||||
export QVariant
|
||||
export QQmlApplicationEngine
|
||||
export QQmlContext
|
||||
|
||||
type QMetaType* {.pure.} = enum
|
||||
type QMetaType* {.pure.} = enum ## \
|
||||
## Qt metatypes values used for specifing the
|
||||
## signals and slots argument and return types.
|
||||
##
|
||||
## This enum mimic the QMetaType::Type C++ enum
|
||||
UnknownType = cint(0),
|
||||
Bool = cint(1),
|
||||
Int = cint(2),
|
||||
@ -50,53 +56,65 @@ proc dos_qvariant_setString(variant: pointer, value: cstring) {.cdecl, dynlib:"l
|
||||
proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc create*(variant: var QVariant) =
|
||||
## Create a new QVariant
|
||||
var data: pointer
|
||||
dos_qvariant_create(data)
|
||||
variant = QVariant(data)
|
||||
|
||||
proc create*(variant: var QVariant, value: cint) =
|
||||
## Create a new QVariant given a cint value
|
||||
var data: pointer
|
||||
dos_qvariant_create_int(data, value)
|
||||
variant = QVariant(data)
|
||||
|
||||
proc create*(variant: var QVariant, value: bool) =
|
||||
## Create a new QVariant given a bool value
|
||||
var data: pointer
|
||||
dos_qvariant_create_bool(data, value)
|
||||
variant = QVariant(data)
|
||||
|
||||
proc create*(variant: var QVariant, value: string) =
|
||||
## Create a new QVariant given a string value
|
||||
var data: pointer
|
||||
dos_qvariant_create_string(data, value)
|
||||
variant = QVariant(data)
|
||||
|
||||
proc create*(variant: var QVariant, value: QObject) =
|
||||
## Create a new QVariant given a QObject
|
||||
var data: pointer
|
||||
dos_qvariant_create_qobject(data, value.data)
|
||||
variant = QVariant(data)
|
||||
|
||||
proc delete*(variant: QVariant) =
|
||||
## Delete a QVariant
|
||||
debugMsg("QVariant", "delete")
|
||||
dos_qvariant_delete(pointer(variant))
|
||||
|
||||
proc isNull*(variant: QVariant): bool =
|
||||
## Return true if the QVariant value is null, false otherwise
|
||||
dos_qvariant_isnull(pointer(variant), result)
|
||||
|
||||
proc intVal*(variant: QVariant): int =
|
||||
## Return the QVariant value as int
|
||||
var rawValue: cint
|
||||
dos_qvariant_toInt(pointer(variant), rawValue)
|
||||
result = cast[int](rawValue)
|
||||
|
||||
proc `intVal=`*(variant: QVariant, value: int) =
|
||||
## Sets the QVariant value int value
|
||||
var rawValue = cast[cint](value)
|
||||
dos_qvariant_setInt(pointer(variant), rawValue)
|
||||
|
||||
proc boolVal*(variant: QVariant): bool =
|
||||
## Return the QVariant value as bool
|
||||
dos_qvariant_toBool(pointer(variant), result)
|
||||
|
||||
proc `boolVal=`*(variant: QVariant, value: bool) =
|
||||
## Sets the QVariant bool value
|
||||
dos_qvariant_setBool(pointer(variant), value)
|
||||
|
||||
proc stringVal*(variant: QVariant): string =
|
||||
## Return the QVariant value as string
|
||||
var rawCString: cstring
|
||||
var rawCStringLength: cint
|
||||
dos_qvariant_toString(pointer(variant), rawCString, rawCStringLength)
|
||||
@ -104,6 +122,7 @@ proc stringVal*(variant: QVariant): string =
|
||||
dos_chararray_delete(rawCString)
|
||||
|
||||
proc `stringVal=`*(variant: QVariant, value: string) =
|
||||
## Sets the QVariant string value
|
||||
dos_qvariant_setString(pointer(variant), value)
|
||||
|
||||
|
||||
@ -114,19 +133,23 @@ proc dos_qqmlapplicationengine_context(engine: pointer, context: var pointer) {.
|
||||
proc dos_qqmlapplicationengine_delete(engine: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc create*(engine: var QQmlApplicationEngine) =
|
||||
## Create an new QQmlApplicationEngine
|
||||
var temp: pointer
|
||||
dos_qqmlapplicationengine_create(temp)
|
||||
engine = QQmlApplicationEngine(temp)
|
||||
|
||||
proc load*(engine: QQmlApplicationEngine, filename: cstring) =
|
||||
## Load the given Qml file
|
||||
dos_qqmlapplicationengine_load(pointer(engine), filename)
|
||||
|
||||
proc rootContext*(engine: QQmlApplicationEngine): QQmlContext =
|
||||
## Return the engine root context
|
||||
var context: pointer
|
||||
dos_qqmlapplicationengine_context(pointer(engine), context)
|
||||
result = cast[QQmlContext](context)
|
||||
|
||||
proc delete*(engine: QQmlApplicationEngine) =
|
||||
## Delete the given QQmlApplicationEngine
|
||||
debugMsg("QQmlApplicationEngine", "delete")
|
||||
dos_qqmlapplicationengine_delete(pointer(engine))
|
||||
|
||||
@ -134,6 +157,7 @@ proc delete*(engine: QQmlApplicationEngine) =
|
||||
proc dos_qqmlcontext_setcontextproperty(context: pointer, propertyName: cstring, propertyValue: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc setContextProperty*(context: QQmlContext, propertyName: string, propertyValue: QVariant) =
|
||||
## Sets a new property with the given value
|
||||
dos_qqmlcontext_setcontextproperty(pointer(context), propertyName, pointer(propertyValue))
|
||||
|
||||
# QApplication
|
||||
@ -142,21 +166,31 @@ proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc create*(application: QApplication) =
|
||||
debugMsg("QApplication", "create")
|
||||
## Create a new QApplication
|
||||
dos_qguiapplication_create()
|
||||
|
||||
proc exec*(application: QApplication) =
|
||||
debugMsg("QApplication", "exec")
|
||||
## Start the Qt event loop
|
||||
dos_qguiapplication_exec()
|
||||
|
||||
proc delete*(application: QApplication) =
|
||||
debugMsg("QApplication", "delete")
|
||||
## Delete the given QApplication
|
||||
dos_qguiapplication_delete()
|
||||
|
||||
# QObject
|
||||
type QVariantArray {.unchecked.} = array[0..0, QVariant]
|
||||
type QVariantArrayPtr = ptr QVariantArray
|
||||
|
||||
proc toVariantSeq(args: QVariantArrayPtr, numArgs: cint): seq[QVariant] =
|
||||
result = @[]
|
||||
for i in 0..numArgs-1:
|
||||
result.add(args[i])
|
||||
|
||||
proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] =
|
||||
result = @[]
|
||||
for metaType in metaTypes:
|
||||
result.add(cint(metaType))
|
||||
|
||||
proc dos_qobject_create(qobject: var pointer, nimobject: pointer, qobjectCallback: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qobject_delete(qobject: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qobject_slot_create(qobject: pointer, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
@ -164,40 +198,31 @@ proc dos_qobject_signal_create(qobject: pointer, signalName: cstring, argumentsC
|
||||
proc dos_qobject_signal_emit(qobject: pointer, signalName: cstring, argumentsCount: cint, arguments: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qobject_property_create(qobject: pointer, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVariant]) =
|
||||
debugMsg("QObject", "onSlotCalled", "begin")
|
||||
debugMsg("QObject", "onSlotCalled", "end")
|
||||
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 toVariantSeq(args: QVariantArrayPtr, numArgs: cint): seq[QVariant] =
|
||||
result = @[]
|
||||
for i in 0..numArgs-1:
|
||||
result.add(args[i])
|
||||
|
||||
proc qobjectCallback(nimobject: pointer, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.exportc.} =
|
||||
debugMsg("QObject", "qobjectCallback", "begin")
|
||||
proc qobjectCallback(nimobject: pointer, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.exportc.} =
|
||||
var nimQObjectCasted = cast[ptr QObject](nimobject)
|
||||
# forward to the QObject subtype instance
|
||||
nimQObjectCasted[].onSlotCalled(slotName.stringVal, arguments.toVariantSeq(numArguments))
|
||||
debugMsg("QObject", "qobjectCallback", "end")
|
||||
|
||||
proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] =
|
||||
result = @[]
|
||||
for metaType in metaTypes:
|
||||
result.add(cint(metaType))
|
||||
|
||||
proc create*(qobject: var QObject) =
|
||||
## Create a new QObject
|
||||
qobject.name = "QObject"
|
||||
qobject.slots = initTable[string,cint]()
|
||||
qobject.signals = initTable[string, cint]()
|
||||
dos_qobject_create(qobject.data, addr(qobject), qobjectCallback)
|
||||
|
||||
proc delete*(qobject: QObject) =
|
||||
debugMsg("QObject", "delete")
|
||||
## Delete the given QObject
|
||||
dos_qobject_delete(qobject.data)
|
||||
|
||||
proc registerSlot*(qobject: var QObject,
|
||||
slotName: string,
|
||||
metaTypes: openarray[QMetaType]) =
|
||||
## Register a slot in the QObject with the given name and signature
|
||||
# Copy the metatypes array
|
||||
var copy = toCIntSeq(metatypes)
|
||||
var index: cint
|
||||
@ -207,6 +232,7 @@ proc registerSlot*(qobject: var QObject,
|
||||
proc registerSignal*(qobject: var QObject,
|
||||
signalName: string,
|
||||
metatypes: openarray[QMetaType]) =
|
||||
## Register a signal in the QObject with the given name and signature
|
||||
var index: cint
|
||||
if metatypes.len > 0:
|
||||
var copy = toCIntSeq(metatypes)
|
||||
@ -220,10 +246,12 @@ proc registerProperty*(qobject: var QObject,
|
||||
propertyType: QMetaType,
|
||||
readSlot: string,
|
||||
writeSlot: string,
|
||||
notifySignal: string) =
|
||||
notifySignal: string) =
|
||||
## Register a property in the QObject with the given name and type.
|
||||
dos_qobject_property_create(qobject.data, propertyName, cast[cint](propertyType), readSlot, writeSlot, notifySignal)
|
||||
|
||||
proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) =
|
||||
## Emit the signal with the given name and values
|
||||
if args.len > 0:
|
||||
var copy: seq[QVariant]
|
||||
for i in 0..args.len-1:
|
||||
@ -239,23 +267,27 @@ proc dos_qquickview_show(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", impo
|
||||
proc dos_qquickview_source(view: pointer, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
proc dos_qquickview_set_source(view: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.}
|
||||
|
||||
proc create(view: var QQuickView) =
|
||||
proc create(view: var QQuickView) =
|
||||
## Create a new QQuickView
|
||||
var temp: pointer
|
||||
dos_qquickview_create(temp)
|
||||
view = QQuickView(temp)
|
||||
|
||||
proc source(view: QQuickView): cstring =
|
||||
## Return the source Qml file loaded by the view
|
||||
var length: int
|
||||
dos_qquickview_source(pointer(view), result, length)
|
||||
|
||||
proc `source=`(view: QQuickView, filename: cstring) =
|
||||
## Sets the source Qml file laoded by the view
|
||||
dos_qquickview_set_source(pointer(view), filename)
|
||||
|
||||
proc show(view: QQuickView) =
|
||||
## Sets the view visible
|
||||
dos_qquickview_show(pointer(view))
|
||||
|
||||
proc delete(view: QQuickView) =
|
||||
debugMsg("QQuickView", "delete")
|
||||
proc delete(view: QQuickView) =
|
||||
## Delete the given QQuickView
|
||||
dos_qquickview_delete(pointer(view))
|
||||
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import tables
|
||||
|
||||
type
|
||||
QVariant* = distinct pointer
|
||||
QQmlApplicationEngine* = distinct pointer
|
||||
QQmlContext* = distinct pointer
|
||||
QApplication* = distinct pointer
|
||||
QObject* {.inheritable.} = ref object of RootObj
|
||||
QVariant* = distinct pointer ## A QVariant
|
||||
QQmlApplicationEngine* = distinct pointer ## A QQmlApplicationEngine
|
||||
QQmlContext* = distinct pointer ## A QQmlContext
|
||||
QApplication* = distinct pointer ## A QApplication
|
||||
QObject* {.inheritable.} = ref object of RootObj ## A QObject
|
||||
name*: string
|
||||
data*: pointer
|
||||
slots*: Table[string, cint]
|
||||
signals*: Table[string, cint]
|
||||
properties*: Table[string, cint]
|
||||
QQuickView* = distinct pointer
|
||||
QQuickView* = distinct pointer ## A QQuickView
|
||||
|
@ -23,7 +23,7 @@ function(add_nim_executable )
|
||||
|
||||
# add target to trigger the nimrod compiler
|
||||
add_custom_target(
|
||||
nim ALL
|
||||
${ARGS_TARGET} ALL
|
||||
COMMAND
|
||||
${NIM_EXECUTABLE} "c" ${in_paths} "--nimcache:" ${DIRECTORY} "--out:" ${nim_target} ${in_files}
|
||||
DEPENDS
|
||||
|
Loading…
x
Reference in New Issue
Block a user