├── .gitignore ├── LICENSE ├── README.md ├── all.cpp ├── bridge.go ├── cdata ├── cdata.go ├── cdata12.c ├── cdata14_386.s ├── cdata14_amd64.s ├── cdata14_arm.s ├── cdata15_386.s ├── cdata15_amd64.s ├── cdata15_arm.s └── cdata_test.go ├── cmd ├── genqrc │ └── main.go └── ubuntu-touch │ ├── particle.desktop │ └── setup.sh ├── cpp ├── capi.cpp ├── capi.h ├── connector.cpp ├── connector.h ├── goitemmodel.cpp ├── goitemmodel.h ├── goitemmodel_api.cpp ├── goitemmodel_api.h ├── goitemmodel_impl.h ├── govalue.cpp ├── govalue.h ├── govaluetype.cpp ├── govaluetype.h ├── idletimer.cpp ├── mmemwin.cpp ├── moc_all.cpp ├── moc_connector.cpp ├── moc_goitemmodel.cpp ├── moc_govalue.cpp ├── moc_idletimer.cpp ├── private │ ├── qmetaobject_p.h │ ├── qmetaobjectbuilder_p.h │ ├── qobject_p.h │ └── qtheader.h ├── qmodelindex.cpp ├── qmodelindex.h ├── update-moc.sh ├── util.cpp └── util.h ├── cpptest ├── cpptest.cpp ├── cpptest.go ├── cpptest.h ├── moc_testtype.cpp ├── testtype.h └── update-moc.sh ├── datatype.go ├── doc.go ├── examples ├── controls │ ├── .gitignore │ ├── README.md │ ├── basiclayouts │ │ ├── basiclayouts.go │ │ └── main.qml │ ├── gallery │ │ ├── content │ │ │ ├── AboutDialog.qml │ │ │ ├── ChildWindow.qml │ │ │ ├── Controls.qml │ │ │ ├── ImageViewer.qml │ │ │ ├── Layouts.qml │ │ │ ├── ModelView.qml │ │ │ └── Styles.qml │ │ ├── gallery.go │ │ ├── images │ │ │ ├── bubble.png │ │ │ ├── button-pressed.png │ │ │ ├── button.png │ │ │ ├── document-open.png │ │ │ ├── document-open@2x.png │ │ │ ├── document-save-as.png │ │ │ ├── document-save-as@2x.png │ │ │ ├── folder_new.png │ │ │ ├── go-next.png │ │ │ ├── go-previous.png │ │ │ ├── preferences-system.png │ │ │ ├── process-stop.png │ │ │ ├── progress-background.png │ │ │ ├── progress-fill.png │ │ │ ├── slider-handle.png │ │ │ ├── tab.png │ │ │ ├── tab_selected.png │ │ │ ├── textfield.png │ │ │ ├── toplevel_window.png │ │ │ ├── view-refresh.png │ │ │ ├── window-new.png │ │ │ └── window-new@2x.png │ │ └── main.qml │ ├── splitview │ │ ├── main.qml │ │ └── splitview.go │ ├── tableview │ │ ├── images │ │ │ ├── header.png │ │ │ └── selectedrow.png │ │ ├── main.qml │ │ └── tableview.go │ └── touch │ │ ├── content │ │ ├── AndroidDelegate.qml │ │ ├── ButtonPage.qml │ │ ├── ListPage.qml │ │ ├── ProgressBarPage.qml │ │ ├── SliderPage.qml │ │ ├── TabBarPage.qml │ │ └── TextInputPage.qml │ │ ├── images │ │ ├── NOTICE.txt │ │ ├── button_default.png │ │ ├── button_pressed.png │ │ ├── navigation_next_item.png │ │ ├── navigation_previous_item.png │ │ ├── tab_selected.png │ │ ├── tabs_standard.png │ │ ├── textinput.png │ │ └── toolbar.png │ │ ├── main.qml │ │ └── touch.go ├── customtype │ ├── customtype.go │ └── customtype.qml ├── gopher │ ├── gopher.go │ ├── gopher.qml │ ├── mix.qml │ ├── model │ │ ├── README.md │ │ ├── gopher.blend │ │ ├── gopher.mtl │ │ └── gopher.obj │ └── wavefront.go ├── imgprovider │ ├── imgprovider.go │ ├── imgprovider.qml │ └── ubuntu-gopher.png ├── itemmodel │ ├── delegate.go │ └── delegate.qml ├── modelview │ └── delegate │ │ ├── delegate.go │ │ └── delegate.qml ├── painting-es2 │ ├── painting.go │ └── painting.qml ├── painting │ ├── painting.go │ └── painting.qml ├── particle │ ├── main.go │ ├── particle.png │ └── particle.qml ├── qmlscene │ ├── Cell.qml │ ├── qmlscene.go │ ├── tutorial1.qml │ ├── tutorial2.qml │ └── tutorial3.qml ├── qrcpacking │ ├── assets │ │ ├── particle.png │ │ └── particle.qml │ ├── main.go │ └── qrc.go ├── reparent │ ├── base.qml │ ├── rect.qml │ └── reparent.go └── snapweb │ └── snapweb.go ├── gl ├── 1.0 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 1.1 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 1.2 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 1.3 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 1.4 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 1.5 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 2.0 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 2.1 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.0 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.1 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.2compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.2core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.3compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 3.3core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.0compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.0core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.1compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.1core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.2compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.2core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.3compat │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── 4.3core │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── es2 │ ├── funcs.cpp │ ├── funcs.h │ └── gl.go ├── gengl │ ├── Makefile │ ├── funcs.go │ ├── gl.xml │ ├── main.go │ ├── parseqt.go │ └── parseqt.rl └── glbase │ └── glbase.go ├── goitemmodel.go ├── goitemmodelimpls.go ├── gomodelindex.go ├── internal └── util │ └── util.go ├── log.go ├── qimage ├── image.cpp ├── image.h └── qimage.go ├── qml.go ├── qml_test.go ├── qmlcommon.go ├── qmlcontext.go ├── qmlengine.go ├── qmllist.go ├── qmlmap.go ├── qmlobject.go ├── qmltypes.go ├── qmlwindow.go ├── qpainter ├── painter.cpp ├── painter.h └── qpainter.go ├── resources.go ├── static.go ├── stats.go └── testing.go /.gitignore: -------------------------------------------------------------------------------- 1 | examples/qmlscene/qmlscene 2 | examples/snapweb/snapweb 3 | examples/particle/particle 4 | gl/gengl/gengl 5 | *.swp 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QML support for the Go language 2 | 3 | Documentation 4 | ------------- 5 | 6 | The introductory documentation as well as the detailed API documentation is 7 | available at [github.com/limetext/qml-go](http://godoc.org/github.com/limetext/qml-go). 8 | 9 | 10 | Blog posts 11 | ---------- 12 | 13 | Some relevant blog posts: 14 | 15 | * [Announcing qml v1 for Go](http://blog.labix.org/2014/08/13/announcing-qml-v1-for-go) 16 | * [Packing resources into Go qml binaries](http://blog.labix.org/2014/09/26/packing-resources-into-go-qml-binaries) 17 | * [Go qml contest results](http://blog.labix.org/2014/04/25/qml-contest-results) 18 | * [Arbitrary Qt extensions with Go qml](http://blog.labix.org/2014/03/21/arbitrary-qt-extensions-with-go-qml) 19 | * [The new Go qml OpenGL API](http://blog.labix.org/2014/08/29/the-new-go-qml-opengl-api) 20 | * [QML components with Go and OpenGL](http://blog.labix.org/2013/12/23/qml-components-with-go-and-opengl) 21 | 22 | 23 | Videos 24 | ------ 25 | 26 | These introductory videos demonstrate the use of Go QML: 27 | 28 | * [Initial demo and overview](http://youtu.be/FVQlMrPa7lI) 29 | * [Initial demo running on an Ubuntu Touch phone](http://youtu.be/HB-3o8Cysec) 30 | * [Spinning Gopher with Go + QML + OpenGL](http://youtu.be/qkH7_dtOyPk) 31 | * [SameGame QML tutorial in Go](http://youtu.be/z8noX48hiMI) 32 | 33 | 34 | Community 35 | --------- 36 | 37 | Please join the [mailing list](https://groups.google.com/forum/#!forum/go-qml) for 38 | following relevant development news and discussing project details. 39 | 40 | 41 | Installation 42 | ------------ 43 | 44 | To try the alpha release you'll need: 45 | 46 | * Go >= 1.2, for the C++ support of _go build_ 47 | * Qt 5.0.X or 5.1.X with the development files 48 | * The Qt headers qmetaobject_p.h and qmetaobjectbuilder_p.h, for the dynamic meta object support 49 | 50 | See below for more details about getting these requirements installed in different environments and operating systems. 51 | 52 | After the requirements are satisfied, _go get_ should work as usual: 53 | 54 | go get github.com/limetext/qml-go 55 | 56 | 57 | Requirements on Ubuntu 58 | ---------------------- 59 | 60 | If you are using Ubuntu, the [Ubuntu SDK](http://developer.ubuntu.com/get-started/) will take care of the Qt dependencies: 61 | 62 | $ sudo add-apt-repository ppa:ubuntu-sdk-team/ppa 63 | $ sudo apt-get update 64 | $ sudo apt-get install qtdeclarative5-dev qtbase5-private-dev qtdeclarative5-private-dev libqt5opengl5-dev qtdeclarative5-qtquick2-plugin 65 | 66 | and Go >= 1.2 may be installed using [godeb](http://blog.labix.org/2013/06/15/in-flight-deb-packages-of-go): 67 | 68 | $ # Pick the right one for your system: 386 or amd64 69 | $ ARCH=amd64 70 | $ wget -q https://godeb.s3.amazonaws.com/godeb-$ARCH.tar.gz 71 | $ tar xzvf godeb-$ARCH.tar.gz 72 | godeb 73 | $ sudo mv godeb /usr/local/bin 74 | $ godeb install 75 | $ go get github.com/limetext/qml-go 76 | 77 | 78 | Requirements on Ubuntu Touch 79 | ---------------------------- 80 | 81 | After following the [installation instructions](https://wiki.ubuntu.com/Touch/Install) for Ubuntu Touch, 82 | run the following commands to get a working build environment inside the device: 83 | 84 | $ adb shell 85 | # cd /tmp 86 | # wget https://github.com/go-qml/qml/raw/v1/cmd/ubuntu-touch/setup.sh 87 | # /bin/bash setup.sh 88 | # su - phablet 89 | $ 90 | 91 | At the end of setup.sh, the phablet user will have GOPATH=$HOME in the environment, 92 | the qml package will be built, and the particle example will be built and run. For 93 | stopping it from the command line, run as the phablet user: 94 | 95 | $ ubuntu-app-stop gopkg.in.qml.particle-example 96 | 97 | for running it again: 98 | 99 | $ ubuntu-app-launch gopkg.in.qml.particle-example 100 | 101 | These commands depend on the following file, installed by setup.sh: 102 | 103 | ~/.local/share/applications/gopkg.in.qml.particle-example.desktop 104 | 105 | 106 | Requirements on Mac OS X 107 | ------------------------ 108 | 109 | On Mac OS X you'll need QT5. It's easiest to install with Homebrew, a 110 | third-party package management system for OS X. 111 | 112 | Installation instructions for Homebrew are here: 113 | 114 | http://brew.sh/ 115 | 116 | Then, install the qt5 and pkg-config packages: 117 | 118 | $ brew install qt5 pkg-config 119 | 120 | Then, force brew to "link" qt5 (this makes it available under /usr/local): 121 | 122 | $ brew link --force qt5 123 | 124 | And finally, fetch and install go-qml: 125 | 126 | $ go get github.com/limetext/qml-go 127 | 128 | 129 | Requirements on Windows 130 | ----------------------- 131 | 132 | On Windows you'll need the following: 133 | 134 | * [MinGW gcc](http://sourceforge.net/projects/mingw/files/latest/download) 4.8.1 (install mingw-get and install the gcc from within the setup GUI) 135 | * [Qt 5.1.1](http://download.qt-project.org/official_releases/qt/5.1/5.1.1/qt-windows-opensource-5.1.1-mingw48_opengl-x86-offline.exe) for MinGW 4.8 136 | * [Go >= 1.2](http://golang.org/doc/install) 137 | 138 | Then, assuming Qt was installed under `C:\Qt5.1.1\`, set up the following environment variables in the respective configuration: 139 | 140 | CPATH += C:\Qt5.1.1\5.1.1\mingw48_32\include 141 | LIBRARY_PATH += C:\Qt5.1.1\5.1.1\mingw48_32\lib 142 | PATH += C:\Qt5.1.1\5.1.1\mingw48_32\bin 143 | 144 | After reopening the shell for the environment changes to take effect, this should work: 145 | 146 | go get github.com/limetext/qml-go 147 | 148 | 149 | Requirements everywhere else 150 | ---------------------------- 151 | 152 | If your operating system does not offer these dependencies readily, 153 | you may still have success installing [Go >= 1.2](http://golang.org/doc/install) 154 | and [Qt 5.0.2](http://download.qt-project.org/archive/qt/5.0/5.0.2/) 155 | directly from the upstreams. Note that you'll likely have to adapt 156 | environment variables to reflect the custom installation path for 157 | these libraries. See the instructions above for examples. 158 | -------------------------------------------------------------------------------- /all.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "cpp/capi.cpp" 3 | #include "cpp/govalue.cpp" 4 | #include "cpp/govaluetype.cpp" 5 | #include "cpp/goitemmodel.cpp" 6 | #include "cpp/goitemmodel_api.cpp" 7 | #include "cpp/idletimer.cpp" 8 | #include "cpp/connector.cpp" 9 | 10 | #include "cpp/moc_all.cpp" 11 | 12 | #ifdef _WIN32 13 | #include "cpp/mmemwin.cpp" 14 | #endif 15 | -------------------------------------------------------------------------------- /cdata/cdata.go: -------------------------------------------------------------------------------- 1 | // Package cdata supports the implementation of the qml package. 2 | package cdata 3 | 4 | func Ref() uintptr 5 | 6 | func Addrs() (uintptr, uintptr) 7 | -------------------------------------------------------------------------------- /cdata/cdata12.c: -------------------------------------------------------------------------------- 1 | // +build !go1.4 2 | 3 | #include "runtime.h" 4 | 5 | void ·Ref(uintptr ref) { 6 | ref = (uintptr)g->m; 7 | FLUSH(&ref); 8 | } 9 | 10 | void runtime·main(void); 11 | void main·main(void); 12 | 13 | void ·Addrs(uintptr rmain, uintptr mmain) { 14 | rmain = (uintptr)runtime·main; 15 | mmain = (uintptr)main·main; 16 | FLUSH(&rmain); 17 | FLUSH(&mmain); 18 | } 19 | -------------------------------------------------------------------------------- /cdata/cdata14_386.s: -------------------------------------------------------------------------------- 1 | // +build go1.4,!go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$4-4 6 | CALL runtime·acquirem(SB) 7 | MOVL 0(SP), AX 8 | MOVL AX, ret+0(FP) 9 | CALL runtime·releasem(SB) 10 | RET 11 | 12 | TEXT ·Addrs(SB),NOSPLIT,$0-8 13 | MOVL $runtime·main(SB), AX 14 | MOVL AX, ret+0(FP) 15 | MOVL $runtime·main_main(SB), AX 16 | MOVL AX, ret+8(FP) 17 | RET 18 | -------------------------------------------------------------------------------- /cdata/cdata14_amd64.s: -------------------------------------------------------------------------------- 1 | // +build go1.4,!go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$8-8 6 | CALL runtime·acquirem(SB) 7 | MOVQ 0(SP), AX 8 | MOVQ AX, ret+0(FP) 9 | CALL runtime·releasem(SB) 10 | RET 11 | 12 | TEXT ·Addrs(SB),NOSPLIT,$0-16 13 | MOVQ $runtime·main(SB), AX 14 | MOVQ AX, ret+0(FP) 15 | MOVQ $runtime·main_main(SB), AX 16 | MOVQ AX, ret+8(FP) 17 | RET 18 | -------------------------------------------------------------------------------- /cdata/cdata14_arm.s: -------------------------------------------------------------------------------- 1 | // +build go1.4,!go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$4-4 6 | BL runtime·acquirem(SB) 7 | MOVW 4(R13), R0 8 | MOVW R0, ret+0(FP) 9 | MOVW R0, 4(R13) 10 | BL runtime·releasem(SB) 11 | RET 12 | 13 | TEXT ·Addrs(SB),NOSPLIT,$0-8 14 | MOVW $runtime·main(SB), R0 15 | MOVW R0, ret+0(FP) 16 | MOVW $runtime·main_main(SB), R0 17 | MOVW R0, ret+4(FP) 18 | RET 19 | -------------------------------------------------------------------------------- /cdata/cdata15_386.s: -------------------------------------------------------------------------------- 1 | // +build go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$4-4 6 | CALL runtime·acquirem(SB) 7 | MOVL 0(SP), AX 8 | MOVL AX, ret+0(FP) 9 | CALL runtime·releasem(SB) 10 | RET 11 | 12 | TEXT ·Addrs(SB),NOSPLIT,$0-8 13 | MOVL $runtime·main(SB), AX 14 | MOVL AX, ret+0(FP) 15 | MOVL $main·main(SB), AX 16 | MOVL AX, ret+8(FP) 17 | RET 18 | -------------------------------------------------------------------------------- /cdata/cdata15_amd64.s: -------------------------------------------------------------------------------- 1 | // +build go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$8-8 6 | CALL runtime·acquirem(SB) 7 | MOVQ 0(SP), AX 8 | MOVQ AX, ret+0(FP) 9 | CALL runtime·releasem(SB) 10 | RET 11 | 12 | TEXT ·Addrs(SB),NOSPLIT,$0-16 13 | MOVQ $runtime·main(SB), AX 14 | MOVQ AX, ret+0(FP) 15 | MOVQ $main·main(SB), AX 16 | MOVQ AX, ret+8(FP) 17 | RET 18 | -------------------------------------------------------------------------------- /cdata/cdata15_arm.s: -------------------------------------------------------------------------------- 1 | // +build go1.5 2 | 3 | #include "textflag.h" 4 | 5 | TEXT ·Ref(SB),NOSPLIT,$4-4 6 | BL runtime·acquirem(SB) 7 | MOVW 4(R13), R0 8 | MOVW R0, ret+0(FP) 9 | MOVW R0, 4(R13) 10 | BL runtime·releasem(SB) 11 | RET 12 | 13 | TEXT ·Addrs(SB),NOSPLIT,$0-8 14 | MOVW $runtime·main(SB), R0 15 | MOVW R0, ret+0(FP) 16 | MOVW $main·main(SB), R0 17 | MOVW R0, ret+4(FP) 18 | RET 19 | -------------------------------------------------------------------------------- /cdata/cdata_test.go: -------------------------------------------------------------------------------- 1 | package cdata 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | "testing" 7 | ) 8 | 9 | type refPair struct { 10 | ref1, ref2 uintptr 11 | } 12 | 13 | func TestRef(t *testing.T) { 14 | const N = 10 15 | runtime.LockOSThread() 16 | exit := sync.WaitGroup{} 17 | exit.Add(1) 18 | defer exit.Done() 19 | wg := sync.WaitGroup{} 20 | wg.Add(N) 21 | ch := make(chan refPair) 22 | for i := 0; i < N; i++ { 23 | go func() { 24 | runtime.LockOSThread() 25 | wg.Done() 26 | ch <- refPair{Ref(), Ref()} 27 | exit.Wait() 28 | }() 29 | } 30 | wg.Wait() 31 | refs := make(map[uintptr]bool) 32 | for i := 0; i < N; i++ { 33 | pair := <-ch 34 | if pair.ref1 != pair.ref2 { 35 | t.Fatalf("found inconsistent ref: %d != %d", pair.ref1, pair.ref2) 36 | } 37 | if refs[pair.ref1] { 38 | t.Fatalf("found duplicated ref: %d", pair.ref1) 39 | } 40 | refs[pair.ref1] = true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmd/ubuntu-touch/particle.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=1.0 4 | Type=Application 5 | Terminal=false 6 | Path=/home/phablet/src/gopkg.in/qml.v0/examples/particle/ 7 | Exec=./particle 8 | Icon=properties 9 | Name=Particle Example 10 | X-Ubuntu-Touch=true 11 | X-Ubuntu-StageHint=SideStage 12 | 13 | # Copy this file to: 14 | # 15 | # ~phablet/.local/share/applications/gopkg.in.qml.particle-example.desktop 16 | -------------------------------------------------------------------------------- /cmd/ubuntu-touch/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ "$USER" != "root" ]; then 6 | echo 'This script must be run as root.' 7 | exit 1 8 | fi 9 | 10 | echo 'Remounting root as read-write ------------------------------------------------' 11 | 12 | mount -o remount,rw / 13 | 14 | echo 'Installing Go and dependencies -----------------------------------------------' 15 | 16 | apt-get update 17 | apt-get install -y \ 18 | golang-go g++ git pkg-config ubuntu-app-launch\ 19 | qtbase5-private-dev qtdeclarative5-private-dev libqt5opengl5-dev 20 | apt-get clean 21 | 22 | echo 'Setting up environment for phablet user --------------------------------------' 23 | 24 | echo 'export GOPATH=$HOME' >> ~phablet/.bash_profile 25 | 26 | echo 'Fetching the qml package -----------------------------------------------------' 27 | 28 | su -l phablet -c 'go get gopkg.in/qml.v0' 29 | 30 | echo 'Installing the .desktop file for the particle example ------------------------' 31 | 32 | APP_ID='gopkg.in.qml.particle-example' 33 | cp ~phablet/src/gopkg.in/qml.v*/cmd/ubuntu-touch/particle.desktop ~phablet/.local/share/applications/$APP_ID.desktop 34 | 35 | echo 'Building and launching particle example --------------------------------------' 36 | 37 | su -l phablet -c 'cd $HOME/src/gopkg.in/qml.v0/examples/particle; go build' 38 | 39 | echo 'Launching particle example ---------------------------------------------------' 40 | 41 | su -l phablet -c "ubuntu-app-launch $APP_ID" 42 | -------------------------------------------------------------------------------- /cpp/connector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "connector.h" 4 | #include "capi.h" 5 | 6 | Connector::~Connector() 7 | { 8 | hookSignalDisconnect(func); 9 | } 10 | 11 | void Connector::invoke() 12 | { 13 | panicf("should never get called"); 14 | } 15 | 16 | int Connector::qt_metacall(QMetaObject::Call c, int idx, void **a) 17 | { 18 | if (c == QMetaObject::InvokeMetaMethod && idx == metaObject()->methodOffset()) { 19 | DataValue args[MaxParams]; 20 | QObject *plain = NULL; 21 | for (int i = 0; i < argsLen; i++) { 22 | int paramType = method.parameterType(i); 23 | if (paramType == 0 && a[1 + i] != NULL) { 24 | const char *typeName = method.parameterTypes()[i].constData(); 25 | void *addr = a[1 + i]; 26 | if (typeName[strlen(typeName)-1] == '*') { 27 | addr = *(void **)addr; 28 | } 29 | plain = new PlainObject(typeName, addr, plain); 30 | QVariant var = QVariant::fromValue((QObject *)plain); 31 | packDataValue(&var, &args[i]); 32 | } else { 33 | QVariant var(method.parameterType(i), a[1 + i]); 34 | packDataValue(&var, &args[i]); 35 | } 36 | } 37 | hookSignalCall(engine, func, args); 38 | if (plain != NULL) { 39 | delete plain; 40 | } 41 | return -1; 42 | } 43 | return standard_qt_metacall(c, idx, a); 44 | } 45 | 46 | // vim:ts=4:sw=4:et 47 | -------------------------------------------------------------------------------- /cpp/connector.h: -------------------------------------------------------------------------------- 1 | #ifndef CONNECTOR_H 2 | #define CONNECTOR_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | class Connector : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | 14 | Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, void *func, int argsLen) 15 | : QObject(sender), engine(engine), method(method), func(func), argsLen(argsLen) {}; 16 | 17 | virtual ~Connector(); 18 | 19 | // MOC HACK: s/Connector::qt_metacall/Connector::standard_qt_metacall/ 20 | int standard_qt_metacall(QMetaObject::Call c, int idx, void **a); 21 | 22 | public slots: 23 | 24 | void invoke(); 25 | 26 | private: 27 | 28 | QQmlEngine *engine; 29 | QMetaMethod method; 30 | void *func; 31 | int argsLen; 32 | }; 33 | 34 | class PlainObject : public QObject 35 | { 36 | Q_OBJECT 37 | 38 | Q_PROPERTY(QString plainType READ getPlainType) 39 | Q_PROPERTY(void *plainAddr READ getPlainAddr) 40 | 41 | QString plainType; 42 | void *plainAddr; 43 | 44 | public: 45 | 46 | PlainObject(QObject *parent = 0) 47 | : QObject(parent) {}; 48 | 49 | PlainObject(const char *plainType, void *plainAddr, QObject *parent = 0) 50 | : QObject(parent), plainType(plainType), plainAddr(plainAddr) {}; 51 | 52 | QString getPlainType() { return plainType; }; 53 | void *getPlainAddr() { return plainAddr; }; 54 | }; 55 | 56 | #endif // CONNECTOR_H 57 | 58 | // vim:ts=4:sw=4:et 59 | -------------------------------------------------------------------------------- /cpp/goitemmodel.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "goitemmodel.h" 3 | 4 | GoItemModel::GoItemModel(QObject* parent, GoAddr* addr) 5 | : QAbstractItemModel(parent), addr(addr) { 6 | 7 | } 8 | 9 | QModelIndex_* miCastTo(const QModelIndex &index) { 10 | return reinterpret_cast(const_cast(&index)); 11 | } 12 | QModelIndex miCastFrom(QModelIndex_ *index) { 13 | if (index == NULL) { 14 | return QModelIndex(); 15 | } 16 | return *reinterpret_cast(index); 17 | } 18 | 19 | // Required functions 20 | int GoItemModel::columnCount(const QModelIndex &parent) const { 21 | return implColumnCount(addr, miCastTo(parent)); 22 | } 23 | 24 | QVariant GoItemModel::data(const QModelIndex &index, int role) const { 25 | DataValue value; 26 | 27 | implData(addr, miCastTo(index), role, &value); 28 | 29 | QVariant var; 30 | unpackDataValue(&value, &var); 31 | 32 | return var; 33 | } 34 | 35 | QModelIndex GoItemModel::index(int row, int column, const QModelIndex &parent) const { 36 | return miCastFrom(implIndex(addr, row, column, miCastTo(parent))); 37 | } 38 | 39 | QModelIndex GoItemModel::parent(const QModelIndex &index) const { 40 | return miCastFrom(implParent(addr, miCastTo(index))); 41 | } 42 | 43 | int GoItemModel::rowCount(const QModelIndex &parent) const { 44 | return implRowCount(addr, miCastTo(parent)); 45 | } 46 | 47 | 48 | // Required for editing 49 | Qt::ItemFlags GoItemModel::flags(const QModelIndex &index) const { 50 | return (Qt::ItemFlags)implFlags(addr, miCastTo(index)); 51 | } 52 | 53 | bool GoItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { 54 | DataValue *dv = (DataValue *) malloc(sizeof(DataValue)); 55 | packDataValue(&value, dv); 56 | return implSetData(addr, miCastTo(index), dv, role); 57 | } 58 | 59 | // Internal Protected functions 60 | 61 | QModelIndex GoItemModel::protCreateIndex(int row, int column, quintptr id) const { 62 | return createIndex(row, column, id); 63 | } 64 | 65 | void GoItemModel::protBeginInsertColumns(const QModelIndex &parent, int first, int last) { 66 | return beginInsertColumns(parent, first, last); 67 | } 68 | 69 | void GoItemModel::protEndInsertColumns() { 70 | return endInsertColumns(); 71 | } 72 | 73 | void GoItemModel::protBeginInsertRows(const QModelIndex &parent, int first, int last) { 74 | return beginInsertRows(parent, first, last); 75 | } 76 | 77 | void GoItemModel::protEndInsertRows() { 78 | return endInsertRows(); 79 | } 80 | 81 | void GoItemModel::protBeginRemoveRows(const QModelIndex &parent, int first, int last) { 82 | return beginRemoveRows(parent, first, last); 83 | } 84 | 85 | void GoItemModel::protEndRemoveRows() { 86 | return endRemoveRows(); 87 | } 88 | -------------------------------------------------------------------------------- /cpp/goitemmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef GOITEMMODEL_H 2 | #define GOITEMMODEL_H 3 | 4 | // #include "capi.h" 5 | #include 6 | #include 7 | #include "goitemmodel_impl.h" 8 | 9 | // QImage_* newQImage(int width, int height, unsigned int format); 10 | // QImage_* loadQImage(const char *filename, int filename_length, const char *format); 11 | // void deleteQImage(QImage_*); 12 | 13 | class GoItemModel : public QAbstractItemModel 14 | { 15 | Q_OBJECT 16 | public: 17 | // QAbstractItemModel(QObject *parent = Q_NULLPTR) 18 | GoItemModel(QObject *parent, GoAddr *impl); 19 | // virtual ~QAbstractItemModel() 20 | 21 | // Required functions 22 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 23 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 24 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 25 | QModelIndex parent(const QModelIndex &index) const; 26 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 27 | 28 | // Required for editing 29 | Qt::ItemFlags flags(const QModelIndex &index) const; 30 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); 31 | 32 | QModelIndex protCreateIndex(int row, int column, quintptr id) const; 33 | void protBeginInsertColumns(const QModelIndex &parent, int first, int last); 34 | void protEndInsertColumns(); 35 | void protBeginInsertRows(const QModelIndex &parent, int first, int last); 36 | void protEndInsertRows(); 37 | void protBeginRemoveRows(const QModelIndex &parent, int first, int last); 38 | void protEndRemoveRows(); 39 | 40 | 41 | 42 | // virtual QModelIndex buddy(const QModelIndex &index) const 43 | // virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const 44 | // virtual bool canFetchMore(const QModelIndex &parent) const 45 | // virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 46 | // virtual void fetchMore(const QModelIndex &parent) 47 | // virtual Qt::ItemFlags flags(const QModelIndex &index) const 48 | // virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const 49 | // bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const 50 | // virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const 51 | // bool insertColumn(int column, const QModelIndex &parent = QModelIndex()) 52 | // virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 53 | // bool insertRow(int row, const QModelIndex &parent = QModelIndex()) 54 | // virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) 55 | // virtual QMap itemData(const QModelIndex &index) const 56 | // virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap )) const 57 | // virtual QMimeData * mimeData(const QModelIndexList &indexes) const 58 | // virtual QStringList mimeTypes() const 59 | // bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild) 60 | // virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) 61 | // bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) 62 | // virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) 63 | // bool removeColumn(int column, const QModelIndex &parent = QModelIndex()) 64 | // virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 65 | // bool removeRow(int row, const QModelIndex &parent = QModelIndex()) 66 | // virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) 67 | // virtual QHash roleNames() const 68 | // virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) 69 | // virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) 70 | // virtual bool setItemData(const QModelIndex &index, const QMap &roles) 71 | // virtual QModelIndex sibling(int row, int column, const QModelIndex &index) const 72 | // virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) 73 | // virtual QSize span(const QModelIndex &index) const 74 | // virtual Qt::DropActions supportedDragActions() const 75 | // virtual Qt::DropActions supportedDropActions() const 76 | 77 | // private: 78 | GoAddr *addr; 79 | }; 80 | 81 | #endif // GOITEMMODEL_H 82 | 83 | // vim:ts=4:sw=4:et:ft=cpp 84 | -------------------------------------------------------------------------------- /cpp/goitemmodel_api.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "goitemmodel.h" 3 | #include "goitemmodel_api.h" 4 | #include "util.cpp" 5 | #include 6 | 7 | 8 | QItemModel_* newGoItemModel(QObject_* parent, GoAddr* impl) { 9 | return reinterpret_cast(new GoItemModel(reinterpret_cast(parent), impl)); 10 | } 11 | 12 | void deleteGoItemModel(QItemModel_* im) { 13 | delete reinterpret_cast(im); 14 | } 15 | 16 | 17 | 18 | QModelIndex_ *modelIndexChild(QModelIndex_ *mi, int row, int col) { 19 | QModelIndex *ret = new QModelIndex; 20 | *ret = reinterpret_cast(mi)->child(row, col); 21 | return (QModelIndex_*)ret; 22 | } 23 | 24 | QModelIndex_ *modelIndexSibling(QModelIndex_ *mi, int row, int col) { 25 | QModelIndex *ret = new QModelIndex; 26 | *ret = reinterpret_cast(mi)->sibling(row, col); 27 | return (QModelIndex_*)ret; 28 | } 29 | 30 | int modelIndexColumn(QModelIndex_ *mi) { 31 | return reinterpret_cast(mi)->column(); 32 | } 33 | 34 | int modelIndexRow(QModelIndex_ *mi) { 35 | return reinterpret_cast(mi)->row(); 36 | } 37 | 38 | void modelIndexData(QModelIndex_ *mi, int role, DataValue *ret) { 39 | QVariant value = reinterpret_cast(mi)->data(role); 40 | packDataValue(&value, ret); 41 | } 42 | 43 | quint32 modelIndexFlags(QModelIndex_ *mi) { 44 | return reinterpret_cast(mi)->flags(); 45 | } 46 | 47 | uintptr_t modelIndexInternalId(QModelIndex_ *mi) { 48 | return reinterpret_cast(mi)->internalId(); 49 | } 50 | 51 | uintptr_t modelIndexInternalPointer(QModelIndex_ *mi) { 52 | return (quintptr)reinterpret_cast(mi)->internalPointer(); 53 | } 54 | 55 | bool modelIndexIsValid(QModelIndex_ *mi) { 56 | return reinterpret_cast(mi)->isValid(); 57 | } 58 | 59 | QItemModel_ *modelIndexModel(QModelIndex_ *mi) { 60 | return (QItemModel_ *)reinterpret_cast(mi)->model(); 61 | } 62 | 63 | QModelIndex_ *modelIndexParent(QModelIndex_ *mi) { 64 | QModelIndex *ret = new QModelIndex; 65 | *ret = reinterpret_cast(mi)->parent(); 66 | return (QModelIndex_*)ret; 67 | } 68 | 69 | 70 | // Protected functions 71 | 72 | QModelIndex_ *itemModelCreateIndex(QItemModel_ *im, int row, int col, uintptr_t id) { 73 | QModelIndex *ret = new QModelIndex; 74 | *ret = reinterpret_cast(im)->protCreateIndex(row, col, id); 75 | return (QModelIndex_*)ret; 76 | } 77 | 78 | void itemModelBeginInsertColumns(QItemModel_ *im, QModelIndex_ *parent, int first, int last) { 79 | reinterpret_cast(im)->protBeginInsertColumns(miCastFrom(parent), first, last); 80 | } 81 | 82 | void itemModelEndInsertColumns(QItemModel_ *im) { 83 | reinterpret_cast(im)->protEndInsertColumns(); 84 | } 85 | 86 | void itemModelBeginInsertRows(QItemModel_ *im, QModelIndex_ *parent, int first, int last) { 87 | reinterpret_cast(im)->protBeginInsertRows(miCastFrom(parent), first, last); 88 | } 89 | 90 | void itemModelEndInsertRows(QItemModel_ *im) { 91 | reinterpret_cast(im)->protEndInsertRows(); 92 | } 93 | 94 | void itemModelBeginRemoveRows(QItemModel_ *im, QModelIndex_ *parent, int first, int last) { 95 | reinterpret_cast(im)->protBeginRemoveRows(miCastFrom(parent), first, last); 96 | } 97 | 98 | void itemModelEndRemoveRows(QItemModel_ *im) { 99 | reinterpret_cast(im)->protEndRemoveRows(); 100 | } 101 | 102 | void itemModelDataChanged(QItemModel_ *im, QModelIndex_ *topLeft, QModelIndex_ *bottomRight) { 103 | reinterpret_cast(im)->dataChanged(miCastFrom(topLeft), miCastFrom(bottomRight)); 104 | } 105 | 106 | // Required functions 107 | int itemModelColumnCount(QItemModel_ *im, QModelIndex_ *parent) { 108 | return reinterpret_cast(im)->columnCount(miCastFrom(parent)); 109 | } 110 | 111 | void itemModelData(QItemModel_ *im, QModelIndex_ *index, int role, DataValue *ret) { 112 | QVariant var = reinterpret_cast(im)->data(miCastFrom(index), role); 113 | 114 | packDataValue(&var, ret); 115 | } 116 | 117 | QModelIndex_ *itemModelIndex(QItemModel_ *im, int row, int column, QModelIndex_ *parent) { 118 | QModelIndex *ret = new QModelIndex; 119 | *ret = reinterpret_cast(im)->index(row, column, miCastFrom(parent)); 120 | return (QModelIndex_*)ret; 121 | } 122 | 123 | QModelIndex_ *itemModelParent(QItemModel_ *im, QModelIndex_ *index) { 124 | QModelIndex *ret = new QModelIndex; 125 | *ret = reinterpret_cast(im)->parent(miCastFrom(index)); 126 | return (QModelIndex_*)ret; 127 | } 128 | 129 | int itemModelRowCount(QItemModel_ *im, QModelIndex_ *parent) { 130 | return reinterpret_cast(im)->rowCount(miCastFrom(parent)); 131 | } 132 | 133 | 134 | // Required for editing 135 | int itemModelFlags(QItemModel_ *im, QModelIndex_ *index) { 136 | return reinterpret_cast(im)->flags(miCastFrom(index)); 137 | } 138 | 139 | bool itemModelSetData(QItemModel_ *im, QModelIndex_ *index, DataValue *value, int role) { 140 | QVariant var; 141 | unpackDataValue(value, &var); 142 | return reinterpret_cast(im)->setData(miCastFrom(index), var, role); 143 | } 144 | -------------------------------------------------------------------------------- /cpp/goitemmodel_api.h: -------------------------------------------------------------------------------- 1 | #ifndef GOITEMMODEL_API_H 2 | #define GOITEMMODEL_API_H 3 | 4 | // #include "capi.h" 5 | #include 6 | #include 7 | #include 8 | #include "capi.h" 9 | #include 10 | 11 | typedef void GoAddr; 12 | typedef void QObject_; 13 | typedef void QItemModel_; 14 | typedef void QModelIndex_; 15 | typedef void QVariant_; 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | QItemModel_* newGoItemModel(QObject_*, GoAddr*); 22 | void deleteGoItemModel(QItemModel_*); 23 | 24 | QModelIndex_ *modelIndexChild(QModelIndex_ *mi, int row, int col); 25 | QModelIndex_ *modelIndexSibling(QModelIndex_ *mi, int row, int col); 26 | int modelIndexColumn(QModelIndex_ *mi); 27 | int modelIndexRow(QModelIndex_ *mi); 28 | void modelIndexData(QModelIndex_ *mi, int role, DataValue *ret); 29 | quint32 modelIndexFlags(QModelIndex_ *mi); 30 | uintptr_t modelIndexInternalId(QModelIndex_ *mi); 31 | uintptr_t modelIndexInternalPointer(QModelIndex_ *mi); 32 | bool modelIndexIsValid(QModelIndex_ *mi); 33 | QItemModel_ *modelIndexModel(QModelIndex_ *mi); 34 | QModelIndex_ *modelIndexParent(QModelIndex_ *mi); 35 | 36 | 37 | // Required functions 38 | int itemModelColumnCount(QItemModel_ *im, QModelIndex_ *parent); 39 | void itemModelData(QItemModel_ *im, QModelIndex_ *index, int role, DataValue *ret); 40 | QModelIndex_ *itemModelIndex(QItemModel_ *im, int row, int column, QModelIndex_ *parent); 41 | QModelIndex_ *itemModelParent(QItemModel_ *im, QModelIndex_ *index); 42 | int itemModelRowCount(QItemModel_ *im, QModelIndex_ *parent); 43 | 44 | // Required for editing 45 | int itemModelFlags(QItemModel_ *im, QModelIndex_ *index); 46 | bool itemModelSetData(QItemModel_ *im, QModelIndex_ *index, DataValue *value, int role); 47 | 48 | // Protected functions 49 | QModelIndex_ *itemModelCreateIndex(QItemModel_ *im, int row, int col, uintptr_t id); 50 | void itemModelBeginInsertColumns(QItemModel_ *im, QModelIndex_ *parent, int first, int last); 51 | void itemModelEndInsertColumns(QItemModel_ *im); 52 | void itemModelBeginInsertRows(QItemModel_ *im, QModelIndex_ *parent, int first, int last); 53 | void itemModelEndInsertRows(QItemModel_ *im); 54 | void itemModelBeginRemoveRows(QItemModel_ *im, QModelIndex_ *parent, int first, int last); 55 | void itemModelEndRemoveRows(QItemModel_ *im); 56 | 57 | 58 | void itemModelDataChanged(QItemModel_ *im, QModelIndex_ *topLeft, QModelIndex_ *bottomRight); 59 | 60 | 61 | // virtual QModelIndex buddy(const QModelIndex &index) const 62 | // virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const 63 | // virtual bool canFetchMore(const QModelIndex &parent) const 64 | // virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 65 | // virtual void fetchMore(const QModelIndex &parent) 66 | // virtual Qt::ItemFlags flags(const QModelIndex &index) const 67 | // virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const 68 | // bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const 69 | // virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const 70 | // bool insertColumn(int column, const QModelIndex &parent = QModelIndex()) 71 | // virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 72 | // bool insertRow(int row, const QModelIndex &parent = QModelIndex()) 73 | // virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) 74 | // virtual QMap itemData(const QModelIndex &index) const 75 | // virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap )) const 76 | // virtual QMimeData * mimeData(const QModelIndexList &indexes) const 77 | // virtual QStringList mimeTypes() const 78 | // bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild) 79 | // virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) 80 | // bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) 81 | // virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) 82 | // bool removeColumn(int column, const QModelIndex &parent = QModelIndex()) 83 | // virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 84 | // bool removeRow(int row, const QModelIndex &parent = QModelIndex()) 85 | // virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) 86 | // virtual QHash roleNames() const 87 | // virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) 88 | // virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) 89 | // virtual bool setItemData(const QModelIndex &index, const QMap &roles) 90 | // virtual QModelIndex sibling(int row, int column, const QModelIndex &index) const 91 | // virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) 92 | // virtual QSize span(const QModelIndex &index) const 93 | // virtual Qt::DropActions supportedDragActions() const 94 | // virtual Qt::DropActions supportedDropActions() const 95 | 96 | 97 | #ifdef __cplusplus 98 | } // extern "C" 99 | #endif 100 | 101 | #endif // GOITEMMODEL_API_H 102 | 103 | // vim:ts=4:sw=4:et:ft=cpp 104 | -------------------------------------------------------------------------------- /cpp/goitemmodel_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef GOITEMMODEL_IMPL_H 2 | #define GOITEMMODEL_IMPL_H 3 | 4 | // #include "capi.h" 5 | #include 6 | #include 7 | #include 8 | 9 | typedef void GoAddr; 10 | typedef void QObject_; 11 | typedef void QItemModel_; 12 | typedef void QModelIndex_; 13 | typedef void QVariant_; 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | // QItemModel_* newGoItemModel(QObject_*, GoAddr*); 20 | // void deleteGoItemModel(QItemModel_*); 21 | 22 | // Required functions 23 | int implColumnCount(GoAddr *impl, QModelIndex_ *parent); 24 | void implData(GoAddr *impl, QModelIndex_ *index, int role, DataValue *ret); 25 | QModelIndex_ *implIndex(GoAddr *impl, int row, int column, QModelIndex_ *parent); 26 | QModelIndex_ *implParent(GoAddr *impl, QModelIndex_ *index); 27 | int implRowCount(GoAddr *impl, QModelIndex_ *parent); 28 | 29 | // Required for editing 30 | int implFlags(GoAddr *impl, QModelIndex_ *index); 31 | bool implSetData(GoAddr *impl, QModelIndex_ *index, DataValue *value, int role); 32 | 33 | 34 | // virtual QModelIndex buddy(const QModelIndex &index) const 35 | // virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const 36 | // virtual bool canFetchMore(const QModelIndex &parent) const 37 | // virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 38 | // virtual void fetchMore(const QModelIndex &parent) 39 | // virtual Qt::ItemFlags flags(const QModelIndex &index) const 40 | // virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const 41 | // bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const 42 | // virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const 43 | // bool insertColumn(int column, const QModelIndex &parent = QModelIndex()) 44 | // virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 45 | // bool insertRow(int row, const QModelIndex &parent = QModelIndex()) 46 | // virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) 47 | // virtual QMap itemData(const QModelIndex &index) const 48 | // virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap )) const 49 | // virtual QMimeData * mimeData(const QModelIndexList &indexes) const 50 | // virtual QStringList mimeTypes() const 51 | // bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild) 52 | // virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) 53 | // bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) 54 | // virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) 55 | // bool removeColumn(int column, const QModelIndex &parent = QModelIndex()) 56 | // virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) 57 | // bool removeRow(int row, const QModelIndex &parent = QModelIndex()) 58 | // virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) 59 | // virtual QHash roleNames() const 60 | // virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) 61 | // virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) 62 | // virtual bool setItemData(const QModelIndex &index, const QMap &roles) 63 | // virtual QModelIndex sibling(int row, int column, const QModelIndex &index) const 64 | // virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) 65 | // virtual QSize span(const QModelIndex &index) const 66 | // virtual Qt::DropActions supportedDragActions() const 67 | // virtual Qt::DropActions supportedDropActions() const 68 | 69 | 70 | #ifdef __cplusplus 71 | } // extern "C" 72 | #endif 73 | 74 | #endif // GOITEMMODEL_IMPL_H 75 | 76 | // vim:ts=4:sw=4:et:ft=cpp 77 | -------------------------------------------------------------------------------- /cpp/govalue.h: -------------------------------------------------------------------------------- 1 | #ifndef GOVALUE_H 2 | #define GOVALUE_H 3 | 4 | // Unfortunatley we need access to private bits, because the 5 | // whole dynamic meta-object concept is sadly being hidden 6 | // away, and without it this package wouldn't exist. 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "capi.h" 13 | 14 | class GoValueMetaObject; 15 | 16 | QMetaObject *metaObjectFor(GoTypeInfo *typeInfo); 17 | 18 | class GoValue : public QObject 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | GoAddr *addr; 24 | GoTypeInfo *typeInfo; 25 | 26 | GoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent); 27 | virtual ~GoValue(); 28 | 29 | void activate(int propIndex); 30 | 31 | private: 32 | GoValueMetaObject *valueMeta; 33 | }; 34 | 35 | class GoPaintedValue : public QQuickPaintedItem 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | GoAddr *addr; 41 | GoTypeInfo *typeInfo; 42 | 43 | GoPaintedValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent); 44 | virtual ~GoPaintedValue(); 45 | 46 | void activate(int propIndex); 47 | 48 | virtual void paint(QPainter *painter); 49 | 50 | private: 51 | GoValueMetaObject *valueMeta; 52 | }; 53 | 54 | #endif // GOVALUE_H 55 | 56 | // vim:ts=4:sw=4:et:ft=cpp 57 | -------------------------------------------------------------------------------- /cpp/govaluetype.h: -------------------------------------------------------------------------------- 1 | #ifndef GOVALUETYPE_H 2 | #define GOVALUETYPE_H 3 | 4 | #include "govalue.h" 5 | 6 | template 7 | class GoValueType : public GoValue 8 | { 9 | public: 10 | 11 | GoValueType() 12 | : GoValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {}; 13 | 14 | static void init(GoTypeInfo *info, GoTypeSpec_ *spec) 15 | { 16 | typeInfo = info; 17 | typeSpec = spec; 18 | static_cast(staticMetaObject) = *metaObjectFor(typeInfo); 19 | }; 20 | 21 | static GoTypeSpec_ *typeSpec; 22 | static GoTypeInfo *typeInfo; 23 | static QMetaObject staticMetaObject; 24 | }; 25 | 26 | template 27 | class GoPaintedValueType : public GoPaintedValue 28 | { 29 | public: 30 | 31 | GoPaintedValueType() 32 | : GoPaintedValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {}; 33 | 34 | static void init(GoTypeInfo *info, GoTypeSpec_ *spec) 35 | { 36 | typeInfo = info; 37 | typeSpec = spec; 38 | static_cast(staticMetaObject) = *metaObjectFor(typeInfo); 39 | }; 40 | 41 | static GoTypeSpec_ *typeSpec; 42 | static GoTypeInfo *typeInfo; 43 | static QMetaObject staticMetaObject; 44 | }; 45 | 46 | #endif // GOVALUETYPE_H 47 | 48 | // vim:ts=4:sw=4:et 49 | -------------------------------------------------------------------------------- /cpp/idletimer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "capi.h" 7 | 8 | class IdleTimer : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | 14 | static IdleTimer *singleton() { 15 | static IdleTimer singleton; 16 | return &singleton; 17 | } 18 | 19 | void init(int32_t *guiIdleRun) 20 | { 21 | this->guiIdleRun = guiIdleRun; 22 | } 23 | 24 | Q_INVOKABLE void start() 25 | { 26 | // timer.start(0, this); 27 | hookIdleTimer(); 28 | } 29 | 30 | protected: 31 | 32 | void timerEvent(QTimerEvent *event) 33 | { 34 | __sync_synchronize(); 35 | if (*guiIdleRun > 0) { 36 | hookIdleTimer(); 37 | } else { 38 | timer.stop(); 39 | } 40 | } 41 | 42 | private: 43 | 44 | int32_t *guiIdleRun; 45 | 46 | QBasicTimer timer; 47 | }; 48 | 49 | void idleTimerInit(int32_t *guiIdleRun) 50 | { 51 | IdleTimer::singleton()->init(guiIdleRun); 52 | } 53 | 54 | void idleTimerStart() 55 | { 56 | QMetaObject::invokeMethod(IdleTimer::singleton(), "start", Qt::AutoConnection); 57 | } 58 | 59 | // vim:ts=4:sw=4:et:ft=cpp 60 | -------------------------------------------------------------------------------- /cpp/mmemwin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define protREAD 1 4 | #define protWRITE 2 5 | #define protEXEC 4 6 | 7 | extern "C" { 8 | 9 | int mprotect(void *addr, size_t len, int prot) 10 | { 11 | DWORD wprot = 0; 12 | if (prot & protWRITE) { 13 | wprot = PAGE_READWRITE; 14 | } else if (prot & protREAD) { 15 | wprot = PAGE_READONLY; 16 | } 17 | if (prot & protEXEC) { 18 | wprot <<= 4; 19 | } 20 | DWORD oldwprot; 21 | if (!VirtualProtect(addr, len, wprot, &oldwprot)) { 22 | return -1; 23 | } 24 | return 0; 25 | } 26 | 27 | } // extern "C" 28 | -------------------------------------------------------------------------------- /cpp/moc_all.cpp: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by cpp/update-moc.sh 2 | #include "cpp/moc_connector.cpp" 3 | #include "cpp/moc_goitemmodel.cpp" 4 | #include "cpp/moc_govalue.cpp" 5 | #include "cpp/moc_idletimer.cpp" 6 | -------------------------------------------------------------------------------- /cpp/moc_goitemmodel.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** Meta object code from reading C++ file 'goitemmodel.h' 3 | ** 4 | ** Created by: The Qt Meta Object Compiler version 67 (Qt 5.6.0) 5 | ** 6 | ** WARNING! All changes made in this file will be lost! 7 | *****************************************************************************/ 8 | 9 | #include "goitemmodel.h" 10 | #include 11 | #include 12 | #if !defined(Q_MOC_OUTPUT_REVISION) 13 | #error "The header file 'goitemmodel.h' doesn't include ." 14 | #elif Q_MOC_OUTPUT_REVISION != 67 15 | #error "This file was generated using the moc from 5.6.0. It" 16 | #error "cannot be used with the include files from this version of Qt." 17 | #error "(The moc has changed too much.)" 18 | #endif 19 | 20 | QT_BEGIN_MOC_NAMESPACE 21 | struct qt_meta_stringdata_GoItemModel_t { 22 | QByteArrayData data[1]; 23 | char stringdata0[12]; 24 | }; 25 | #define QT_MOC_LITERAL(idx, ofs, len) \ 26 | Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ 27 | qptrdiff(offsetof(qt_meta_stringdata_GoItemModel_t, stringdata0) + ofs \ 28 | - idx * sizeof(QByteArrayData)) \ 29 | ) 30 | static const qt_meta_stringdata_GoItemModel_t qt_meta_stringdata_GoItemModel = { 31 | { 32 | QT_MOC_LITERAL(0, 0, 11) // "GoItemModel" 33 | 34 | }, 35 | "GoItemModel" 36 | }; 37 | #undef QT_MOC_LITERAL 38 | 39 | static const uint qt_meta_data_GoItemModel[] = { 40 | 41 | // content: 42 | 7, // revision 43 | 0, // classname 44 | 0, 0, // classinfo 45 | 0, 0, // methods 46 | 0, 0, // properties 47 | 0, 0, // enums/sets 48 | 0, 0, // constructors 49 | 0, // flags 50 | 0, // signalCount 51 | 52 | 0 // eod 53 | }; 54 | 55 | void GoItemModel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 56 | { 57 | Q_UNUSED(_o); 58 | Q_UNUSED(_id); 59 | Q_UNUSED(_c); 60 | Q_UNUSED(_a); 61 | } 62 | 63 | const QMetaObject GoItemModel::staticMetaObject = { 64 | { &QAbstractItemModel::staticMetaObject, qt_meta_stringdata_GoItemModel.data, 65 | qt_meta_data_GoItemModel, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} 66 | }; 67 | 68 | 69 | const QMetaObject *GoItemModel::metaObject() const 70 | { 71 | return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; 72 | } 73 | 74 | void *GoItemModel::qt_metacast(const char *_clname) 75 | { 76 | if (!_clname) return Q_NULLPTR; 77 | if (!strcmp(_clname, qt_meta_stringdata_GoItemModel.stringdata0)) 78 | return static_cast(const_cast< GoItemModel*>(this)); 79 | return QAbstractItemModel::qt_metacast(_clname); 80 | } 81 | 82 | int GoItemModel::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 83 | { 84 | _id = QAbstractItemModel::qt_metacall(_c, _id, _a); 85 | if (_id < 0) 86 | return _id; 87 | return _id; 88 | } 89 | QT_END_MOC_NAMESPACE 90 | -------------------------------------------------------------------------------- /cpp/moc_govalue.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** Meta object code from reading C++ file 'govalue.h' 3 | ** 4 | ** Created by: The Qt Meta Object Compiler version 67 (Qt 5.6.0) 5 | ** 6 | ** WARNING! All changes made in this file will be lost! 7 | *****************************************************************************/ 8 | 9 | #include "govalue.h" 10 | #include 11 | #include 12 | #if !defined(Q_MOC_OUTPUT_REVISION) 13 | #error "The header file 'govalue.h' doesn't include ." 14 | #elif Q_MOC_OUTPUT_REVISION != 67 15 | #error "This file was generated using the moc from 5.6.0. It" 16 | #error "cannot be used with the include files from this version of Qt." 17 | #error "(The moc has changed too much.)" 18 | #endif 19 | 20 | QT_BEGIN_MOC_NAMESPACE 21 | struct qt_meta_stringdata_GoValue_t { 22 | QByteArrayData data[1]; 23 | char stringdata0[8]; 24 | }; 25 | #define QT_MOC_LITERAL(idx, ofs, len) \ 26 | Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ 27 | qptrdiff(offsetof(qt_meta_stringdata_GoValue_t, stringdata0) + ofs \ 28 | - idx * sizeof(QByteArrayData)) \ 29 | ) 30 | static const qt_meta_stringdata_GoValue_t qt_meta_stringdata_GoValue = { 31 | { 32 | QT_MOC_LITERAL(0, 0, 7) // "GoValue" 33 | 34 | }, 35 | "GoValue" 36 | }; 37 | #undef QT_MOC_LITERAL 38 | 39 | static const uint qt_meta_data_GoValue[] = { 40 | 41 | // content: 42 | 7, // revision 43 | 0, // classname 44 | 0, 0, // classinfo 45 | 0, 0, // methods 46 | 0, 0, // properties 47 | 0, 0, // enums/sets 48 | 0, 0, // constructors 49 | 0, // flags 50 | 0, // signalCount 51 | 52 | 0 // eod 53 | }; 54 | 55 | void GoValue::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 56 | { 57 | Q_UNUSED(_o); 58 | Q_UNUSED(_id); 59 | Q_UNUSED(_c); 60 | Q_UNUSED(_a); 61 | } 62 | 63 | const QMetaObject GoValue::staticMetaObject = { 64 | { &QObject::staticMetaObject, qt_meta_stringdata_GoValue.data, 65 | qt_meta_data_GoValue, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} 66 | }; 67 | 68 | 69 | const QMetaObject *GoValue::metaObject() const 70 | { 71 | return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; 72 | } 73 | 74 | void *GoValue::qt_metacast(const char *_clname) 75 | { 76 | if (!_clname) return Q_NULLPTR; 77 | if (!strcmp(_clname, qt_meta_stringdata_GoValue.stringdata0)) 78 | return static_cast(const_cast< GoValue*>(this)); 79 | return QObject::qt_metacast(_clname); 80 | } 81 | 82 | int GoValue::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 83 | { 84 | _id = QObject::qt_metacall(_c, _id, _a); 85 | if (_id < 0) 86 | return _id; 87 | return _id; 88 | } 89 | struct qt_meta_stringdata_GoPaintedValue_t { 90 | QByteArrayData data[1]; 91 | char stringdata0[15]; 92 | }; 93 | #define QT_MOC_LITERAL(idx, ofs, len) \ 94 | Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ 95 | qptrdiff(offsetof(qt_meta_stringdata_GoPaintedValue_t, stringdata0) + ofs \ 96 | - idx * sizeof(QByteArrayData)) \ 97 | ) 98 | static const qt_meta_stringdata_GoPaintedValue_t qt_meta_stringdata_GoPaintedValue = { 99 | { 100 | QT_MOC_LITERAL(0, 0, 14) // "GoPaintedValue" 101 | 102 | }, 103 | "GoPaintedValue" 104 | }; 105 | #undef QT_MOC_LITERAL 106 | 107 | static const uint qt_meta_data_GoPaintedValue[] = { 108 | 109 | // content: 110 | 7, // revision 111 | 0, // classname 112 | 0, 0, // classinfo 113 | 0, 0, // methods 114 | 0, 0, // properties 115 | 0, 0, // enums/sets 116 | 0, 0, // constructors 117 | 0, // flags 118 | 0, // signalCount 119 | 120 | 0 // eod 121 | }; 122 | 123 | void GoPaintedValue::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 124 | { 125 | Q_UNUSED(_o); 126 | Q_UNUSED(_id); 127 | Q_UNUSED(_c); 128 | Q_UNUSED(_a); 129 | } 130 | 131 | const QMetaObject GoPaintedValue::staticMetaObject = { 132 | { &QQuickPaintedItem::staticMetaObject, qt_meta_stringdata_GoPaintedValue.data, 133 | qt_meta_data_GoPaintedValue, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} 134 | }; 135 | 136 | 137 | const QMetaObject *GoPaintedValue::metaObject() const 138 | { 139 | return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; 140 | } 141 | 142 | void *GoPaintedValue::qt_metacast(const char *_clname) 143 | { 144 | if (!_clname) return Q_NULLPTR; 145 | if (!strcmp(_clname, qt_meta_stringdata_GoPaintedValue.stringdata0)) 146 | return static_cast(const_cast< GoPaintedValue*>(this)); 147 | return QQuickPaintedItem::qt_metacast(_clname); 148 | } 149 | 150 | int GoPaintedValue::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 151 | { 152 | _id = QQuickPaintedItem::qt_metacall(_c, _id, _a); 153 | if (_id < 0) 154 | return _id; 155 | return _id; 156 | } 157 | QT_END_MOC_NAMESPACE 158 | -------------------------------------------------------------------------------- /cpp/moc_idletimer.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** Meta object code from reading C++ file 'idletimer.cpp' 3 | ** 4 | ** Created by: The Qt Meta Object Compiler version 67 (Qt 5.6.0) 5 | ** 6 | ** WARNING! All changes made in this file will be lost! 7 | *****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #if !defined(Q_MOC_OUTPUT_REVISION) 12 | #error "The header file 'idletimer.cpp' doesn't include ." 13 | #elif Q_MOC_OUTPUT_REVISION != 67 14 | #error "This file was generated using the moc from 5.6.0. It" 15 | #error "cannot be used with the include files from this version of Qt." 16 | #error "(The moc has changed too much.)" 17 | #endif 18 | 19 | QT_BEGIN_MOC_NAMESPACE 20 | struct qt_meta_stringdata_IdleTimer_t { 21 | QByteArrayData data[3]; 22 | char stringdata0[17]; 23 | }; 24 | #define QT_MOC_LITERAL(idx, ofs, len) \ 25 | Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ 26 | qptrdiff(offsetof(qt_meta_stringdata_IdleTimer_t, stringdata0) + ofs \ 27 | - idx * sizeof(QByteArrayData)) \ 28 | ) 29 | static const qt_meta_stringdata_IdleTimer_t qt_meta_stringdata_IdleTimer = { 30 | { 31 | QT_MOC_LITERAL(0, 0, 9), // "IdleTimer" 32 | QT_MOC_LITERAL(1, 10, 5), // "start" 33 | QT_MOC_LITERAL(2, 16, 0) // "" 34 | 35 | }, 36 | "IdleTimer\0start\0" 37 | }; 38 | #undef QT_MOC_LITERAL 39 | 40 | static const uint qt_meta_data_IdleTimer[] = { 41 | 42 | // content: 43 | 7, // revision 44 | 0, // classname 45 | 0, 0, // classinfo 46 | 1, 14, // methods 47 | 0, 0, // properties 48 | 0, 0, // enums/sets 49 | 0, 0, // constructors 50 | 0, // flags 51 | 0, // signalCount 52 | 53 | // methods: name, argc, parameters, tag, flags 54 | 1, 0, 19, 2, 0x02 /* Public */, 55 | 56 | // methods: parameters 57 | QMetaType::Void, 58 | 59 | 0 // eod 60 | }; 61 | 62 | void IdleTimer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 63 | { 64 | if (_c == QMetaObject::InvokeMetaMethod) { 65 | IdleTimer *_t = static_cast(_o); 66 | Q_UNUSED(_t) 67 | switch (_id) { 68 | case 0: _t->start(); break; 69 | default: ; 70 | } 71 | } 72 | Q_UNUSED(_a); 73 | } 74 | 75 | const QMetaObject IdleTimer::staticMetaObject = { 76 | { &QObject::staticMetaObject, qt_meta_stringdata_IdleTimer.data, 77 | qt_meta_data_IdleTimer, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} 78 | }; 79 | 80 | 81 | const QMetaObject *IdleTimer::metaObject() const 82 | { 83 | return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; 84 | } 85 | 86 | void *IdleTimer::qt_metacast(const char *_clname) 87 | { 88 | if (!_clname) return Q_NULLPTR; 89 | if (!strcmp(_clname, qt_meta_stringdata_IdleTimer.stringdata0)) 90 | return static_cast(const_cast< IdleTimer*>(this)); 91 | return QObject::qt_metacast(_clname); 92 | } 93 | 94 | int IdleTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 95 | { 96 | _id = QObject::qt_metacall(_c, _id, _a); 97 | if (_id < 0) 98 | return _id; 99 | if (_c == QMetaObject::InvokeMetaMethod) { 100 | if (_id < 1) 101 | qt_static_metacall(this, _c, _id, _a); 102 | _id -= 1; 103 | } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { 104 | if (_id < 1) 105 | *reinterpret_cast(_a[0]) = -1; 106 | _id -= 1; 107 | } 108 | return _id; 109 | } 110 | QT_END_MOC_NAMESPACE 111 | -------------------------------------------------------------------------------- /cpp/private/qmetaobject_p.h: -------------------------------------------------------------------------------- 1 | #include "private/qtheader.h" 2 | #include QT_PRIVATE_HEADER(QtCore,qmetaobject_p.h) 3 | -------------------------------------------------------------------------------- /cpp/private/qmetaobjectbuilder_p.h: -------------------------------------------------------------------------------- 1 | #include "private/qtheader.h" 2 | #include QT_PRIVATE_HEADER(QtCore,qmetaobjectbuilder_p.h) 3 | -------------------------------------------------------------------------------- /cpp/private/qobject_p.h: -------------------------------------------------------------------------------- 1 | #include "private/qtheader.h" 2 | #include QT_PRIVATE_HEADER(QtCore,qobject_p.h) 3 | -------------------------------------------------------------------------------- /cpp/private/qtheader.h: -------------------------------------------------------------------------------- 1 | #ifndef QTPRIVATE_H 2 | #define QTPRIVATE_H 3 | 4 | #include 5 | 6 | #define QT_MAJOR_ (QT_VERSION>>16) 7 | #define QT_MINOR_ (QT_VERSION>>8&0xFF) 8 | #define QT_MICRO_ (QT_VERSION&0xFF) 9 | 10 | #if QT_MAJOR_ == 5 11 | #define QT_MAJOR 5 12 | #else 13 | #error Unupported Qt major version. Please report. 14 | #endif 15 | 16 | #if QT_MINOR_ == 0 17 | #define QT_MINOR 0 18 | #elif QT_MINOR_ == 1 19 | #define QT_MINOR 1 20 | #elif QT_MINOR_ == 2 21 | #define QT_MINOR 2 22 | #elif QT_MINOR_ == 3 23 | #define QT_MINOR 3 24 | #elif QT_MINOR_ == 4 25 | #define QT_MINOR 4 26 | #elif QT_MINOR_ == 5 27 | #define QT_MINOR 5 28 | #elif QT_MINOR_ == 6 29 | #define QT_MINOR 6 30 | #elif QT_MINOR_ == 7 31 | #define QT_MINOR 7 32 | #elif QT_MINOR_ == 8 33 | #define QT_MINOR 8 34 | #elif QT_MINOR_ == 9 35 | #define QT_MINOR 9 36 | #elif QT_MINOR_ == 10 37 | #define QT_MINOR 10 38 | #else 39 | #error Unupported Qt minor version. Please report. 40 | #endif 41 | 42 | #if QT_MICRO_ == 0 43 | #define QT_MICRO 0 44 | #elif QT_MICRO_ == 1 45 | #define QT_MICRO 1 46 | #elif QT_MICRO_ == 2 47 | #define QT_MICRO 2 48 | #elif QT_MICRO_ == 3 49 | #define QT_MICRO 3 50 | #elif QT_MICRO_ == 4 51 | #define QT_MICRO 4 52 | #elif QT_MICRO_ == 5 53 | #define QT_MICRO 5 54 | #elif QT_MICRO_ == 6 55 | #define QT_MICRO 6 56 | #elif QT_MICRO_ == 7 57 | #define QT_MICRO 7 58 | #elif QT_MICRO_ == 8 59 | #define QT_MICRO 8 60 | #elif QT_MICRO_ == 9 61 | #define QT_MICRO 9 62 | #elif QT_MICRO_ == 10 63 | #define QT_MICRO 10 64 | #else 65 | #error Unupported Qt micro version. Please report. 66 | #endif 67 | 68 | #define QT_PRIVATE_HEADER(dir,file) 69 | 70 | #endif // QTPRIVATE_H 71 | -------------------------------------------------------------------------------- /cpp/qmodelindex.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "qmodelindex.h" 3 | #include "util.cpp" 4 | 5 | 6 | QModelIndex_* newGoModelIndex(QObject_* parent, GoAddr* impl) { 7 | return reinterpret_cast(new GoModelIndex(reinterpret_cast(parent), impl)); 8 | } 9 | 10 | void deleteGoModelIndex(QModelIndex_* im) { 11 | delete reinterpret_cast(im); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /cpp/qmodelindex.h: -------------------------------------------------------------------------------- 1 | #ifndef MODELINDEX_H 2 | #define MODELINDEX_H 3 | 4 | // #include "capi.h" 5 | 6 | typedef void GoAddr; 7 | typedef void QObject_; 8 | typedef void QItemModel_; 9 | typedef void QModelIndex_; 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | QItemModel_* newGoItemModel(QObject_*, GoAddr*); 16 | void deleteGoItemModel(QItemModel_*); 17 | 18 | 19 | #ifdef __cplusplus 20 | } // extern "C" 21 | #endif 22 | 23 | #endif // MODELINDEX_H 24 | 25 | // vim:ts=4:sw=4:et:ft=cpp 26 | -------------------------------------------------------------------------------- /cpp/update-moc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd `dirname $0` 5 | 6 | subdir=`basename $PWD` 7 | 8 | export QT_SELECT=5 9 | 10 | ALL=moc_all.cpp 11 | 12 | echo "// This file is automatically generated by cpp/update-moc.sh" > $ALL 13 | 14 | for file in `grep -l Q_''OBJECT *`; do 15 | mocfile=`echo $file | awk -F. '{print("moc_"$1".cpp")}'` 16 | mochack=`sed -n 's,^ *// MOC HACK: \(.*\),\1,p' $file` 17 | moc $file | sed "$mochack" > $mocfile 18 | echo "#include \"$subdir/$mocfile\"" >> $ALL 19 | done 20 | -------------------------------------------------------------------------------- /cpp/util.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "util.h" 3 | 4 | QString QStringFromGoString(const char *str, unsigned int length) { 5 | QByteArray qstrarray(str, length); 6 | return QString::fromUtf8(qstrarray); 7 | } 8 | -------------------------------------------------------------------------------- /cpp/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | #include 5 | 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | 12 | 13 | QString QStringFromGoString(const char *str, unsigned int length); 14 | 15 | 16 | 17 | #ifdef __cplusplus 18 | } // extern "C" 19 | #endif 20 | 21 | #endif // UTIL_H 22 | -------------------------------------------------------------------------------- /cpptest/cpptest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cpptest.h" 4 | #include "testtype.h" 5 | 6 | TestType_ *newTestType() 7 | { 8 | return new TestType(); 9 | } 10 | 11 | int plainTestTypeN(PlainTestType_ *plain) 12 | { 13 | return static_cast(plain)->n; 14 | } 15 | -------------------------------------------------------------------------------- /cpptest/cpptest.go: -------------------------------------------------------------------------------- 1 | // Package cpptest is an internal test helper. 2 | package cpptest 3 | 4 | // #cgo CXXFLAGS: -std=c++0x -Wall -fno-strict-aliasing -I.. 5 | // #cgo LDFLAGS: -lstdc++ 6 | // 7 | // #cgo pkg-config: Qt5Core 8 | // 9 | // #include "cpptest.h" 10 | // 11 | import "C" 12 | 13 | import ( 14 | "unsafe" 15 | 16 | "github.com/limetext/qml-go" 17 | ) 18 | 19 | func NewTestType(engine *qml.Engine) qml.Object { 20 | var obj qml.Object 21 | qml.RunMain(func() { 22 | addr := C.newTestType() 23 | obj = qml.CommonOf(addr, engine) 24 | }) 25 | return obj 26 | } 27 | 28 | func PlainTestTypeN(obj qml.Object) int { 29 | return int(C.plainTestTypeN(unsafe.Pointer(obj.Property("plainAddr").(uintptr)))) 30 | } 31 | -------------------------------------------------------------------------------- /cpptest/cpptest.h: -------------------------------------------------------------------------------- 1 | #ifndef UONEAUTH_H 2 | #define UONEAUTH_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef void TestType_; 9 | typedef void PlainTestType_; 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | TestType_ *newTestType(); 16 | 17 | int plainTestTypeN(PlainTestType_ *plain); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif // UONEAUTH_H 24 | -------------------------------------------------------------------------------- /cpptest/testtype.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTTYPE_H 2 | #define TESTTYPE_H 3 | 4 | #include 5 | 6 | class PlainTestType { 7 | 8 | public: 9 | 10 | PlainTestType(int n) : n(n) {}; 11 | 12 | int n; 13 | }; 14 | 15 | class TestType : public QObject 16 | { 17 | Q_OBJECT 18 | 19 | Q_PROPERTY(void *voidAddr READ getVoidAddr) 20 | 21 | void *voidAddr; 22 | 23 | public: 24 | 25 | TestType(QObject *parent = 0) : QObject(parent), voidAddr((void*)42) {}; 26 | 27 | void *getVoidAddr() { return voidAddr; }; 28 | 29 | Q_INVOKABLE void emitPlain() { 30 | PlainTestType plain = PlainTestType(42); 31 | emit plainEmittedCpy(plain); 32 | emit plainEmittedRef(plain); 33 | emit plainEmittedPtr(&plain); 34 | }; 35 | 36 | signals: 37 | 38 | void plainEmittedCpy(const PlainTestType plain); 39 | void plainEmittedRef(const PlainTestType &plain); 40 | void plainEmittedPtr(const PlainTestType *plain); 41 | }; 42 | 43 | #endif // TESTTYPE_H 44 | 45 | // vim:ts=4:sw=4:et 46 | -------------------------------------------------------------------------------- /cpptest/update-moc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd `dirname $0` 5 | 6 | export QT_SELECT=5 7 | 8 | for file in `grep -l Q_''OBJECT *`; do 9 | mocfile=`echo $file | awk -F. '{print("moc_"$1".cpp")}'` 10 | mochack=`sed -n 's,^ *// MOC HACK: \(.*\),\1,p' $file` 11 | moc $file | sed "$mochack" > $mocfile 12 | done 13 | -------------------------------------------------------------------------------- /examples/controls/.gitignore: -------------------------------------------------------------------------------- 1 | basiclayouts/basiclayouts 2 | gallery/gallery 3 | splitview/splitview 4 | tableview/tableview 5 | touch/touch 6 | -------------------------------------------------------------------------------- /examples/controls/README.md: -------------------------------------------------------------------------------- 1 | These examples were ported from [qtquickcontrols](git@gitorious.org:qt/qtquickcontrols.git). 2 | 3 | Only the basic ones were ported, in order to demonstrate how easy it is to create a full-fledged UI with Go and QML. 4 | 5 | There were a few more, but they that had native modules and those were omitted due to laziness. 6 | 7 | In order to run them you might need some extra Qt5 plugins. On Ubuntu those can be installed using this command: 8 | sudo apt-get install qtdeclarative5-controls-plugin qtdeclarative5-xmllistmodel-plugin 9 | -------------------------------------------------------------------------------- /examples/controls/basiclayouts/basiclayouts.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | controls, err := engine.LoadFile("main.qml") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | window := controls.CreateWindow(nil) 26 | 27 | window.Show() 28 | window.Wait() 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /examples/controls/basiclayouts/main.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Layouts 1.0 48 | 49 | ApplicationWindow { 50 | visible: true 51 | title: "Basic layouts" 52 | property int margin: 11 53 | width: mainLayout.implicitWidth + 2 * margin 54 | height: mainLayout.implicitHeight + 2 * margin 55 | minimumWidth: mainLayout.Layout.minimumWidth + 2 * margin 56 | minimumHeight: mainLayout.Layout.minimumHeight + 2 * margin 57 | 58 | ColumnLayout { 59 | id: mainLayout 60 | anchors.fill: parent 61 | anchors.margins: margin 62 | GroupBox { 63 | id: rowBox 64 | title: "Row layout" 65 | Layout.fillWidth: true 66 | 67 | RowLayout { 68 | id: rowLayout 69 | anchors.fill: parent 70 | TextField { 71 | placeholderText: "This wants to grow horizontally" 72 | Layout.fillWidth: true 73 | } 74 | Button { 75 | text: "Button" 76 | } 77 | } 78 | } 79 | 80 | GroupBox { 81 | id: gridBox 82 | title: "Grid layout" 83 | Layout.fillWidth: true 84 | 85 | GridLayout { 86 | id: gridLayout 87 | rows: 3 88 | flow: GridLayout.TopToBottom 89 | anchors.fill: parent 90 | 91 | Label { text: "Line 1" } 92 | Label { text: "Line 2" } 93 | Label { text: "Line 3" } 94 | 95 | TextField { } 96 | TextField { } 97 | TextField { } 98 | 99 | TextArea { 100 | text: "This widget spans over three rows in the GridLayout.\n" 101 | + "All items in the GridLayout are implicitly positioned from top to bottom." 102 | Layout.rowSpan: 3 103 | Layout.fillHeight: true 104 | Layout.fillWidth: true 105 | } 106 | } 107 | } 108 | TextArea { 109 | id: t3 110 | text: "This fills the whole cell" 111 | Layout.minimumHeight: 30 112 | Layout.fillHeight: true 113 | Layout.fillWidth: true 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /examples/controls/gallery/content/AboutDialog.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | import QtQuick 2.2 41 | import QtQuick.Dialogs 1.1 42 | 43 | MessageDialog { 44 | icon: StandardIcon.Information 45 | text: "QtQuick.Controls gallery example" 46 | detailedText: "This example demonstrates most of the available Qt Quick Controls." 47 | title: "About Gallery" 48 | } 49 | -------------------------------------------------------------------------------- /examples/controls/gallery/content/ChildWindow.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Window 2.1 47 | import QtQuick.Controls 1.1 48 | 49 | Window { 50 | id: window1 51 | 52 | width: 400 53 | height: 400 54 | 55 | title: "child window" 56 | flags: Qt.Dialog 57 | 58 | Rectangle { 59 | color: syspal.window 60 | anchors.fill: parent 61 | 62 | Label { 63 | id: dimensionsText 64 | anchors.horizontalCenter: parent.horizontalCenter 65 | anchors.top: parent.top 66 | width: parent.width 67 | horizontalAlignment: Text.AlignHCenter 68 | } 69 | 70 | Label { 71 | id: availableDimensionsText 72 | anchors.horizontalCenter: parent.horizontalCenter 73 | anchors.top: dimensionsText.bottom 74 | width: parent.width 75 | horizontalAlignment: Text.AlignHCenter 76 | } 77 | 78 | Label { 79 | id: closeText 80 | anchors.horizontalCenter: parent.horizontalCenter 81 | anchors.top: availableDimensionsText.bottom 82 | text: "This is a new Window, press the\nbutton below to close it again." 83 | } 84 | Button { 85 | anchors.horizontalCenter: closeText.horizontalCenter 86 | anchors.top: closeText.bottom 87 | id: closeWindowButton 88 | text:"Close" 89 | width: 98 90 | tooltip:"Press me, to close this window again" 91 | onClicked: window1.visible = false 92 | } 93 | Button { 94 | anchors.horizontalCenter: closeText.horizontalCenter 95 | anchors.top: closeWindowButton.bottom 96 | id: maximizeWindowButton 97 | text:"Maximize" 98 | width: 98 99 | tooltip:"Press me, to maximize this window again" 100 | onClicked: window1.visibility = Window.Maximized; 101 | } 102 | Button { 103 | anchors.horizontalCenter: closeText.horizontalCenter 104 | anchors.top: maximizeWindowButton.bottom 105 | id: normalizeWindowButton 106 | text:"Normalize" 107 | width: 98 108 | tooltip:"Press me, to normalize this window again" 109 | onClicked: window1.visibility = Window.Windowed; 110 | } 111 | Button { 112 | anchors.horizontalCenter: closeText.horizontalCenter 113 | anchors.top: normalizeWindowButton.bottom 114 | id: minimizeWindowButton 115 | text:"Minimize" 116 | width: 98 117 | tooltip:"Press me, to minimize this window again" 118 | onClicked: window1.visibility = Window.Minimized; 119 | } 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /examples/controls/gallery/content/ImageViewer.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | import QtQuick 2.2 41 | import QtQuick.Window 2.1 42 | 43 | Window { 44 | id: imageViewer 45 | minimumWidth: viewerImage.width 46 | minimumHeight: viewerImage.height 47 | function open(source) { 48 | viewerImage.source = source 49 | width = viewerImage.implicitWidth + 20 50 | height = viewerImage.implicitHeight + 20 51 | title = source 52 | visible = true 53 | } 54 | Image { 55 | id: viewerImage 56 | anchors.centerIn: parent 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/controls/gallery/content/Layouts.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | import QtQuick 2.2 42 | import QtQuick.Controls 1.1 43 | import QtQuick.Layouts 1.0 44 | 45 | Item { 46 | id:root 47 | anchors.fill: parent 48 | anchors.margins: 8 49 | 50 | ColumnLayout { 51 | id: mainLayout 52 | anchors.fill: parent 53 | spacing: 4 54 | GroupBox { 55 | id: rowBox 56 | title: "Row layout" 57 | Layout.fillWidth: true 58 | RowLayout { 59 | id: rowLayout 60 | anchors.fill: parent 61 | TextField { 62 | placeholderText: "This wants to grow horizontally" 63 | Layout.fillWidth: true 64 | } 65 | Button { 66 | text: "Button" 67 | } 68 | } 69 | } 70 | 71 | GroupBox { 72 | id: gridBox 73 | title: "Grid layout" 74 | Layout.fillWidth: true 75 | 76 | GridLayout { 77 | id: gridLayout 78 | anchors.fill: parent 79 | rows: 3 80 | flow: GridLayout.TopToBottom 81 | 82 | Label { text: "Line 1" } 83 | Label { text: "Line 2" } 84 | Label { text: "Line 3" } 85 | 86 | TextField { } 87 | TextField { } 88 | TextField { } 89 | 90 | TextArea { 91 | text: "This widget spans over three rows in the GridLayout.\n" 92 | + "All items in the GridLayout are implicitly positioned from top to bottom." 93 | Layout.rowSpan: 3 94 | Layout.fillHeight: true 95 | Layout.fillWidth: true 96 | } 97 | } 98 | } 99 | TextArea { 100 | id: t3 101 | text: "This fills the whole cell" 102 | Layout.minimumHeight: 30 103 | Layout.fillHeight: true 104 | Layout.fillWidth: true 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/controls/gallery/content/ModelView.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | //import QtQuick.XmlListModel 2.1 48 | 49 | Item { 50 | id: root 51 | width: 600 52 | height: 300 53 | anchors.fill: parent 54 | anchors.margins: Qt.platform.os === "osx" ? 12 : 6 55 | 56 | // XmlListModel { 57 | // id: flickerModel 58 | // source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2&tags=" + "Cat" 59 | // query: "/rss/channel/item" 60 | // namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" 61 | // XmlRole { name: "title"; query: "title/string()" } 62 | // XmlRole { name: "imagesource"; query: "media:thumbnail/@url/string()" } 63 | // XmlRole { name: "credit"; query: "media:credit/string()" } 64 | // } 65 | 66 | ListModel { 67 | id: dummyModel 68 | Component.onCompleted: { 69 | for (var i = 0 ; i < 100 ; ++i) { 70 | append({"index": i, "title": "A title " + i, "imagesource" :"http://someurl.com", "credit" : "N/A"}) 71 | } 72 | } 73 | } 74 | 75 | TableView{ 76 | model: dummyModel 77 | anchors.fill: parent 78 | 79 | TableViewColumn { 80 | role: "index" 81 | title: "#" 82 | width: 36 83 | resizable: false 84 | movable: false 85 | } 86 | TableViewColumn { 87 | role: "title" 88 | title: "Title" 89 | width: 120 90 | } 91 | TableViewColumn { 92 | role: "credit" 93 | title: "Credit" 94 | width: 120 95 | } 96 | TableViewColumn { 97 | role: "imagesource" 98 | title: "Image source" 99 | width: 200 100 | visible: true 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /examples/controls/gallery/gallery.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | controls, err := engine.LoadFile("main.qml") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | window := controls.CreateWindow(nil) 26 | 27 | window.Show() 28 | window.Wait() 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /examples/controls/gallery/images/bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/bubble.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/button-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/button-pressed.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/button.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/document-open.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/document-open@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/document-open@2x.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/document-save-as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/document-save-as.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/document-save-as@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/document-save-as@2x.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/folder_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/folder_new.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/go-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/go-next.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/go-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/go-previous.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/preferences-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/preferences-system.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/process-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/process-stop.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/progress-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/progress-background.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/progress-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/progress-fill.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/slider-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/slider-handle.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/tab.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/tab_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/tab_selected.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/textfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/textfield.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/toplevel_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/toplevel_window.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/view-refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/view-refresh.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/window-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/window-new.png -------------------------------------------------------------------------------- /examples/controls/gallery/images/window-new@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/gallery/images/window-new@2x.png -------------------------------------------------------------------------------- /examples/controls/splitview/main.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Layouts 1.0 48 | 49 | ApplicationWindow { 50 | visible: true 51 | width: 600 52 | height: 400 53 | 54 | SplitView { 55 | anchors.fill: parent 56 | 57 | Rectangle { 58 | id: column 59 | width: 200 60 | Layout.minimumWidth: 100 61 | Layout.maximumWidth: 300 62 | color: "lightsteelblue" 63 | } 64 | 65 | SplitView { 66 | orientation: Qt.Vertical 67 | Layout.fillWidth: true 68 | 69 | Rectangle { 70 | id: row1 71 | height: 200 72 | color: "lightblue" 73 | Layout.minimumHeight: 1 74 | } 75 | 76 | Rectangle { 77 | id: row2 78 | color: "lightgray" 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/controls/splitview/splitview.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | controls, err := engine.LoadFile("main.qml") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | window := controls.CreateWindow(nil) 26 | 27 | window.Show() 28 | window.Wait() 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /examples/controls/tableview/images/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/tableview/images/header.png -------------------------------------------------------------------------------- /examples/controls/tableview/images/selectedrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/tableview/images/selectedrow.png -------------------------------------------------------------------------------- /examples/controls/tableview/tableview.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | controls, err := engine.LoadFile("main.qml") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | window := controls.CreateWindow(nil) 26 | 27 | window.Show() 28 | window.Wait() 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /examples/controls/touch/content/AndroidDelegate.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | 47 | Item { 48 | id: root 49 | width: parent.width 50 | height: 88 51 | 52 | property alias text: textitem.text 53 | signal clicked 54 | 55 | Rectangle { 56 | anchors.fill: parent 57 | color: "#11ffffff" 58 | visible: mouse.pressed 59 | } 60 | 61 | Text { 62 | id: textitem 63 | color: "white" 64 | font.pixelSize: 32 65 | text: modelData 66 | anchors.verticalCenter: parent.verticalCenter 67 | anchors.left: parent.left 68 | anchors.leftMargin: 30 69 | } 70 | 71 | Rectangle { 72 | anchors.left: parent.left 73 | anchors.right: parent.right 74 | anchors.margins: 15 75 | height: 1 76 | color: "#424246" 77 | } 78 | 79 | Image { 80 | anchors.right: parent.right 81 | anchors.rightMargin: 20 82 | anchors.verticalCenter: parent.verticalCenter 83 | source: "../images/navigation_next_item.png" 84 | } 85 | 86 | MouseArea { 87 | id: mouse 88 | anchors.fill: parent 89 | onClicked: root.clicked() 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /examples/controls/touch/content/ListPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Controls.Styles 1.1 48 | 49 | ScrollView { 50 | width: parent.width 51 | height: parent.height 52 | 53 | flickableItem.interactive: true 54 | 55 | ListView { 56 | anchors.fill: parent 57 | model: 100 58 | delegate: AndroidDelegate { 59 | text: "Item #" + modelData 60 | } 61 | } 62 | 63 | style: ScrollViewStyle { 64 | transientScrollBars: true 65 | handle: Item { 66 | implicitWidth: 14 67 | implicitHeight: 26 68 | Rectangle { 69 | color: "#424246" 70 | anchors.fill: parent 71 | anchors.topMargin: 6 72 | anchors.leftMargin: 4 73 | anchors.rightMargin: 4 74 | anchors.bottomMargin: 6 75 | } 76 | } 77 | scrollBarBackground: Item { 78 | implicitWidth: 14 79 | implicitHeight: 26 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/controls/touch/content/ProgressBarPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Controls.Styles 1.1 48 | 49 | Item { 50 | width: parent.width 51 | height: parent.height 52 | 53 | property real progress: 0 54 | SequentialAnimation on progress { 55 | loops: Animation.Infinite 56 | running: true 57 | NumberAnimation { 58 | from: 0 59 | to: 1 60 | duration: 3000 61 | } 62 | NumberAnimation { 63 | from: 1 64 | to: 0 65 | duration: 3000 66 | } 67 | } 68 | 69 | Column { 70 | spacing: 40 71 | anchors.centerIn: parent 72 | 73 | ProgressBar { 74 | anchors.margins: 20 75 | style: touchStyle 76 | width: 400 77 | value: progress 78 | } 79 | 80 | ProgressBar { 81 | anchors.margins: 20 82 | style: touchStyle 83 | width: 400 84 | value: 1 - progress 85 | } 86 | 87 | ProgressBar { 88 | anchors.margins: 20 89 | style: touchStyle 90 | value: 1 91 | width: 400 92 | } 93 | 94 | } 95 | 96 | Component { 97 | id: touchStyle 98 | ProgressBarStyle { 99 | panel: Rectangle { 100 | implicitHeight: 15 101 | implicitWidth: 400 102 | color: "#444" 103 | opacity: 0.8 104 | Rectangle { 105 | antialiasing: true 106 | radius: 1 107 | color: "#468bb7" 108 | height: parent.height 109 | width: parent.width * control.value / control.maximumValue 110 | } 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /examples/controls/touch/content/SliderPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Controls.Styles 1.1 48 | 49 | Item { 50 | width: parent.width 51 | height: parent.height 52 | 53 | Column { 54 | spacing: 12 55 | anchors.centerIn: parent 56 | 57 | Slider { 58 | anchors.margins: 20 59 | style: touchStyle 60 | value: 0 61 | } 62 | Slider { 63 | anchors.margins: 20 64 | style: touchStyle 65 | value: 0.5 66 | } 67 | Slider { 68 | anchors.margins: 20 69 | style: touchStyle 70 | value: 1.0 71 | } 72 | 73 | } 74 | 75 | Component { 76 | id: touchStyle 77 | SliderStyle { 78 | handle: Rectangle { 79 | width: 30 80 | height: 30 81 | radius: height 82 | antialiasing: true 83 | color: Qt.lighter("#468bb7", 1.1) 84 | } 85 | 86 | groove: Item { 87 | implicitHeight: 50 88 | implicitWidth: 400 89 | Rectangle { 90 | height: 8 91 | width: parent.width 92 | anchors.verticalCenter: parent.verticalCenter 93 | color: "#444" 94 | opacity: 0.8 95 | Rectangle { 96 | antialiasing: true 97 | radius: 1 98 | color: "#468bb7" 99 | height: parent.height 100 | width: parent.width * control.value / control.maximumValue 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /examples/controls/touch/content/TabBarPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Controls.Styles 1.1 48 | 49 | Item { 50 | width: parent.width 51 | height: parent.height 52 | 53 | TabView { 54 | anchors.fill: parent 55 | style: touchStyle 56 | Tab { 57 | title: "Buttons" 58 | ButtonPage{ visible: true } 59 | } 60 | Tab { 61 | title: "Sliders" 62 | SliderPage{ visible: true } 63 | } 64 | Tab { 65 | title: "Progress" 66 | ProgressBarPage{ visible: true } 67 | } 68 | } 69 | 70 | Component { 71 | id: touchStyle 72 | TabViewStyle { 73 | tabsAlignment: Qt.AlignVCenter 74 | tabOverlap: 0 75 | frame: Item { } 76 | tab: Item { 77 | implicitWidth: control.width/control.count 78 | implicitHeight: 50 79 | BorderImage { 80 | anchors.fill: parent 81 | border.bottom: 8 82 | border.top: 8 83 | source: styleData.selected ? "../images/tab_selected.png":"../images/tabs_standard.png" 84 | Text { 85 | anchors.centerIn: parent 86 | color: "white" 87 | text: styleData.title.toUpperCase() 88 | font.pixelSize: 16 89 | } 90 | Rectangle { 91 | visible: index > 0 92 | anchors.top: parent.top 93 | anchors.bottom: parent.bottom 94 | anchors.margins: 10 95 | width:1 96 | color: "#3a3a3a" 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /examples/controls/touch/content/TextInputPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | 43 | 44 | 45 | import QtQuick 2.2 46 | import QtQuick.Controls 1.1 47 | import QtQuick.Controls.Styles 1.1 48 | 49 | Item { 50 | width: parent.width 51 | height: parent.height 52 | 53 | property real progress: 0 54 | SequentialAnimation on progress { 55 | loops: Animation.Infinite 56 | running: true 57 | NumberAnimation { 58 | from: 0 59 | to: 1 60 | duration: 3000 61 | } 62 | NumberAnimation { 63 | from: 1 64 | to: 0 65 | duration: 3000 66 | } 67 | } 68 | 69 | Column { 70 | spacing: 40 71 | anchors.centerIn: parent 72 | 73 | TextField { 74 | anchors.margins: 20 75 | text: "Text input" 76 | style: touchStyle 77 | } 78 | 79 | TextField { 80 | anchors.margins: 20 81 | text: "Readonly Text input" 82 | style: touchStyle 83 | readOnly: true 84 | } 85 | } 86 | Component { 87 | id: touchStyle 88 | 89 | TextFieldStyle { 90 | textColor: "white" 91 | font.pixelSize: 28 92 | background: Item { 93 | implicitHeight: 50 94 | implicitWidth: 320 95 | BorderImage { 96 | source: "../images/textinput.png" 97 | border.left: 8 98 | border.right: 8 99 | anchors.bottom: parent.bottom 100 | anchors.left: parent.left 101 | anchors.right: parent.right 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /examples/controls/touch/images/NOTICE.txt: -------------------------------------------------------------------------------- 1 | Notice some of these images are derived from Google applications resources. They were provided under the following license: 2 | You may use the materials in this directory without restriction to develop your apps and to use in your apps. 3 | -------------------------------------------------------------------------------- /examples/controls/touch/images/button_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/button_default.png -------------------------------------------------------------------------------- /examples/controls/touch/images/button_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/button_pressed.png -------------------------------------------------------------------------------- /examples/controls/touch/images/navigation_next_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/navigation_next_item.png -------------------------------------------------------------------------------- /examples/controls/touch/images/navigation_previous_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/navigation_previous_item.png -------------------------------------------------------------------------------- /examples/controls/touch/images/tab_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/tab_selected.png -------------------------------------------------------------------------------- /examples/controls/touch/images/tabs_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/tabs_standard.png -------------------------------------------------------------------------------- /examples/controls/touch/images/textinput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/textinput.png -------------------------------------------------------------------------------- /examples/controls/touch/images/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/controls/touch/images/toolbar.png -------------------------------------------------------------------------------- /examples/controls/touch/main.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Quick Controls module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | import QtQuick 2.2 42 | import QtQuick.Controls 1.1 43 | import "content" 44 | 45 | ApplicationWindow { 46 | visible: true 47 | width: 800 48 | height: 1280 49 | 50 | Rectangle { 51 | color: "#212126" 52 | anchors.fill: parent 53 | } 54 | 55 | toolBar: BorderImage { 56 | border.bottom: 8 57 | source: "images/toolbar.png" 58 | width: parent.width 59 | height: 100 60 | 61 | Rectangle { 62 | id: backButton 63 | width: opacity ? 60 : 0 64 | anchors.left: parent.left 65 | anchors.leftMargin: 20 66 | opacity: stackView.depth > 1 ? 1 : 0 67 | anchors.verticalCenter: parent.verticalCenter 68 | antialiasing: true 69 | height: 60 70 | radius: 4 71 | color: backmouse.pressed ? "#222" : "transparent" 72 | Behavior on opacity { NumberAnimation{} } 73 | Image { 74 | anchors.verticalCenter: parent.verticalCenter 75 | source: "images/navigation_previous_item.png" 76 | } 77 | MouseArea { 78 | id: backmouse 79 | anchors.fill: parent 80 | anchors.margins: -10 81 | onClicked: stackView.pop() 82 | } 83 | } 84 | 85 | Text { 86 | font.pixelSize: 42 87 | Behavior on x { NumberAnimation{ easing.type: Easing.OutCubic} } 88 | x: backButton.x + backButton.width + 20 89 | anchors.verticalCenter: parent.verticalCenter 90 | color: "white" 91 | text: "Widget Gallery" 92 | } 93 | } 94 | 95 | ListModel { 96 | id: pageModel 97 | ListElement { 98 | title: "Buttons" 99 | page: "content/ButtonPage.qml" 100 | } 101 | ListElement { 102 | title: "Sliders" 103 | page: "content/SliderPage.qml" 104 | } 105 | ListElement { 106 | title: "ProgressBar" 107 | page: "content/ProgressBarPage.qml" 108 | } 109 | ListElement { 110 | title: "Tabs" 111 | page: "content/TabBarPage.qml" 112 | } 113 | ListElement { 114 | title: "TextInput" 115 | page: "content/TextInputPage.qml" 116 | } 117 | ListElement { 118 | title: "List" 119 | page: "content/ListPage.qml" 120 | } 121 | } 122 | 123 | StackView { 124 | id: stackView 125 | anchors.fill: parent 126 | // Implements back key navigation 127 | focus: true 128 | Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) { 129 | stackView.pop(); 130 | event.accepted = true; 131 | } 132 | 133 | initialItem: Item { 134 | width: parent.width 135 | height: parent.height 136 | ListView { 137 | model: pageModel 138 | anchors.fill: parent 139 | delegate: AndroidDelegate { 140 | text: title 141 | onClicked: stackView.push(Qt.resolvedUrl(page)) 142 | } 143 | } 144 | } 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /examples/controls/touch/touch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | controls, err := engine.LoadFile("main.qml") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | window := controls.CreateWindow(nil) 26 | 27 | window.Show() 28 | window.Wait() 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /examples/customtype/customtype.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | type GoType struct { 18 | Text string 19 | } 20 | 21 | func (v *GoType) SetText(text string) { 22 | fmt.Println("Text changing to:", text) 23 | v.Text = text 24 | } 25 | 26 | type GoSingleton struct { 27 | Event string 28 | } 29 | 30 | func run() error { 31 | qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ 32 | Init: func(v *GoType, obj qml.Object) {}, 33 | }, { 34 | Init: func(v *GoSingleton, obj qml.Object) { v.Event = "birthday" }, 35 | 36 | Singleton: true, 37 | }}) 38 | 39 | engine := qml.NewEngine() 40 | component, err := engine.LoadFile("customtype.qml") 41 | if err != nil { 42 | return err 43 | } 44 | 45 | value := component.Create(nil) 46 | fmt.Println("Text is:", value.Interface().(*GoType).Text) 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /examples/customtype/customtype.qml: -------------------------------------------------------------------------------- 1 | import GoExtensions 1.0 2 | 3 | GoType { 4 | text: "Happy " + GoSingleton.event + ", Go!" 5 | } 6 | -------------------------------------------------------------------------------- /examples/gopher/gopher.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | "github.com/limetext/qml-go/gl/2.0" 9 | "github.com/limetext/qml-go/qpainter" 10 | ) 11 | 12 | var filename = "gopher.qml" 13 | 14 | func main() { 15 | if len(os.Args) == 2 { 16 | filename = os.Args[1] 17 | } 18 | if err := qml.Run(run); err != nil { 19 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 20 | os.Exit(1) 21 | } 22 | } 23 | 24 | func run() error { 25 | engine := qml.NewEngine() 26 | 27 | model, err := Read("model/gopher.obj") 28 | if err != nil { 29 | return err 30 | } 31 | 32 | qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ 33 | Init: func(g *Gopher, obj qml.Object) { 34 | g.Object = obj 35 | g.model = model 36 | }, 37 | }}) 38 | 39 | component, err := engine.LoadFile(filename) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | win := component.CreateWindow(nil) 45 | win.Set("x", 560) 46 | win.Set("y", 320) 47 | win.Show() 48 | win.Wait() 49 | return nil 50 | } 51 | 52 | type Gopher struct { 53 | qml.Object 54 | 55 | model map[string]*Object 56 | 57 | Rotation int 58 | } 59 | 60 | func (r *Gopher) SetRotation(rotation int) { 61 | r.Rotation = rotation 62 | r.Call("update") 63 | } 64 | 65 | func (r *Gopher) Paint(obj qml.Object, p *qpainter.Painter) { 66 | gl := GL.API(p) 67 | 68 | width := float32(r.Int("width")) 69 | 70 | gl.Enable(GL.BLEND) 71 | gl.BlendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) 72 | 73 | gl.ShadeModel(GL.SMOOTH) 74 | gl.Enable(GL.DEPTH_TEST) 75 | gl.DepthMask(true) 76 | gl.Enable(GL.NORMALIZE) 77 | 78 | gl.Clear(GL.DEPTH_BUFFER_BIT) 79 | 80 | gl.Scalef(width/3, width/3, width/3) 81 | 82 | lka := []float32{0.3, 0.3, 0.3, 1.0} 83 | lkd := []float32{1.0, 1.0, 1.0, 0.0} 84 | lks := []float32{1.0, 1.0, 1.0, 1.0} 85 | lpos := []float32{-2, 6, 3, 1.0} 86 | 87 | gl.Enable(GL.LIGHTING) 88 | gl.Lightfv(GL.LIGHT0, GL.AMBIENT, lka) 89 | gl.Lightfv(GL.LIGHT0, GL.DIFFUSE, lkd) 90 | gl.Lightfv(GL.LIGHT0, GL.SPECULAR, lks) 91 | gl.Lightfv(GL.LIGHT0, GL.POSITION, lpos) 92 | gl.Enable(GL.LIGHT0) 93 | 94 | gl.EnableClientState(GL.NORMAL_ARRAY) 95 | gl.EnableClientState(GL.VERTEX_ARRAY) 96 | 97 | gl.Translatef(1.5, 1.5, 0) 98 | gl.Rotatef(-90, 0, 0, 1) 99 | gl.Rotatef(float32(90+((36000+r.Rotation)%360)), 1, 0, 0) 100 | 101 | gl.Disable(GL.COLOR_MATERIAL) 102 | 103 | for _, obj := range r.model { 104 | for _, group := range obj.Groups { 105 | gl.Materialfv(GL.FRONT, GL.AMBIENT, group.Material.Ambient) 106 | gl.Materialfv(GL.FRONT, GL.DIFFUSE, group.Material.Diffuse) 107 | gl.Materialfv(GL.FRONT, GL.SPECULAR, group.Material.Specular) 108 | gl.Materialf(GL.FRONT, GL.SHININESS, group.Material.Shininess) 109 | gl.VertexPointer(3, GL.FLOAT, 0, group.Vertexes) 110 | gl.NormalPointer(GL.FLOAT, 0, group.Normals) 111 | gl.DrawArrays(GL.TRIANGLES, 0, len(group.Vertexes)/3) 112 | } 113 | } 114 | 115 | gl.Enable(GL.COLOR_MATERIAL) 116 | 117 | gl.DisableClientState(GL.NORMAL_ARRAY) 118 | gl.DisableClientState(GL.VERTEX_ARRAY) 119 | } 120 | -------------------------------------------------------------------------------- /examples/gopher/gopher.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import GoExtensions 1.0 3 | 4 | Rectangle { 5 | width: 640; height: 400 6 | color: "black" 7 | 8 | Gopher { 9 | id: gopher 10 | width: 300; height: 300 11 | anchors.centerIn: parent 12 | 13 | NumberAnimation on rotation { 14 | id: anim 15 | from: 360; to: 0 16 | duration: 5000 17 | loops: Animation.Infinite 18 | } 19 | 20 | MouseArea { 21 | anchors.fill: parent 22 | 23 | property real startX 24 | property real startR 25 | 26 | onPressed: { 27 | startX = mouse.x 28 | startR = gopher.rotation 29 | anim.running = false 30 | } 31 | onReleased: { 32 | anim.from = gopher.rotation + 360 33 | anim.to = gopher.rotation 34 | anim.running = true 35 | } 36 | onPositionChanged: { 37 | gopher.rotation = (36000 + (startR - (mouse.x - startX))) % 360 38 | } 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/gopher/mix.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import GoExtensions 1.0 3 | 4 | Rectangle { 5 | id: root 6 | 7 | width: 640 8 | height: 220 9 | color: "black" 10 | 11 | Rectangle { 12 | x: 20; y: 20; width: 100; height: 100 13 | color: "red" 14 | 15 | SequentialAnimation on x { 16 | loops: Animation.Infinite 17 | NumberAnimation { from: 20; to: 120; duration: 4000; easing.type: Easing.InOutQuad } 18 | NumberAnimation { from: 120; to: 20; duration: 4000; easing.type: Easing.InOutQuad } 19 | } 20 | } 21 | 22 | Rectangle { 23 | x: 40; y: 40; width: 100; height: 100 24 | color: "yellow" 25 | opacity: 0.7 26 | 27 | SequentialAnimation on x { 28 | loops: Animation.Infinite 29 | NumberAnimation { from: 40; to: 220; duration: 4000; easing.type: Easing.InOutQuad } 30 | NumberAnimation { from: 220; to: 40; duration: 4000; easing.type: Easing.InOutQuad } 31 | } 32 | } 33 | 34 | Gopher { 35 | id: gopher 36 | 37 | x: 60; y: 60; width: 100; height: 100 38 | 39 | SequentialAnimation on x { 40 | loops: Animation.Infinite 41 | NumberAnimation { from: 60; to: 320; duration: 4000; easing.type: Easing.InOutQuad } 42 | NumberAnimation { from: 320; to: 60; duration: 4000; easing.type: Easing.InOutQuad } 43 | } 44 | } 45 | 46 | Rectangle { 47 | x: 80; y: 80; width: 100; height: 100 48 | color: "yellow" 49 | opacity: 0.7 50 | 51 | SequentialAnimation on x { 52 | loops: Animation.Infinite 53 | NumberAnimation { from: 80; to: 420; duration: 4000; easing.type: Easing.InOutQuad } 54 | NumberAnimation { from: 420; to: 80; duration: 4000; easing.type: Easing.InOutQuad } 55 | } 56 | } 57 | 58 | Rectangle { 59 | x: 100; y: 100; width: 100; height: 100 60 | color: "red" 61 | 62 | SequentialAnimation on x { 63 | loops: Animation.Infinite 64 | NumberAnimation { from: 100; to: 520; duration: 4000; easing.type: Easing.InOutQuad } 65 | NumberAnimation { from: 520; to: 100; duration: 4000; easing.type: Easing.InOutQuad } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/gopher/model/README.md: -------------------------------------------------------------------------------- 1 | 2 | Author 3 | ------ 4 | 5 | * https://github.com/golang-samples/gopher-3d 6 | 7 | License 8 | ------- 9 | 10 | * http://creativecommons.org/licenses/by/3.0/deed.en 11 | -------------------------------------------------------------------------------- /examples/gopher/model/gopher.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/gopher/model/gopher.blend -------------------------------------------------------------------------------- /examples/gopher/model/gopher.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'gopher.blend' 2 | # Material Count: 7 3 | 4 | newmtl Body 5 | Ns 96.078431 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.000000 0.429367 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | 13 | newmtl Eye-White 14 | Ns 96.078431 15 | Ka 0.000000 0.000000 0.000000 16 | Kd 0.800000 0.800000 0.800000 17 | Ks 1.000000 1.000000 1.000000 18 | Ni 1.000000 19 | d 1.000000 20 | illum 2 21 | 22 | newmtl Material 23 | Ns 96.078431 24 | Ka 0.000000 0.000000 0.000000 25 | Kd 0.640000 0.640000 0.640000 26 | Ks 0.500000 0.500000 0.500000 27 | Ni 1.000000 28 | d 1.000000 29 | illum 2 30 | 31 | newmtl Material.001 32 | Ns 96.078431 33 | Ka 0.000000 0.000000 0.000000 34 | Kd 0.000000 0.000000 0.000000 35 | Ks 0.000000 0.000000 0.000000 36 | Ni 1.000000 37 | d 1.000000 38 | illum 2 39 | 40 | newmtl NoseTop 41 | Ns 96.078431 42 | Ka 0.000000 0.000000 0.000000 43 | Kd 0.000000 0.000000 0.000000 44 | Ks 0.000000 0.000000 0.000000 45 | Ni 1.000000 46 | d 1.000000 47 | illum 2 48 | 49 | newmtl SkinColor 50 | Ns 96.078431 51 | Ka 0.000000 0.000000 0.000000 52 | Kd 0.609017 0.353452 0.144174 53 | Ks 0.500000 0.500000 0.500000 54 | Ni 1.000000 55 | d 1.000000 56 | illum 2 57 | 58 | newmtl Tooth 59 | Ns 96.078431 60 | Ka 0.000000 0.000000 0.000000 61 | Kd 0.640000 0.640000 0.640000 62 | Ks 0.500000 0.500000 0.500000 63 | Ni 1.000000 64 | d 1.000000 65 | illum 2 66 | -------------------------------------------------------------------------------- /examples/imgprovider/imgprovider.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image" 6 | "image/png" 7 | "os" 8 | 9 | "github.com/limetext/qml-go" 10 | ) 11 | 12 | func main() { 13 | if err := qml.Run(run); err != nil { 14 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 15 | os.Exit(1) 16 | } 17 | } 18 | 19 | func run() error { 20 | engine := qml.NewEngine() 21 | engine.AddImageProvider("pwd", func(id string, width, height int) image.Image { 22 | f, err := os.Open(id) 23 | if err != nil { 24 | panic(err) 25 | } 26 | defer f.Close() 27 | image, err := png.Decode(f) 28 | if err != nil { 29 | panic(err) 30 | } 31 | return image 32 | }) 33 | 34 | component, err := engine.LoadFile("imgprovider.qml") 35 | if err != nil { 36 | return err 37 | } 38 | 39 | win := component.CreateWindow(nil) 40 | win.Show() 41 | win.Wait() 42 | 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /examples/imgprovider/imgprovider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Image { 4 | source: "image://pwd/ubuntu-gopher.png" 5 | } 6 | -------------------------------------------------------------------------------- /examples/imgprovider/ubuntu-gopher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/imgprovider/ubuntu-gopher.png -------------------------------------------------------------------------------- /examples/itemmodel/delegate.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image/color" 6 | "math/rand" 7 | "os" 8 | "time" 9 | 10 | "github.com/limetext/qml-go" 11 | ) 12 | 13 | func main() { 14 | if err := qml.Run(run); err != nil { 15 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 16 | os.Exit(1) 17 | } 18 | } 19 | 20 | func run() error { 21 | engine := qml.NewEngine() 22 | colors := NewList(engine) 23 | engine.Context().SetVar("colors", colors) 24 | cls := engine.Context().Var("colors") 25 | fmt.Printf("Colors: %T %v\n", cls, cls) 26 | component, err := engine.LoadFile("delegate.qml") 27 | if err != nil { 28 | return err 29 | } 30 | window := component.CreateWindow(nil) 31 | window.Show() 32 | go func() { 33 | n := func() uint8 { return uint8(rand.Intn(256)) } 34 | for i := 0; i < 100; i++ { 35 | colors.Add(color.RGBA{n(), n(), n(), 0xff}) 36 | time.Sleep(1 * time.Second) 37 | } 38 | }() 39 | window.Wait() 40 | return nil 41 | } 42 | 43 | type List struct { 44 | qml.ItemModel 45 | internal qml.ItemModelInternal 46 | list []color.RGBA 47 | } 48 | 49 | var _ qml.ItemModelImpl = &List{} 50 | 51 | func NewList(engine *qml.Engine) *List { 52 | list := &List{} 53 | list.ItemModel, list.internal = qml.NewItemModel(engine, nil, list) 54 | return list 55 | } 56 | 57 | func (l *List) Add(c color.RGBA) { 58 | qml.RunMain(func() { 59 | l.internal.BeginInsertRows(nil, len(l.list), len(l.list)) 60 | l.list = append(l.list, c) 61 | l.internal.EndInsertRows() 62 | }) 63 | } 64 | 65 | func (l *List) validateModelIndex(mi qml.ModelIndex) bool { 66 | column := mi.Column() 67 | row := mi.Row() 68 | return mi.IsValid() && column == 0 && row >= 0 && row < len(l.list) 69 | } 70 | 71 | func fmtMI(mi qml.ModelIndex) string { 72 | if !mi.IsValid() { 73 | return "ModelIndex{invalid}" 74 | } 75 | return fmt.Sprintf("ModelIndex{%v, %v, %v}", mi.Row(), mi.Column(), mi.InternalId()) 76 | } 77 | 78 | // Required functions 79 | func (l *List) ColumnCount(parent qml.ModelIndex) int { 80 | fmt.Println("ColumnCount:", fmtMI(parent)) 81 | return 1 82 | } 83 | 84 | func (l *List) RowCount(parent qml.ModelIndex) int { 85 | fmt.Println("RowCount:", fmtMI(parent), len(l.list)) 86 | return len(l.list) 87 | } 88 | 89 | func (l *List) Data(index qml.ModelIndex, role qml.Role) interface{} { 90 | fmt.Println("Data:", fmtMI(index), role) 91 | return l.list[index.Row()] 92 | } 93 | 94 | func (l *List) Index(row int, column int, parent qml.ModelIndex) qml.ModelIndex { 95 | // fmt.Println("Index:", row, column, fmtMI(parent)) 96 | if !parent.IsValid() && column == 0 && row >= 0 && row < len(l.list) { 97 | return l.internal.CreateIndex(row, column, 0) 98 | } 99 | return nil 100 | } 101 | 102 | func (l *List) Parent(index qml.ModelIndex) qml.ModelIndex { 103 | // fmt.Println("Parent:", index) 104 | return nil 105 | } 106 | 107 | // Required for editing 108 | func (l *List) Flags(index qml.ModelIndex) qml.ItemFlags { 109 | fmt.Println("Flags:", fmtMI(index)) 110 | return qml.NoItemFlags 111 | } 112 | 113 | func (l *List) SetData(index qml.ModelIndex, value interface{}, role qml.Role) bool { 114 | fmt.Println("SetData:", fmtMI(index), role, value) 115 | if !l.validateModelIndex(index) { 116 | return false 117 | } 118 | rgba, ok := value.(color.RGBA) 119 | if !ok { 120 | return false 121 | } 122 | l.list[index.Row()] = rgba 123 | return true 124 | } 125 | -------------------------------------------------------------------------------- /examples/itemmodel/delegate.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | width: 320; height: 200 5 | 6 | Component.onCompleted: { 7 | console.log("colors:", colors); 8 | } 9 | 10 | ListView { 11 | width: 120; 12 | model: colors 13 | delegate: Text { 14 | text: "I am color number: " + index 15 | color: display 16 | } 17 | anchors.top: parent.top 18 | anchors.bottom: parent.bottom 19 | anchors.horizontalCenter: parent.horizontalCenter 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/modelview/delegate/delegate.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image/color" 6 | "math/rand" 7 | "os" 8 | "time" 9 | 10 | "github.com/limetext/qml-go" 11 | ) 12 | 13 | func main() { 14 | if err := qml.Run(run); err != nil { 15 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 16 | os.Exit(1) 17 | } 18 | } 19 | 20 | func run() error { 21 | engine := qml.NewEngine() 22 | colors := &Colors{} 23 | engine.Context().SetVar("colors", colors) 24 | component, err := engine.LoadFile("delegate.qml") 25 | if err != nil { 26 | return err 27 | } 28 | window := component.CreateWindow(nil) 29 | window.Show() 30 | go func() { 31 | n := func() uint8 { return uint8(rand.Intn(256)) } 32 | for i := 0; i < 100; i++ { 33 | colors.Add(color.RGBA{n(), n(), n(), 0xff}) 34 | time.Sleep(1 * time.Second) 35 | } 36 | }() 37 | window.Wait() 38 | return nil 39 | } 40 | 41 | type Colors struct { 42 | list []color.RGBA 43 | Len int 44 | } 45 | 46 | func (colors *Colors) Add(c color.RGBA) { 47 | colors.list = append(colors.list, c) 48 | colors.Len = len(colors.list) 49 | qml.Changed(colors, &colors.Len) 50 | } 51 | 52 | func (colors *Colors) Color(index int) color.RGBA { 53 | return colors.list[index] 54 | } 55 | -------------------------------------------------------------------------------- /examples/modelview/delegate/delegate.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | width: 320; height: 200 5 | 6 | ListView { 7 | width: 120; 8 | model: colors.len 9 | delegate: Text { 10 | text: "I am color number: " + index 11 | color: colors.color(index) 12 | } 13 | anchors.top: parent.top 14 | anchors.bottom: parent.bottom 15 | anchors.horizontalCenter: parent.horizontalCenter 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/painting-es2/painting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | "github.com/limetext/qml-go/gl/es2" 9 | "github.com/limetext/qml-go/qpainter" 10 | ) 11 | 12 | func main() { 13 | if err := qml.Run(run); err != nil { 14 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 15 | os.Exit(1) 16 | } 17 | } 18 | 19 | func run() error { 20 | qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ 21 | Init: func(r *GoRect, obj qml.Object) { r.Object = obj }, 22 | }}) 23 | 24 | engine := qml.NewEngine() 25 | component, err := engine.LoadFile("painting.qml") 26 | if err != nil { 27 | return err 28 | } 29 | 30 | win := component.CreateWindow(nil) 31 | win.Show() 32 | win.Wait() 33 | return nil 34 | } 35 | 36 | type GoRect struct { 37 | qml.Object 38 | } 39 | 40 | var vertexShader = ` 41 | #version 120 42 | 43 | attribute vec2 position; 44 | 45 | void main() 46 | { 47 | gl_Position = vec4(position.x, position.y, 0.0, 1.0); 48 | } 49 | ` 50 | 51 | var fragmentShader = ` 52 | #version 120 53 | 54 | void main() 55 | { 56 | gl_FragColor = vec4(1.0, 1.0, 1.0, 0.8); 57 | } 58 | ` 59 | 60 | func (r *GoRect) Paint(obj qml.Object, p *qpainter.Painter) { 61 | gl := GL.API(p) 62 | 63 | vertices := []float32{ 64 | -1, -1, 65 | +1, -1, 66 | +1, +1, 67 | -1, +1, 68 | } 69 | 70 | indices := []uint8{ 71 | 0, 1, 2, // first triangle 72 | 2, 3, 0, // second triangle 73 | } 74 | 75 | buf := gl.GenBuffers(2) 76 | gl.BindBuffer(GL.ARRAY_BUFFER, buf[0]) 77 | gl.BufferData(GL.ARRAY_BUFFER, 0, vertices, GL.STATIC_DRAW) 78 | gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, buf[1]) 79 | gl.BufferData(GL.ELEMENT_ARRAY_BUFFER, 0, indices, GL.STATIC_DRAW) 80 | 81 | vshader := gl.CreateShader(GL.VERTEX_SHADER) 82 | gl.ShaderSource(vshader, vertexShader) 83 | gl.CompileShader(vshader) 84 | 85 | var status [1]int32 86 | gl.GetShaderiv(vshader, GL.COMPILE_STATUS, status[:]) 87 | if status[0] == 0 { 88 | log := gl.GetShaderInfoLog(vshader) 89 | panic("vertex shader compilation failed: " + string(log)) 90 | } 91 | 92 | fshader := gl.CreateShader(GL.FRAGMENT_SHADER) 93 | gl.ShaderSource(fshader, fragmentShader) 94 | gl.CompileShader(fshader) 95 | 96 | gl.GetShaderiv(fshader, GL.COMPILE_STATUS, status[:]) 97 | if status[0] == 0 { 98 | log := gl.GetShaderInfoLog(fshader) 99 | panic("fragment shader compilation failed: " + string(log)) 100 | } 101 | 102 | program := gl.CreateProgram() 103 | gl.AttachShader(program, vshader) 104 | gl.AttachShader(program, fshader) 105 | gl.LinkProgram(program) 106 | gl.UseProgram(program) 107 | 108 | position := gl.GetAttribLocation(program, "position") 109 | gl.VertexAttribPointer(position, 2, GL.FLOAT, false, 0, 0) 110 | gl.EnableVertexAttribArray(position) 111 | 112 | gl.Enable(GL.BLEND) 113 | gl.BlendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) 114 | 115 | gl.DrawElements(GL.TRIANGLES, 6, GL.UNSIGNED_BYTE, nil) 116 | } 117 | -------------------------------------------------------------------------------- /examples/painting-es2/painting.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import GoExtensions 1.0 3 | 4 | Rectangle { 5 | id: root 6 | 7 | width: 640 8 | height: 280 9 | color: "black" 10 | 11 | Rectangle { 12 | x: 20; y: 20; width: 100; height: 100 13 | color: "red" 14 | 15 | SequentialAnimation on x { 16 | loops: Animation.Infinite 17 | NumberAnimation { from: 20; to: 120; duration: 4000; easing.type: Easing.InOutQuad } 18 | NumberAnimation { from: 120; to: 20; duration: 4000; easing.type: Easing.InOutQuad } 19 | } 20 | } 21 | 22 | Rectangle { 23 | x: 40; y: 40; width: 100; height: 100 24 | color: "yellow" 25 | opacity: 0.7 26 | 27 | SequentialAnimation on x { 28 | loops: Animation.Infinite 29 | NumberAnimation { from: 40; to: 220; duration: 4000; easing.type: Easing.InOutQuad } 30 | NumberAnimation { from: 220; to: 40; duration: 4000; easing.type: Easing.InOutQuad } 31 | } 32 | } 33 | 34 | GoRect { 35 | x: 60; y: 60; width: 100; height: 100 36 | 37 | SequentialAnimation on x { 38 | loops: Animation.Infinite 39 | NumberAnimation { from: 60; to: 320; duration: 4000; easing.type: Easing.InOutQuad } 40 | NumberAnimation { from: 320; to: 60; duration: 4000; easing.type: Easing.InOutQuad } 41 | } 42 | } 43 | 44 | Rectangle { 45 | x: 80; y: 80; width: 100; height: 100 46 | color: "yellow" 47 | opacity: 0.7 48 | 49 | SequentialAnimation on x { 50 | loops: Animation.Infinite 51 | NumberAnimation { from: 80; to: 420; duration: 4000; easing.type: Easing.InOutQuad } 52 | NumberAnimation { from: 420; to: 80; duration: 4000; easing.type: Easing.InOutQuad } 53 | } 54 | } 55 | 56 | Rectangle { 57 | x: 100; y: 100; width: 100; height: 100 58 | color: "red" 59 | 60 | SequentialAnimation on x { 61 | loops: Animation.Infinite 62 | NumberAnimation { from: 100; to: 520; duration: 4000; easing.type: Easing.InOutQuad } 63 | NumberAnimation { from: 520; to: 100; duration: 4000; easing.type: Easing.InOutQuad } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/painting/painting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | "github.com/limetext/qml-go/gl/2.0" 9 | "github.com/limetext/qml-go/qpainter" 10 | ) 11 | 12 | func main() { 13 | if err := qml.Run(run); err != nil { 14 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 15 | os.Exit(1) 16 | } 17 | } 18 | 19 | type GoRect struct { 20 | qml.Object 21 | } 22 | 23 | func (r *GoRect) Paint(obj qml.Object, p *qpainter.Painter) { 24 | gl := GL.API(p) 25 | 26 | width := float32(r.Int("width")) 27 | height := float32(r.Int("height")) 28 | 29 | gl.Enable(GL.BLEND) 30 | gl.BlendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) 31 | gl.Color4f(1.0, 1.0, 1.0, 0.8) 32 | gl.Begin(GL.QUADS) 33 | gl.Vertex2f(0, 0) 34 | gl.Vertex2f(width, 0) 35 | gl.Vertex2f(width, height) 36 | gl.Vertex2f(0, height) 37 | gl.End() 38 | 39 | gl.LineWidth(2.5) 40 | gl.Color4f(0.0, 0.0, 0.0, 1.0) 41 | gl.Begin(GL.LINES) 42 | gl.Vertex2f(0, 0) 43 | gl.Vertex2f(width, height) 44 | gl.Vertex2f(width, 0) 45 | gl.Vertex2f(0, height) 46 | gl.End() 47 | } 48 | 49 | func run() error { 50 | qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ 51 | Init: func(r *GoRect, obj qml.Object) { r.Object = obj }, 52 | }}) 53 | 54 | engine := qml.NewEngine() 55 | component, err := engine.LoadFile("painting.qml") 56 | if err != nil { 57 | return err 58 | } 59 | 60 | win := component.CreateWindow(nil) 61 | win.Show() 62 | win.Wait() 63 | 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /examples/painting/painting.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import GoExtensions 1.0 3 | 4 | Rectangle { 5 | id: root 6 | 7 | width: 640 8 | height: 280 9 | color: "black" 10 | 11 | Rectangle { 12 | x: 20; y: 20; width: 100; height: 100 13 | color: "red" 14 | 15 | SequentialAnimation on x { 16 | loops: Animation.Infinite 17 | NumberAnimation { from: 20; to: 120; duration: 4000; easing.type: Easing.InOutQuad } 18 | NumberAnimation { from: 120; to: 20; duration: 4000; easing.type: Easing.InOutQuad } 19 | } 20 | } 21 | 22 | Rectangle { 23 | x: 40; y: 40; width: 100; height: 100 24 | color: "yellow" 25 | opacity: 0.7 26 | 27 | SequentialAnimation on x { 28 | loops: Animation.Infinite 29 | NumberAnimation { from: 40; to: 220; duration: 4000; easing.type: Easing.InOutQuad } 30 | NumberAnimation { from: 220; to: 40; duration: 4000; easing.type: Easing.InOutQuad } 31 | } 32 | } 33 | 34 | GoRect { 35 | x: 60; y: 60; width: 100; height: 100 36 | 37 | SequentialAnimation on x { 38 | loops: Animation.Infinite 39 | NumberAnimation { from: 60; to: 320; duration: 4000; easing.type: Easing.InOutQuad } 40 | NumberAnimation { from: 320; to: 60; duration: 4000; easing.type: Easing.InOutQuad } 41 | } 42 | } 43 | 44 | Rectangle { 45 | x: 80; y: 80; width: 100; height: 100 46 | color: "yellow" 47 | opacity: 0.7 48 | 49 | SequentialAnimation on x { 50 | loops: Animation.Infinite 51 | NumberAnimation { from: 80; to: 420; duration: 4000; easing.type: Easing.InOutQuad } 52 | NumberAnimation { from: 420; to: 80; duration: 4000; easing.type: Easing.InOutQuad } 53 | } 54 | } 55 | 56 | Rectangle { 57 | x: 100; y: 100; width: 100; height: 100 58 | color: "red" 59 | 60 | SequentialAnimation on x { 61 | loops: Animation.Infinite 62 | NumberAnimation { from: 100; to: 520; duration: 4000; easing.type: Easing.InOutQuad } 63 | NumberAnimation { from: 520; to: 100; duration: 4000; easing.type: Easing.InOutQuad } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/particle/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "os" 7 | "time" 8 | 9 | "github.com/limetext/qml-go" 10 | ) 11 | 12 | func main() { 13 | if err := qml.Run(run); err != nil { 14 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 15 | os.Exit(1) 16 | } 17 | } 18 | 19 | func run() error { 20 | engine := qml.NewEngine() 21 | component, err := engine.LoadFile("particle.qml") 22 | if err != nil { 23 | return err 24 | } 25 | 26 | ctrl := Control{Message: "Hello from Go!"} 27 | 28 | context := engine.Context() 29 | context.SetVar("ctrl", &ctrl) 30 | 31 | window := component.CreateWindow(nil) 32 | 33 | ctrl.Root = window.Root() 34 | 35 | rand.Seed(time.Now().Unix()) 36 | 37 | window.Show() 38 | window.Wait() 39 | 40 | return nil 41 | } 42 | 43 | type Control struct { 44 | Root qml.Object 45 | Message string 46 | } 47 | 48 | func (ctrl *Control) TextReleased(text qml.Object) { 49 | x := text.Int("x") 50 | y := text.Int("y") 51 | width := text.Int("width") 52 | height := text.Int("height") 53 | 54 | ctrl.Emit(x+15, y+height/2) 55 | ctrl.Emit(x+width/2, 1.0*y+height/2) 56 | ctrl.Emit(x+width-15, 1.0*y+height/2) 57 | 58 | go func() { 59 | time.Sleep(500 * time.Millisecond) 60 | messages := []string{"Hello", "Hello", "Hacks"} 61 | ctrl.Message = messages[rand.Intn(len(messages))] + " from Go!" 62 | qml.Changed(ctrl, &ctrl.Message) 63 | }() 64 | } 65 | 66 | func (ctrl *Control) Emit(x, y int) { 67 | component := ctrl.Root.Object("emitterComponent") 68 | for i := 0; i < 8; i++ { 69 | emitter := component.Create(nil) 70 | emitter.Set("x", x) 71 | emitter.Set("y", y) 72 | emitter.Set("targetX", rand.Intn(240)-120+x) 73 | emitter.Set("targetY", rand.Intn(240)-120+y) 74 | emitter.Set("life", rand.Intn(2400)+200) 75 | emitter.Set("emitRate", rand.Intn(32)+32) 76 | emitter.ObjectByName("xAnim").Call("start") 77 | emitter.ObjectByName("yAnim").Call("start") 78 | emitter.Set("enabled", true) 79 | } 80 | } 81 | 82 | func (ctrl *Control) Done(emitter qml.Object) { 83 | emitter.Destroy() 84 | } 85 | -------------------------------------------------------------------------------- /examples/particle/particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/particle/particle.png -------------------------------------------------------------------------------- /examples/particle/particle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Particles 2.0 3 | import QtGraphicalEffects 1.0; 4 | 5 | Rectangle { 6 | id: root 7 | 8 | width: 640 9 | height: 480 10 | 11 | gradient: Gradient { 12 | GradientStop { position: 0.0; color: "#3a2c32"; } 13 | GradientStop { position: 0.8; color: "#875864"; } 14 | GradientStop { position: 1.0; color: "#9b616c"; } 15 | } 16 | 17 | Text { 18 | text: ctrl.message 19 | 20 | Component.onCompleted: { 21 | x = parent.width/2 - width/2 22 | y = parent.height/2 - height/2 23 | } 24 | 25 | color: "white" 26 | font.bold: true 27 | font.pointSize: 20 28 | 29 | MouseArea { 30 | id: mouseArea 31 | anchors.fill: parent 32 | drag.target: parent 33 | onReleased: ctrl.textReleased(parent) 34 | } 35 | } 36 | 37 | ParticleSystem { id: sys } 38 | 39 | ImageParticle { 40 | system: sys 41 | source: "particle.png" 42 | color: "white" 43 | colorVariation: 1.0 44 | alpha: 0.1 45 | } 46 | 47 | property var emitterComponent: Component { 48 | id: emitterComponent 49 | Emitter { 50 | id: container 51 | system: sys 52 | Emitter { 53 | system: sys 54 | emitRate: 128 55 | lifeSpan: 600 56 | size: 16 57 | endSize: 8 58 | velocity: AngleDirection { angleVariation:360; magnitude: 60 } 59 | } 60 | 61 | property int life: 2600 62 | property real targetX: 0 63 | property real targetY: 0 64 | emitRate: 128 65 | lifeSpan: 600 66 | size: 24 67 | endSize: 8 68 | NumberAnimation on x { 69 | objectName: "xAnim" 70 | id: xAnim; 71 | to: targetX 72 | duration: life 73 | running: false 74 | } 75 | NumberAnimation on y { 76 | objectName: "yAnim" 77 | id: yAnim; 78 | to: targetY 79 | duration: life 80 | running: false 81 | } 82 | Timer { 83 | interval: life 84 | running: true 85 | onTriggered: ctrl.done(container) 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /examples/qmlscene/Cell.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | id: container 5 | property alias cellColor: rectangle.color 6 | signal clicked(color cellColor) 7 | 8 | width: 40; height: 25 9 | 10 | Rectangle { 11 | id: rectangle 12 | border.color: "white" 13 | anchors.fill: parent 14 | } 15 | 16 | MouseArea { 17 | anchors.fill: parent 18 | onClicked: container.clicked(container.cellColor) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/qmlscene/qmlscene.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if len(os.Args) != 2 { 12 | fmt.Fprintf(os.Stderr, "usage: %s \n", os.Args[0]) 13 | os.Exit(1) 14 | } 15 | if err := qml.Run(run); err != nil { 16 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 17 | os.Exit(1) 18 | } 19 | } 20 | 21 | func run() error { 22 | engine := qml.NewEngine() 23 | 24 | engine.On("quit", func() { os.Exit(0) }) 25 | 26 | component, err := engine.LoadFile(os.Args[1]) 27 | if err != nil { 28 | return err 29 | } 30 | window := component.CreateWindow(nil) 31 | window.Show() 32 | window.Wait() 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /examples/qmlscene/tutorial1.qml: -------------------------------------------------------------------------------- 1 | // See http://qt-project.org/doc/qt-5.1/qtquick/qml-tutorial1.html 2 | 3 | import QtQuick 2.0 4 | 5 | Rectangle { 6 | id: page 7 | width: 320; height: 480 8 | color: "lightgray" 9 | 10 | Text { 11 | id: helloText 12 | text: "Hello world!" 13 | y: 30 14 | anchors.horizontalCenter: page.horizontalCenter 15 | font.pointSize: 24; font.bold: true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/qmlscene/tutorial2.qml: -------------------------------------------------------------------------------- 1 | // See http://qt-project.org/doc/qt-5.1/qtquick/qml-tutorial2.html 2 | 3 | import QtQuick 2.0 4 | 5 | Rectangle { 6 | id: page 7 | width: 320; height: 480 8 | color: "lightgray" 9 | 10 | Text { 11 | id: helloText 12 | text: "Hello world!" 13 | y: 30 14 | anchors.horizontalCenter: page.horizontalCenter 15 | font.pointSize: 24; font.bold: true 16 | } 17 | 18 | Grid { 19 | id: colorPicker 20 | x: 4; anchors.bottom: page.bottom; anchors.bottomMargin: 4 21 | rows: 2; columns: 3; spacing: 3 22 | 23 | Cell { cellColor: "red"; onClicked: helloText.color = cellColor } 24 | Cell { cellColor: "green"; onClicked: helloText.color = cellColor } 25 | Cell { cellColor: "blue"; onClicked: helloText.color = cellColor } 26 | Cell { cellColor: "yellow"; onClicked: helloText.color = cellColor } 27 | Cell { cellColor: "steelblue"; onClicked: helloText.color = cellColor } 28 | Cell { cellColor: "black"; onClicked: helloText.color = cellColor } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/qmlscene/tutorial3.qml: -------------------------------------------------------------------------------- 1 | // See http://qt-project.org/doc/qt-5.1/qtquick/qml-tutorial3.html 2 | 3 | import QtQuick 2.0 4 | 5 | Rectangle { 6 | id: page 7 | width: 320; height: 480 8 | color: "lightgray" 9 | 10 | Text { 11 | id: helloText 12 | text: "Hello world!" 13 | y: 30 14 | anchors.horizontalCenter: page.horizontalCenter 15 | font.pointSize: 24; font.bold: true 16 | 17 | MouseArea { id: mouseArea; anchors.fill: parent } 18 | 19 | states: State { 20 | name: "down"; when: mouseArea.pressed == true 21 | PropertyChanges { target: helloText; y: 160; rotation: 180; color: "red" } 22 | } 23 | 24 | transitions: Transition { 25 | from: ""; to: "down"; reversible: true 26 | ParallelAnimation { 27 | NumberAnimation { properties: "y,rotation"; duration: 500; easing.type: Easing.InOutQuad } 28 | ColorAnimation { duration: 500 } 29 | } 30 | } 31 | } 32 | 33 | Grid { 34 | id: colorPicker 35 | x: 4; anchors.bottom: page.bottom; anchors.bottomMargin: 4 36 | rows: 2; columns: 3; spacing: 3 37 | 38 | Cell { cellColor: "red"; onClicked: helloText.color = cellColor } 39 | Cell { cellColor: "green"; onClicked: helloText.color = cellColor } 40 | Cell { cellColor: "blue"; onClicked: helloText.color = cellColor } 41 | Cell { cellColor: "yellow"; onClicked: helloText.color = cellColor } 42 | Cell { cellColor: "steelblue"; onClicked: helloText.color = cellColor } 43 | Cell { cellColor: "black"; onClicked: helloText.color = cellColor } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/qrcpacking/assets/particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limetext/qml-go/e895a291f2aa9d05ba936cab85534827b2f17144/examples/qrcpacking/assets/particle.png -------------------------------------------------------------------------------- /examples/qrcpacking/assets/particle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Particles 2.0 3 | import QtGraphicalEffects 1.0; 4 | 5 | Rectangle { 6 | id: root 7 | 8 | width: 640 9 | height: 480 10 | 11 | gradient: Gradient { 12 | GradientStop { position: 0.0; color: "#3a2c32"; } 13 | GradientStop { position: 0.8; color: "#875864"; } 14 | GradientStop { position: 1.0; color: "#9b616c"; } 15 | } 16 | 17 | Text { 18 | text: ctrl.message 19 | 20 | Component.onCompleted: { 21 | x = parent.width/2 - width/2 22 | y = parent.height/2 - height/2 23 | } 24 | 25 | color: "white" 26 | font.bold: true 27 | font.pointSize: 20 28 | 29 | MouseArea { 30 | id: mouseArea 31 | anchors.fill: parent 32 | drag.target: parent 33 | onReleased: ctrl.textReleased(parent) 34 | } 35 | } 36 | 37 | ParticleSystem { id: sys } 38 | 39 | ImageParticle { 40 | system: sys 41 | source: "qrc:///assets/particle.png" 42 | color: "white" 43 | colorVariation: 1.0 44 | alpha: 0.1 45 | } 46 | 47 | property var emitterComponent: Component { 48 | id: emitterComponent 49 | Emitter { 50 | id: container 51 | system: sys 52 | Emitter { 53 | system: sys 54 | emitRate: 128 55 | lifeSpan: 600 56 | size: 16 57 | endSize: 8 58 | velocity: AngleDirection { angleVariation:360; magnitude: 60 } 59 | } 60 | 61 | property int life: 2600 62 | property real targetX: 0 63 | property real targetY: 0 64 | emitRate: 128 65 | lifeSpan: 600 66 | size: 24 67 | endSize: 8 68 | NumberAnimation on x { 69 | objectName: "xAnim" 70 | id: xAnim; 71 | to: targetX 72 | duration: life 73 | running: false 74 | } 75 | NumberAnimation on y { 76 | objectName: "yAnim" 77 | id: yAnim; 78 | to: targetY 79 | duration: life 80 | running: false 81 | } 82 | Timer { 83 | interval: life 84 | running: true 85 | onTriggered: ctrl.done(container) 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /examples/qrcpacking/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate genqrc assets 4 | 5 | import ( 6 | "fmt" 7 | "math/rand" 8 | "os" 9 | "time" 10 | 11 | "github.com/limetext/qml-go" 12 | ) 13 | 14 | func main() { 15 | if err := qml.Run(run); err != nil { 16 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 17 | os.Exit(1) 18 | } 19 | } 20 | 21 | func run() error { 22 | engine := qml.NewEngine() 23 | component, err := engine.LoadFile("qrc:///assets/particle.qml") 24 | if err != nil { 25 | return err 26 | } 27 | 28 | ctrl := Control{Message: "Hello from Go!"} 29 | 30 | context := engine.Context() 31 | context.SetVar("ctrl", &ctrl) 32 | 33 | window := component.CreateWindow(nil) 34 | 35 | ctrl.Root = window.Root() 36 | 37 | rand.Seed(time.Now().Unix()) 38 | 39 | window.Show() 40 | window.Wait() 41 | 42 | return nil 43 | } 44 | 45 | type Control struct { 46 | Root qml.Object 47 | Message string 48 | } 49 | 50 | func (ctrl *Control) TextReleased(text qml.Object) { 51 | x := text.Int("x") 52 | y := text.Int("y") 53 | width := text.Int("width") 54 | height := text.Int("height") 55 | 56 | ctrl.Emit(x+15, y+height/2) 57 | ctrl.Emit(x+width/2, 1.0*y+height/2) 58 | ctrl.Emit(x+width-15, 1.0*y+height/2) 59 | 60 | go func() { 61 | time.Sleep(500 * time.Millisecond) 62 | messages := []string{"Hello", "Hello", "Hacks"} 63 | ctrl.Message = messages[rand.Intn(len(messages))] + " from Go!" 64 | qml.Changed(ctrl, &ctrl.Message) 65 | }() 66 | } 67 | 68 | func (ctrl *Control) Emit(x, y int) { 69 | component := ctrl.Root.Object("emitterComponent") 70 | for i := 0; i < 8; i++ { 71 | emitter := component.Create(nil) 72 | emitter.Set("x", x) 73 | emitter.Set("y", y) 74 | emitter.Set("targetX", rand.Intn(240)-120+x) 75 | emitter.Set("targetY", rand.Intn(240)-120+y) 76 | emitter.Set("life", rand.Intn(2400)+200) 77 | emitter.Set("emitRate", rand.Intn(32)+32) 78 | emitter.ObjectByName("xAnim").Call("start") 79 | emitter.ObjectByName("yAnim").Call("start") 80 | emitter.Set("enabled", true) 81 | } 82 | } 83 | 84 | func (ctrl *Control) Done(emitter qml.Object) { 85 | emitter.Destroy() 86 | } 87 | -------------------------------------------------------------------------------- /examples/qrcpacking/qrc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // This file is automatically generated by github.com/limetext/qml-go/cmd/genqrc 4 | 5 | import ( 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/limetext/qml-go" 11 | ) 12 | 13 | func init() { 14 | var r *qml.Resources 15 | var err error 16 | if os.Getenv("QRC_REPACK") == "1" { 17 | err = qrcRepackResources() 18 | if err != nil { 19 | panic("cannot repack qrc resources: " + err.Error()) 20 | } 21 | r, err = qml.ParseResources(qrcResourcesRepacked) 22 | } else { 23 | r, err = qml.ParseResourcesString(qrcResourcesData) 24 | } 25 | if err != nil { 26 | panic("cannot parse bundled resources data: " + err.Error()) 27 | } 28 | qml.LoadResources(r) 29 | } 30 | 31 | func qrcRepackResources() error { 32 | subdirs := []string{"assets"} 33 | var rp qml.ResourcesPacker 34 | for _, subdir := range subdirs { 35 | err := filepath.Walk(subdir, func(path string, info os.FileInfo, err error) error { 36 | if err != nil { 37 | return err 38 | } 39 | if info.IsDir() { 40 | return nil 41 | } 42 | data, err := ioutil.ReadFile(path) 43 | if err != nil { 44 | return err 45 | } 46 | rp.Add(filepath.ToSlash(path), data) 47 | return nil 48 | }) 49 | if err != nil { 50 | return err 51 | } 52 | } 53 | qrcResourcesRepacked = rp.Pack().Bytes() 54 | return nil 55 | } 56 | 57 | var qrcResourcesRepacked []byte 58 | var qrcResourcesData = "qres\x00\x00\x00\x01\x00\x00\t\xeb\x00\x00\x00\x14\x00\x00\t\x9d\x00\x00\x03]\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \b\x06\x00\x00\x00szz\xf4\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\x02\xffIDATxڔWM\x8f\xd40\fM\xd2t\x96\x0f\xed\xc2a\xf7\x00\a~\x01\xff\xff\x9fp\xe2\xc0\x05\x84\x84\x90X\x81\xc4\x0e\xdb6&\xae\x9c\xea\xcd\xc3閑\xacd\xda\xd4~v\x9e\x1d'\x87\xff\xf8\x89H\xaaC\x93hc\xd1W&:/1F9\xaa3\x9b\xe2\xbd5jh\xb0\xb5\x99\x9e\a3\x1c`^\xd5\xc9\\\xc7Ť\xaf8\xc6\v\x85=\x80W\xe6i\x00\xcf\x11\x84\x10\x90bϳ\x01\x98\xecY?\x02\x1d\xaf\xd5\xf0\b\x86Q\xdc\x1d\x82mXl\u07b6IA\xccG\x01\xe8G\xcf-\xec\tF\xde{6\x8e\\H\x06\"BĢ\x01\xd9\x05\x80\xc6\a\x02\xd18\x90H1\x86\xbe\x98\xa7\xed}!\x1e\bG\x82\x01\\\x81\xe1\f\xe3\b`\"\xf1\x80\xa3о\xe9\x85]\x10T&0#x<\xd8\xff\x11\xfe\xefeJp\xb6*:\xc63\x80\xdd\x00\xe8\xc2g\x90r͋\x93͙\xf9\t\x14F`y\x04\x0ed\xda\x1a\x01\xe7t\xfe\x88\x002(F\xef\xd9\xf3\x04{ޛ\x17\x00\x96\x81\x98\x02\xeb\xb6\"\xd6\x00\x8c\xf00\x01\xe1\xd8x\xa4T\x8c\x94~b\xdf,\xf0\xae9Q(3V\x00\xc9\xca+\xa7\xda@F\xd8x\xdaIS/:\x19\xb6\xb7\x8dj;採\xc1\xa9zhDS\xf5]\x95[c\xfb\xf7*\x9f\xab\xfc&\x1e\b\x01\xc7\xf3#\x06\nst\x1630\x95\x17U\xdeWym$Ue/\xab\xdcT\xf9P\xe5\x81·\xd4ѹ\xea\xcdNU\x8b\x0e\xeb\x11\xd8[3vm`\x16{\xae9\xff\xa6\xca'\xe2Fp\xf4\xfdC\xac^q\t\x8e\xa2W\x90\xa27\x96\xbe\xad~\\;\aT\xcf\xf8\xb6\x05\xd21\xea\xe5}\x006k\x1e\xff4\xcf'\xc8\xf7@\xa1\x96\x8e\xde\xf5}&/e'\x02M~X\xe8U\xf9\x1f3\xfa`r\x0f \x84\xb6\x82\x8fmi\x00\x8as\xa8`\xe1\xc0:\xaf\n\xbf\x1a\xe9f\x8b`\xb1h\xfc\xaa\xf2\xadcP\xbc\xc6E%\xc3\xc1\x80\v\x17\xe2\a\x82SO?V\xb93>Lf\\S\xf1\xdc1Th\xdc\xdegz\x89G*o\x0f\x16\x97\xb3\xe5\xfd\x17\xa7\x17\x10ꀚ\xbeB\xe7\xc2:\xa6ڗa\aS\x80d3\x9d\xe5\x05\xfa<\x9e\xb3\x0e!\xe33\x91t\xb1\x9ep;\v&\xaa\u05ed\x8dJ\xce\xe9\x17\bX\x8fh\xec\xc8\xe2Da\v\xb3\x17\x81؎L\xa74\xcbN\xca\x16\xe0\xd1#y/d\xebb\x9f\xcfV\xe3g'\rG:\xb2{-\x99P\x9d\xc0\bx\x1c\xb8\xe8\x88\xdaG'\xe8\xeb8\x9c\x83S\xd7y\r\x87\x9d\xe5\xa2/\xe4\x9ep2ţ-j\x8a\x13\x8c^\xe9\xe6L\xf0ȊϺMik\x95\xb0\x9bI\x0e\x00>\xf3\x99|\x9c\x15L\xc2\xdd{A\xe3\xc3\t.&\xec}\x82m\x92N\xd1\x11 \x12\xfd\xd0\xcd(\x00\x89F\xeaf\xc2\x13\xf7C&\x9bx\x17\x92#\x00\x02\x84n\xa0K\x898\x1c\xe8\x95\xde\xf2\xe4\xedXo\xa9G\x80h\x0fG\xc5)\x92\x81\x15@շ\x1c\xbd\x9e\xff\x15`\x00\xdfɄ\xff\xd7\x15\xb9\x95\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x06$import QtQuick 2.0\nimport QtQuick.Particles 2.0\nimport QtGraphicalEffects 1.0;\n\nRectangle {\n\tid: root\n\n\twidth: 640\n\theight: 480\n\n\tgradient: Gradient {\n\t\tGradientStop { position: 0.0; color: \"#3a2c32\"; }\n\t\tGradientStop { position: 0.8; color: \"#875864\"; }\n\t\tGradientStop { position: 1.0; color: \"#9b616c\"; }\n\t}\n\n\tText {\n\t\ttext: ctrl.message\n\n\t\tComponent.onCompleted: {\n\t\t\tx = parent.width/2 - width/2\n\t\t\ty = parent.height/2 - height/2\n\t\t}\n\n\t\tcolor: \"white\"\n\t\tfont.bold: true\n\t\tfont.pointSize: 20\n\n\t\tMouseArea {\n\t\t id: mouseArea\n\t\t anchors.fill: parent\n\t\t drag.target: parent\n onReleased: ctrl.textReleased(parent)\n\t\t}\n\t}\n\n\tParticleSystem { id: sys }\n\n\tImageParticle {\n\t\tsystem: sys\n\t\tsource: \"qrc:///assets/particle.png\"\n\t\tcolor: \"white\"\n\t\tcolorVariation: 1.0\n\t\talpha: 0.1\n\t}\n\n\tproperty var emitterComponent: Component {\n\t\tid: emitterComponent\n\t\tEmitter {\n\t\t\tid: container\n\t\t\tsystem: sys\n\t\t\tEmitter {\n\t\t\t\tsystem: sys\n\t\t\t\temitRate: 128\n\t\t\t\tlifeSpan: 600\n\t\t\t\tsize: 16\n\t\t\t\tendSize: 8\n\t\t\t\tvelocity: AngleDirection { angleVariation:360; magnitude: 60 }\n\t\t\t}\n\n\t\t\tproperty int life: 2600\n\t\t\tproperty real targetX: 0\n\t\t\tproperty real targetY: 0\n\t\t\temitRate: 128\n\t\t\tlifeSpan: 600\n\t\t\tsize: 24\n\t\t\tendSize: 8\n\t\t\tNumberAnimation on x {\n\t\t\t\tobjectName: \"xAnim\"\n\t\t\t\tid: xAnim;\n\t\t\t\tto: targetX\n\t\t\t\tduration: life\n\t\t\t\trunning: false\n\t\t\t}\n\t\t\tNumberAnimation on y {\n\t\t\t\tobjectName: \"yAnim\"\n\t\t\t\tid: yAnim;\n\t\t\t\tto: targetY\n\t\t\t\tduration: life\n\t\t\t\trunning: false\n\t\t\t}\n\t\t\tTimer {\n\t\t\t\tinterval: life\n\t\t\t\trunning: true\n\t\t\t\tonTriggered: ctrl.done(container)\n\t\t\t}\n\t\t}\n\t}\n}\n\x00\x06\x06\x8a\x9c\xb3\x00a\x00s\x00s\x00e\x00t\x00s\x00\f\b\xf9b\xa7\x00p\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00.\x00p\x00n\x00g\x00\f\b\xf9e\xdc\x00p\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00.\x00q\x00m\x00l\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x01\x00\x00\x03a" 59 | -------------------------------------------------------------------------------- /examples/reparent/base.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Rectangle { 4 | width: 640 5 | height: 480 6 | color: "black" 7 | } 8 | -------------------------------------------------------------------------------- /examples/reparent/rect.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Rectangle { 4 | anchors.centerIn: parent 5 | width: 50 6 | height: 50 7 | color: "red" 8 | } 9 | -------------------------------------------------------------------------------- /examples/reparent/reparent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/limetext/qml-go" 8 | ) 9 | 10 | func main() { 11 | if err := qml.Run(run); err != nil { 12 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 13 | os.Exit(1) 14 | } 15 | } 16 | 17 | func run() error { 18 | engine := qml.NewEngine() 19 | 20 | base, err := engine.LoadFile("base.qml") 21 | if err != nil { 22 | return err 23 | } 24 | rect, err := engine.LoadFile("rect.qml") 25 | if err != nil { 26 | return err 27 | } 28 | 29 | win := base.CreateWindow(nil) 30 | obj := rect.Create(nil) 31 | 32 | obj.Set("parent", win.Root()) 33 | 34 | win.Show() 35 | win.Wait() 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /examples/snapweb/snapweb.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image/png" 6 | "os" 7 | 8 | "github.com/limetext/qml-go" 9 | ) 10 | 11 | const webview = ` 12 | import QtQuick 2.0 13 | import QtWebKit 3.0 14 | 15 | WebView { 16 | width: 1024 17 | height: 768 18 | } 19 | ` 20 | 21 | func main() { 22 | if len(os.Args) != 3 { 23 | fmt.Fprintf(os.Stderr, "usage: %s \n", os.Args[0]) 24 | os.Exit(1) 25 | } 26 | if err := qml.Run(run); err != nil { 27 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 28 | os.Exit(1) 29 | } 30 | } 31 | 32 | func run() error { 33 | engine := qml.NewEngine() 34 | component, err := engine.LoadString("webview.qml", webview) 35 | if err != nil { 36 | return err 37 | } 38 | ctrl := &Control{ 39 | done: make(chan error), 40 | win: component.CreateWindow(nil), 41 | } 42 | engine.Context().SetVar("ctrl", ctrl) 43 | root := ctrl.win.Root() 44 | root.On("loadingChanged", ctrl.Snapshot) 45 | root.Set("url", os.Args[1]) 46 | ctrl.win.Show() 47 | return <-ctrl.done 48 | } 49 | 50 | type Control struct { 51 | win *qml.Window 52 | done chan error 53 | } 54 | 55 | func (ctrl *Control) Snapshot(request qml.Object) { 56 | if request.Int("status") != 2 { 57 | return 58 | } 59 | f, err := os.Create(os.Args[2]) 60 | if err != nil { 61 | ctrl.done <- err 62 | return 63 | } 64 | defer f.Close() 65 | img := ctrl.win.Snapshot() 66 | err = png.Encode(f, img) 67 | if err != nil { 68 | os.Remove(os.Args[2]) 69 | } 70 | ctrl.done <- err 71 | } 72 | -------------------------------------------------------------------------------- /gl/gengl/Makefile: -------------------------------------------------------------------------------- 1 | 2 | gengl: main.go parseqt.go 3 | go build 4 | 5 | %.go: %.rl 6 | ragel -Z -G2 -o $@ $< 7 | 8 | run: gengl 9 | ./gengl 10 | -------------------------------------------------------------------------------- /gl/gengl/parseqt.rl: -------------------------------------------------------------------------------- 1 | // 2 | // To compile: 3 | // 4 | // ragel -Z -G2 -o parseqt.go parseqt.rl 5 | // 6 | // To show a diagram of the state machine: 7 | // 8 | // ragel -V -G2 -p -o parseqt.dot parseqt.rl 9 | // dot -Tsvg -o parseqt.svg parseqt.dot 10 | // chrome parseqt.svg 11 | // 12 | 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | ) 18 | 19 | %%{ 20 | machine parseqt; 21 | 22 | write data; 23 | }%% 24 | 25 | func parseQt(data string, header *Header) error { 26 | var cs, p, pe int 27 | var ts, te, act, eof int 28 | 29 | pe = len(data) 30 | eof = len(data) 31 | 32 | _, _, _ = ts, te, act 33 | 34 | //stack := make([]int, 32) 35 | //top := 0 36 | 37 | var curline = 1 38 | 39 | var m0, m1, m2, m3, m4, m5, m6 int 40 | var foundclass int 41 | var inpublic bool 42 | var heading string 43 | var lineblock int 44 | var f Func 45 | 46 | %%{ 47 | nl = '\n' @{ curline++ }; 48 | cd = [^\n]; 49 | sp = [ \t]; 50 | id = [A-Za-z0-9_]+; 51 | spnl = ( sp | nl ); 52 | 53 | main := |* 54 | 'class Q_GUI_EXPORT ' id >{ m0 = p } %{ m1 = p } ' : public QAbstractOpenGLFunctions' nl '{' nl 55 | { 56 | header.Class = data[m0:m1] 57 | foundclass++ 58 | fgoto inclass; 59 | }; 60 | 61 | 'class Q_GUI_EXPORT ' id >{ m0 = p } %{ m1 = p } nl '{' nl 62 | { 63 | if data[m0:m1] == "QOpenGLFunctions" { 64 | header.Class = data[m0:m1] 65 | foundclass++ 66 | } 67 | fgoto inclass; 68 | }; 69 | 70 | # Ignore any other line. 71 | cd* nl; 72 | *|; 73 | 74 | inclass := |* 75 | # Track heading comments. 76 | sp* '//' sp* cd* >{ m0 = p } @{ m1 = p } sp* nl 77 | { 78 | heading = data[m0:m1] 79 | _ = heading 80 | lineblock++ 81 | }; 82 | 83 | # Ignore constructor/destructor. 84 | sp* '~'? id >{ m0 = p } %{ m1 = p } '()' sp* ( ';' | '{}' ) sp* nl { 85 | if data[m0:m1] != header.Class { 86 | fbreak; 87 | } 88 | }; 89 | 90 | # Ignore initialization function. 91 | sp* 'bool' sp+ 'initializeOpenGLFunctions()' cd* nl; 92 | 93 | # Ignore friend classes. 94 | sp* 'friend' sp+ 'class' sp+ id sp* ';' sp* nl; 95 | 96 | # Track public/private to ignore whatever isn't public. 97 | sp* 'public:' sp* nl 98 | { 99 | inpublic = true 100 | }; 101 | sp* ( 'private:' | 'protected:' ) sp* nl 102 | { 103 | inpublic = false 104 | }; 105 | 106 | # Record function prototypes. 107 | sp* ( 'const' sp+ )? id >{ m0 = p } %{ m1 = p; m4 = 0 } ( sp 'const'? | '*'+ ${ m4++ } )+ 108 | # Name 109 | 'gl' >{ m2 = p } id %{ m3 = p; f = Func{Name: data[m2:m3], Type: data[m0:m1], Addr: m4} } sp* '(' >{ m6 = 0 } sp* 110 | # Parameters 111 | ( 'void'? sp* ')' | ( ( 'const' %{ m6 = 1 } sp+ )? id >{ m0 = p } %{ m1 = p; m4 = 0 } ( sp 'const'? | '*' ${ m4++ } )+ id >{ m2 = p; m5 = 0 } %{ m3 = p } ( '[' [0-9]+ ${ m5 = m5*10 + (int(data[p]) - '0') } ']' )? sp* [,)] 112 | >{ f.Param = append(f.Param, Param{Name: data[m2:m3], Type: data[m0:m1], Addr: m4, Array: m5, Const: m6 > 0}); m6 = 0 } sp* )+ ) 113 | sp* ';' 114 | { 115 | if (inpublic) { 116 | header.Func = append(header.Func, f) 117 | } 118 | }; 119 | 120 | # Record feature flags. 121 | sp* 'enum OpenGLFeature' sp* nl sp* '{' sp* nl 122 | ( sp* id >{ m0 = p } %{ m1 = p } sp* '=' sp* '0x' >{ m2 = p } [0-9]+ %{ m3 = p } ','? sp* nl 123 | >{ header.FeatureFlags = append(header.FeatureFlags, Const{Name: data[m0:m1], Value: data[m2:m3]}) } )+ 124 | sp* '};' nl; 125 | 126 | # Ignore non-gl functions and fields. 127 | sp* ( 'static' sp+ )? ( 'const' sp+ )? [A-Za-z0-9_:]+ ( sp 'const'? | '*'+ ${ m4++ } )+ ( id - ( 'gl' id ) ) ( '(' cd* ')' )? sp* 'const'? 128 | sp* ( ';' | '{' cd* '}' ) sp* nl; 129 | 130 | # Ignore Q_DECLARE_FLAGS 131 | sp* 'Q_DECLARE_FLAGS(' cd+ ')' sp* nl; 132 | 133 | # Ignore deprecated functionality. 134 | '#if QT_DEPRECATED_SINCE(' cd+ ')' sp* nl 135 | ( cd* - '#endif' ) sp* nl 136 | '#endif' sp* nl; 137 | 138 | # Done. 139 | sp* '}' sp* ';' nl 140 | { 141 | foundclass++; 142 | fgoto main; 143 | }; 144 | 145 | # Reset relevant states on empty lines. 146 | sp* nl 147 | { 148 | // Reset heading comment. 149 | heading = "" 150 | 151 | // Start new line block. 152 | lineblock++ 153 | }; 154 | 155 | *|; 156 | 157 | skiperror := [^\n]* (';' | nl ) @{ fgoto main; }; 158 | 159 | write init; 160 | write exec; 161 | }%% 162 | 163 | if p < pe { 164 | m0, m1 = p, p 165 | for m0 > 0 && data[m0-1] != '\n' { 166 | m0-- 167 | } 168 | for m1 < len(data) && data[m1] != '\n' { 169 | m1++ 170 | } 171 | return fmt.Errorf("cannot parse header file:%d:%d: %s", curline, p-m0, data[m0:m1]) 172 | } 173 | 174 | if foundclass == 0 { 175 | return fmt.Errorf("cannot find C++ class in header file") 176 | } 177 | if foundclass == 1 { 178 | return fmt.Errorf("cannot find end of C++ class in header file") 179 | } 180 | if foundclass > 2 { 181 | return fmt.Errorf("found too many C++ classes in header file") 182 | } 183 | return nil 184 | } 185 | -------------------------------------------------------------------------------- /gl/glbase/glbase.go: -------------------------------------------------------------------------------- 1 | package glbase 2 | 3 | // A Context represents an OpenGL context that may be rendered on by the 4 | // version-specific APIs under this package. 5 | type Context struct { 6 | // This is just a marker at the moment, as the GL.API functions will 7 | // initialize their GL context from the current context in the 8 | // renderer thread. The design supports proper expansion and fixes for 9 | // upstream changes that break that model, though. 10 | private struct{} 11 | } 12 | 13 | // Contexter is implemented by values that have an assigned OpenGL context. 14 | type Contexter interface { 15 | GLContext() *Context 16 | } 17 | 18 | type ( 19 | Bitfield uint32 20 | Enum uint32 21 | Sync uintptr 22 | Clampf float32 23 | Clampd float64 24 | 25 | Uniform int32 26 | Attrib int32 27 | Texture uint32 28 | Program uint32 29 | Shader uint32 30 | Buffer uint32 31 | Framebuffer uint32 32 | Renderbuffer uint32 33 | ) 34 | -------------------------------------------------------------------------------- /goitemmodelimpls.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | type ItemModelDefaultImpl struct { 4 | } 5 | 6 | func (l *ItemModelDefaultImpl) ColumnCount(parent ModelIndex) int { 7 | return 1 8 | } 9 | 10 | func (l *ItemModelDefaultImpl) RowCount(parent ModelIndex) int { 11 | return 1 12 | } 13 | 14 | func (l *ItemModelDefaultImpl) Data(index ModelIndex, role Role) interface{} { 15 | return nil 16 | } 17 | 18 | func (l *ItemModelDefaultImpl) Index(row int, column int, parent ModelIndex) ModelIndex { 19 | // if !parent.IsValid() && column == 0 && row >= 0 && row < len(l.lines) { 20 | // return l.internal.CreateIndex(row, column, 0) 21 | // } 22 | return nil 23 | } 24 | 25 | func (l *ItemModelDefaultImpl) Parent(index ModelIndex) ModelIndex { 26 | return nil 27 | } 28 | 29 | // Editing functions 30 | 31 | func (l *ItemModelDefaultImpl) Flags(index ModelIndex) ItemFlags { 32 | return NoItemFlags 33 | } 34 | 35 | func (l *ItemModelDefaultImpl) SetData(index ModelIndex, value interface{}, role Role) bool { 36 | return false 37 | } 38 | -------------------------------------------------------------------------------- /gomodelindex.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #cgo CPPFLAGS: -I../cpp 4 | // #cgo CXXFLAGS: -std=c++0x -pedantic-errors -Wall -fno-strict-aliasing 5 | // #cgo LDFLAGS: -lstdc++ 6 | // #cgo pkg-config: Qt5Core Qt5Widgets Qt5Quick 7 | // 8 | // #include 9 | // #include "goitemmodel_api.h" 10 | // 11 | import "C" 12 | import "unsafe" 13 | 14 | type qModelIndex struct { 15 | ptr uintptr 16 | engine *Engine 17 | } 18 | 19 | func mkModelIndex(ptr uintptr, engine *Engine) ModelIndex { 20 | if ptr == 0 { 21 | return nil 22 | } 23 | return &qModelIndex{ 24 | ptr: ptr, 25 | engine: engine, 26 | } 27 | } 28 | 29 | type ModelIndex interface { 30 | // ModelIndex can only be created from a ItemModel 31 | internal_ModelIndex() 32 | Child(row, col int) ModelIndex 33 | Sibling(row, col int) ModelIndex 34 | Column() int 35 | Row() int 36 | Data(role Role) interface{} 37 | Flags() ItemFlags 38 | InternalId() uintptr 39 | InternalPointer() uintptr 40 | IsValid() bool 41 | Model() ItemModel 42 | Parent() ModelIndex 43 | } 44 | 45 | func (i *qModelIndex) internal_ModelIndex() {} 46 | 47 | func (i *qModelIndex) Child(row, col int) ModelIndex { 48 | return mkModelIndex(uintptr(C.modelIndexChild(unsafe.Pointer(i.ptr), C.int(row), C.int(col))), i.engine) 49 | } 50 | 51 | func (i *qModelIndex) Sibling(row, col int) ModelIndex { 52 | return mkModelIndex(uintptr(C.modelIndexSibling(unsafe.Pointer(i.ptr), C.int(row), C.int(col))), i.engine) 53 | } 54 | 55 | func (i *qModelIndex) Column() int { 56 | return int(C.modelIndexColumn(unsafe.Pointer(i.ptr))) 57 | } 58 | 59 | func (i *qModelIndex) Row() int { 60 | return int(C.modelIndexRow(unsafe.Pointer(i.ptr))) 61 | } 62 | 63 | func (i *qModelIndex) Data(role Role) interface{} { 64 | var dvalue C.DataValue 65 | C.modelIndexData(unsafe.Pointer(i.ptr), C.int(role), &dvalue) 66 | return unpackDataValue(&dvalue, i.engine) 67 | } 68 | 69 | func (i *qModelIndex) Flags() ItemFlags { 70 | return ItemFlags(C.modelIndexFlags(unsafe.Pointer(i.ptr))) 71 | } 72 | 73 | func (i *qModelIndex) InternalId() uintptr { 74 | return uintptr(C.modelIndexInternalId(unsafe.Pointer(i.ptr))) 75 | } 76 | 77 | func (i *qModelIndex) InternalPointer() uintptr { 78 | return uintptr(C.modelIndexInternalPointer(unsafe.Pointer(i.ptr))) 79 | } 80 | 81 | func (i *qModelIndex) IsValid() bool { 82 | if i == nil || i.ptr == 0 { 83 | return false 84 | } 85 | return bool(C.modelIndexIsValid(unsafe.Pointer(i.ptr))) 86 | } 87 | 88 | func (i *qModelIndex) Model() ItemModel { 89 | return itemModelFromCPP(uintptr(C.modelIndexModel(unsafe.Pointer(i.ptr))), i.engine) 90 | } 91 | 92 | func (i *qModelIndex) Parent() ModelIndex { 93 | return mkModelIndex(uintptr(C.modelIndexParent(unsafe.Pointer(i.ptr))), i.engine) 94 | } 95 | -------------------------------------------------------------------------------- /internal/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "reflect" 5 | "unsafe" 6 | ) 7 | 8 | func Hashable(value interface{}) (hashable bool) { 9 | defer func() { recover() }() 10 | return value == value 11 | } 12 | 13 | // unsafeString returns a Go string backed by C data. 14 | // 15 | // If the C data is deallocated or moved, the string will be 16 | // invalid and will crash the program if used. As such, the 17 | // resulting string must only be used inside the implementation 18 | // of the qml package and while the life time of the C data 19 | // is guaranteed. 20 | func UnsafeString(data unsafe.Pointer, size int) string { 21 | var s string 22 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 23 | sh.Data = uintptr(data) 24 | sh.Len = size 25 | return s 26 | } 27 | 28 | // unsafeStringData returns a C string backed by Go data. The C 29 | // string is NOT null-terminated, so its length must be taken 30 | // into account. 31 | // 32 | // If the s Go string is garbage collected, the returned C data 33 | // will be invalid and will crash the program if used. As such, 34 | // the resulting data must only be used inside the implementation 35 | // of the qml package and while the life time of the Go string 36 | // is guaranteed. 37 | func UnsafeStringData(s string) (unsafe.Pointer, int) { 38 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 39 | return unsafe.Pointer(sh.Data), sh.Len 40 | } 41 | 42 | // unsafeBytesData returns a C string backed by Go data. The C 43 | // string is NOT null-terminated, so its length must be taken 44 | // into account. 45 | // 46 | // If the array backing the b Go slice is garbage collected, the 47 | // returned C data will be invalid and will crash the program if 48 | // used. As such, the resulting data must only be used inside the 49 | // implementation of the qml package and while the life time of 50 | // the Go array is guaranteed. 51 | func UnsafeBytesData(b []byte) (unsafe.Pointer, int) { 52 | return *(*unsafe.Pointer)(unsafe.Pointer(&b)), len(b) 53 | } 54 | -------------------------------------------------------------------------------- /log.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include "capi.h" 4 | // 5 | import "C" 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "path/filepath" 11 | "strings" 12 | "unsafe" 13 | 14 | "github.com/limetext/qml-go/internal/util" 15 | ) 16 | 17 | // SetLogger sets the target for messages logged by the qml package, 18 | // including console.log and related calls from within qml code. 19 | // 20 | // The logger value must implement either the StdLogger interface, 21 | // which is satisfied by the standard *log.Logger type, or the QmlLogger 22 | // interface, which offers more control over the logged message. 23 | // 24 | // If no logger is provided, the qml package will send messages to the 25 | // default log package logger. This behavior may also be restored by 26 | // providing a nil logger to this function. 27 | func SetLogger(logger interface{}) { 28 | if logger == nil { 29 | logHandler = defaultLogger{} 30 | return 31 | } 32 | if qmll, ok := logger.(QmlLogger); ok { 33 | logHandler = qmll 34 | return 35 | } 36 | if stdl, ok := logger.(StdLogger); ok { 37 | logHandler = wrappedStdLogger{stdl} 38 | return 39 | } 40 | panic("unsupported logger interface") 41 | } 42 | 43 | // The QmlLogger interface may be implemented to better control how 44 | // log messages from the qml package are handled. Values that 45 | // implement either StdLogger or QmlLogger may be provided to the 46 | // SetLogger function. 47 | type QmlLogger interface { 48 | // QmlOutput is called whenever a new message is available for logging. 49 | // The message value must not be used after the method returns. 50 | QmlOutput(message LogMessage) error 51 | } 52 | 53 | // The StdLogger interface is implemented by standard *log.Logger values. 54 | // Values that implement either StdLogger or QmlLogger may be provided 55 | // to the SetLogger function. 56 | type StdLogger interface { 57 | // Output is called whenever a new message is available for logging. 58 | // See the standard log.Logger type for more details. 59 | Output(calldepth int, s string) error 60 | } 61 | 62 | // NOTE: LogMessage is an interface to avoid allocating and copying 63 | // several strings for each logged message. 64 | 65 | // LogMessage is implemented by values provided to QmlLogger.QmlOutput. 66 | type LogMessage interface { 67 | Severity() LogSeverity 68 | Text() string 69 | File() string 70 | Line() int 71 | 72 | String() string // returns "file:line: text" 73 | 74 | privateMarker() 75 | } 76 | 77 | type LogSeverity int 78 | 79 | const ( 80 | LogDebug LogSeverity = iota 81 | LogWarning 82 | LogCritical 83 | LogFatal 84 | ) 85 | 86 | var logHandler QmlLogger = defaultLogger{} 87 | 88 | type defaultLogger struct{} 89 | 90 | func (defaultLogger) QmlOutput(msg LogMessage) error { 91 | log.Println(msg.String()) 92 | return nil 93 | } 94 | 95 | func init() { 96 | // Install the C++ log handler that diverts calls to the hook below. 97 | C.installLogHandler() 98 | } 99 | 100 | //export hookLogHandler 101 | func hookLogHandler(cmsg *C.LogMessage) { 102 | // Workarund for QTBUG-35943 103 | text := util.UnsafeString(unsafe.Pointer(cmsg.text), int(cmsg.textLen)) 104 | if strings.HasPrefix(text, `"Qt Warning: Compose file:`) { 105 | return 106 | } 107 | msg := logMessage{c: cmsg} 108 | logHandler.QmlOutput(&msg) 109 | msg.invalid = true 110 | } 111 | 112 | type wrappedStdLogger struct { 113 | StdLogger 114 | } 115 | 116 | func (l wrappedStdLogger) QmlOutput(msg LogMessage) error { 117 | return l.Output(0, msg.String()) 118 | } 119 | 120 | type logMessage struct { 121 | c *C.LogMessage 122 | 123 | // invalid flags that cmsg points to unreliable memory, 124 | // since the log hook has already returned. 125 | invalid bool 126 | } 127 | 128 | func (m *logMessage) assertValid() { 129 | if m.invalid { 130 | panic("attempted to use log message outside of log hook") 131 | } 132 | } 133 | 134 | func (m *logMessage) Severity() LogSeverity { 135 | return LogSeverity(m.c.severity) 136 | } 137 | 138 | func (m *logMessage) Line() int { 139 | m.assertValid() 140 | return int(m.c.line) 141 | } 142 | 143 | func (m *logMessage) String() string { 144 | m.assertValid() 145 | file := util.UnsafeString(unsafe.Pointer(m.c.file), int(m.c.fileLen)) 146 | text := util.UnsafeString(unsafe.Pointer(m.c.text), int(m.c.textLen)) 147 | return fmt.Sprintf("%s:%d: %s", filepath.Base(file), m.c.line, text) 148 | } 149 | 150 | func (m *logMessage) File() string { 151 | m.assertValid() 152 | return C.GoStringN(m.c.file, m.c.fileLen) 153 | } 154 | 155 | func (m *logMessage) Text() string { 156 | m.assertValid() 157 | return C.GoStringN(m.c.text, m.c.line) 158 | } 159 | 160 | func (*logMessage) privateMarker() {} 161 | -------------------------------------------------------------------------------- /qimage/image.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "image.h" 4 | #include "util.cpp" 5 | 6 | QImage_* newQImage(int width, int height, unsigned int format) { 7 | return new QImage(width, height, (QImage::Format)format); 8 | } 9 | 10 | QImage_* loadQImage(const char *filename, int filename_length, const char *format) { 11 | QString qfilename = QStringFromGoString(filename, filename_length); 12 | return new QImage(qfilename, format); 13 | } 14 | 15 | void deleteQImage(QImage_* img) { 16 | delete (QImage*)img; 17 | } 18 | -------------------------------------------------------------------------------- /qimage/image.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_H 2 | #define IMAGE_H 3 | 4 | #include "capi.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | QImage_* newQImage(int width, int height, unsigned int format); 11 | QImage_* loadQImage(const char *filename, int filename_length, const char *format); 12 | void deleteQImage(QImage_*); 13 | 14 | 15 | #ifdef __cplusplus 16 | } // extern "C" 17 | #endif 18 | 19 | #endif // IMAGE_H 20 | 21 | // vim:ts=4:sw=4:et:ft=cpp 22 | -------------------------------------------------------------------------------- /qimage/qimage.go: -------------------------------------------------------------------------------- 1 | package qimage 2 | 3 | // #cgo CPPFLAGS: -I../cpp 4 | // #cgo CXXFLAGS: -std=c++0x -pedantic-errors -Wall -fno-strict-aliasing 5 | // #cgo LDFLAGS: -lstdc++ 6 | // #cgo pkg-config: Qt5Core Qt5Widgets Qt5Quick 7 | // 8 | // #include 9 | // #include "image.h" 10 | // 11 | import "C" 12 | import ( 13 | "runtime" 14 | "unsafe" 15 | 16 | "github.com/limetext/qml-go/internal/util" 17 | ) 18 | 19 | type QImage interface { 20 | } 21 | 22 | type Format uint 23 | 24 | const ( 25 | Format_Invalid Format = 0 26 | Format_RGB32 Format = 4 27 | Format_ARGB32_Premultiplied Format = 6 28 | Format_RGB16 Format = 7 29 | ) 30 | 31 | type qImage struct { 32 | ptr unsafe.Pointer 33 | } 34 | 35 | func NewImage(width int, height int, format Format) QImage { 36 | qimgptr := C.newQImage(C.int(width), C.int(height), C.uint(format)) 37 | 38 | return mkImage(qimgptr) 39 | } 40 | 41 | func LoadImage(filename string, format string) QImage { 42 | fname, fnamelen := util.UnsafeStringData(filename) 43 | fmat, _ := util.UnsafeStringData(format + "\x00") 44 | 45 | qimgptr := C.loadQImage((*C.char)(fname), C.int(fnamelen), (*C.char)(fmat)) 46 | 47 | return mkImage(qimgptr) 48 | } 49 | 50 | func mkImage(qimgptr unsafe.Pointer) *qImage { 51 | qimg := &qImage{ptr: qimgptr} 52 | 53 | runtime.SetFinalizer(qimg, deleteImage) 54 | 55 | return qimg 56 | } 57 | 58 | func deleteImage(qimg *qImage) { 59 | C.deleteQImage(qimg.ptr) 60 | qimg.ptr = nil 61 | } 62 | -------------------------------------------------------------------------------- /qml.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include 4 | // 5 | // #include "capi.h" 6 | // 7 | import "C" 8 | 9 | import ( 10 | "errors" 11 | "unsafe" 12 | 13 | "github.com/limetext/qml-go/internal/util" 14 | ) 15 | 16 | func AddLibraryPath(path string) { 17 | cpath, cpathLen := util.UnsafeStringData(path) 18 | RunMain(func() { 19 | C.coreAddLibraryPath((*C.char)(cpath), C.int(cpathLen)) 20 | }) 21 | } 22 | 23 | func SetApplicationName(name string) { 24 | cname, cnameLen := util.UnsafeStringData(name) 25 | RunMain(func() { 26 | C.coreSetApplicationName((*C.char)(cname), C.int(cnameLen)) 27 | }) 28 | } 29 | 30 | func SetApplicationVersion(version string) { 31 | cversion, cversionLen := util.UnsafeStringData(version) 32 | RunMain(func() { 33 | C.coreSetApplicationVersion((*C.char)(cversion), C.int(cversionLen)) 34 | }) 35 | } 36 | 37 | func SetOrganizationDomain(domain string) { 38 | cdomain, cdomainLen := util.UnsafeStringData(domain) 39 | RunMain(func() { 40 | C.coreSetOrganizationDomain((*C.char)(cdomain), C.int(cdomainLen)) 41 | }) 42 | } 43 | 44 | func SetOrganizationName(name string) { 45 | cname, cnameLen := util.UnsafeStringData(name) 46 | RunMain(func() { 47 | C.coreSetOrganizationName((*C.char)(cname), C.int(cnameLen)) 48 | }) 49 | } 50 | 51 | func SetApplicationDisplayName(name string) { 52 | cname, cnameLen := util.UnsafeStringData(name) 53 | RunMain(func() { 54 | C.guiappSetApplicationDisplayName((*C.char)(cname), C.int(cnameLen)) 55 | }) 56 | } 57 | 58 | // Qt 5.7 59 | // func SetDesktopFileName(path string) { 60 | // cpath, cpathLen := util.UnsafeStringData(path) 61 | // RunMain(func() { 62 | // C.guiappSetDesktopFileName((*C.char)(cpath), C.int(cpathLen)) 63 | // }) 64 | // } 65 | 66 | func SetWindowIcon(path string) { 67 | cpath, cpathLen := util.UnsafeStringData(path) 68 | RunMain(func() { 69 | C.guiappSetWindowIcon((*C.char)(cpath), C.int(cpathLen)) 70 | }) 71 | } 72 | 73 | func cerror(cerr *C.error) error { 74 | err := errors.New(C.GoString((*C.char)(unsafe.Pointer(cerr)))) 75 | C.free(unsafe.Pointer(cerr)) 76 | return err 77 | } 78 | 79 | func cmust(cerr *C.error) { 80 | if cerr != nil { 81 | panic(cerror(cerr).Error()) 82 | } 83 | } 84 | 85 | // TODO Signal emitting support for go values. 86 | 87 | // LoadResources registers all resources in the provided resources collection, 88 | // making them available to be loaded by any Engine and QML file. 89 | // Registered resources are made available under "qrc:///some/path", where 90 | // "some/path" is the path the resource was added with. 91 | func LoadResources(r *Resources) { 92 | var base unsafe.Pointer 93 | if len(r.sdata) > 0 { 94 | base = *(*unsafe.Pointer)(unsafe.Pointer(&r.sdata)) 95 | } else if len(r.bdata) > 0 { 96 | base = *(*unsafe.Pointer)(unsafe.Pointer(&r.bdata)) 97 | } 98 | tree := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.treeOffset))) 99 | name := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.nameOffset))) 100 | data := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.dataOffset))) 101 | C.registerResourceData(C.int(r.version), tree, name, data) 102 | } 103 | 104 | // UnloadResources unregisters all previously registered resources from r. 105 | func UnloadResources(r *Resources) { 106 | var base unsafe.Pointer 107 | if len(r.sdata) > 0 { 108 | base = *(*unsafe.Pointer)(unsafe.Pointer(&r.sdata)) 109 | } else if len(r.bdata) > 0 { 110 | base = *(*unsafe.Pointer)(unsafe.Pointer(&r.bdata)) 111 | } 112 | tree := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.treeOffset))) 113 | name := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.nameOffset))) 114 | data := (*C.char)(unsafe.Pointer(uintptr(base) + uintptr(r.dataOffset))) 115 | C.unregisterResourceData(C.int(r.version), tree, name, data) 116 | } 117 | -------------------------------------------------------------------------------- /qmlcontext.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include 4 | // 5 | // #include "capi.h" 6 | // 7 | import "C" 8 | import ( 9 | "github.com/limetext/qml-go/internal/util" 10 | ) 11 | 12 | // Context represents a QML context that can hold variables visible 13 | // to logic running within it. 14 | type Context struct { 15 | Common 16 | } 17 | 18 | // SetVar makes the provided value available as a variable with the 19 | // given name for QML code executed within the c context. 20 | // 21 | // If value is a struct, its exported fields are also made accessible to 22 | // QML code as attributes of the named object. The attribute name in the 23 | // object has the same name of the Go field name, except for the first 24 | // letter which is lowercased. This is conventional and enforced by 25 | // the QML implementation. 26 | // 27 | // The engine will hold a reference to the provided value, so it will 28 | // not be garbage collected until the engine is destroyed, even if the 29 | // value is unused or changed. 30 | func (ctx *Context) SetVar(name string, value interface{}) { 31 | cname, cnamelen := util.UnsafeStringData(name) 32 | RunMain(func() { 33 | var dvalue C.DataValue 34 | packDataValue(value, &dvalue, ctx.engine, cppOwner) 35 | 36 | qname := C.newString((*C.char)(cname), C.int(cnamelen)) 37 | defer C.delString(qname) 38 | 39 | C.contextSetProperty(ctx.addr, qname, &dvalue) 40 | }) 41 | } 42 | 43 | // SetVars makes the exported fields of the provided value available as 44 | // variables for QML code executed within the c context. The variable names 45 | // will have the same name of the Go field names, except for the first 46 | // letter which is lowercased. This is conventional and enforced by 47 | // the QML implementation. 48 | // 49 | // The engine will hold a reference to the provided value, so it will 50 | // not be garbage collected until the engine is destroyed, even if the 51 | // value is unused or changed. 52 | func (ctx *Context) SetVars(value interface{}) { 53 | RunMain(func() { 54 | C.contextSetObject(ctx.addr, wrapGoValue(ctx.engine, value, cppOwner)) 55 | }) 56 | } 57 | 58 | // Var returns the context variable with the given name. 59 | func (ctx *Context) Var(name string) interface{} { 60 | cname, cnamelen := util.UnsafeStringData(name) 61 | 62 | var dvalue C.DataValue 63 | RunMain(func() { 64 | qname := C.newString((*C.char)(cname), C.int(cnamelen)) 65 | defer C.delString(qname) 66 | 67 | C.contextGetProperty(ctx.addr, qname, &dvalue) 68 | }) 69 | return unpackDataValue(&dvalue, ctx.engine) 70 | } 71 | 72 | // Spawn creates a new context that has ctx as a parent. 73 | func (ctx *Context) Spawn() *Context { 74 | var result Context 75 | result.engine = ctx.engine 76 | RunMain(func() { 77 | result.setAddr(C.contextSpawn(ctx.addr)) 78 | }) 79 | return &result 80 | } 81 | -------------------------------------------------------------------------------- /qmllist.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // List holds a QML list which may be converted to a Go slice of an 9 | // appropriate type via Convert. 10 | // 11 | // In the future this will also be able to hold a reference 12 | // to QML-owned maps, so they can be mutated in place. 13 | type List struct { 14 | // In the future this will be able to hold a reference to QML-owned 15 | // lists, so they can be mutated. 16 | data []interface{} 17 | } 18 | 19 | // Len returns the number of elements in the list. 20 | func (l *List) Len() int { 21 | return len(l.data) 22 | } 23 | 24 | // Convert allocates a new slice and copies the list content into it, 25 | // performing type conversions as possible, and then assigns the result 26 | // to the slice pointed to by sliceAddr. 27 | // Convert panics if the list values are not compatible with the 28 | // provided slice. 29 | func (l *List) Convert(sliceAddr interface{}) { 30 | toPtr := reflect.ValueOf(sliceAddr) 31 | if toPtr.Kind() != reflect.Ptr || toPtr.Type().Elem().Kind() != reflect.Slice { 32 | panic(fmt.Sprintf("List.Convert got a sliceAddr parameter that is not a slice address: %#v", sliceAddr)) 33 | } 34 | err := convertAndSet(toPtr.Elem(), reflect.ValueOf(l), reflect.Value{}) 35 | if err != nil { 36 | panic(err.Error()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /qmlmap.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // Map holds a QML map which may be converted to a Go map of an 9 | // appropriate type via Convert. 10 | // 11 | // In the future this will also be able to hold a reference 12 | // to QML-owned maps, so they can be mutated in place. 13 | type Map struct { 14 | data []interface{} 15 | } 16 | 17 | // Len returns the number of pairs in the map. 18 | func (m *Map) Len() int { 19 | return len(m.data) / 2 20 | } 21 | 22 | // Convert allocates a new map and copies the content of m property to it, 23 | // performing type conversions as possible, and then assigns the result to 24 | // the map pointed to by mapAddr. Map panics if m contains values that 25 | // cannot be converted to the type of the map at mapAddr. 26 | func (m *Map) Convert(mapAddr interface{}) { 27 | toPtr := reflect.ValueOf(mapAddr) 28 | if toPtr.Kind() != reflect.Ptr || toPtr.Type().Elem().Kind() != reflect.Map { 29 | panic(fmt.Sprintf("Map.Convert got a mapAddr parameter that is not a map address: %#v", mapAddr)) 30 | } 31 | err := convertAndSet(toPtr.Elem(), reflect.ValueOf(m), reflect.Value{}) 32 | if err != nil { 33 | panic(err.Error()) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /qmlobject.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | import "image/color" 4 | 5 | // Object is the common interface implemented by all QML types. 6 | // 7 | // See the documentation of Common for details about this interface. 8 | type Object interface { 9 | Common() *Common 10 | Addr() uintptr 11 | TypeName() string 12 | Interface() interface{} 13 | Set(property string, value interface{}) 14 | Property(name string) interface{} 15 | Int(property string) int 16 | Int64(property string) int64 17 | Float64(property string) float64 18 | Bool(property string) bool 19 | String(property string) string 20 | Color(property string) color.RGBA 21 | Object(property string) Object 22 | Map(property string) *Map 23 | List(property string) *List 24 | ObjectByName(objectName string) Object 25 | Call(method string, params ...interface{}) interface{} 26 | Create(ctx *Context) Object 27 | CreateWindow(ctx *Context) *Window 28 | Destroy() 29 | On(signal string, function interface{}) 30 | Clear() 31 | } 32 | -------------------------------------------------------------------------------- /qmltypes.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include 4 | // 5 | // #include "capi.h" 6 | // 7 | import "C" 8 | 9 | import ( 10 | "fmt" 11 | "reflect" 12 | "unsafe" 13 | ) 14 | 15 | // TypeSpec holds the specification of a QML type that is backed by Go logic. 16 | // 17 | // The type specification must be registered with the RegisterTypes function 18 | // before it will be visible to QML code, as in: 19 | // 20 | // qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ 21 | // Init: func(p *Person, obj qml.Object) {}, 22 | // }}) 23 | // 24 | // See the package documentation for more details. 25 | // 26 | type TypeSpec struct { 27 | // Init must be set to a function that is called when QML code requests 28 | // the creation of a new value of this type. The provided function must 29 | // have the following type: 30 | // 31 | // func(value *CustomType, object qml.Object) 32 | // 33 | // Where CustomType is the custom type being registered. The function will 34 | // be called with a newly created *CustomType and its respective qml.Object. 35 | Init interface{} 36 | 37 | // Name optionally holds the identifier the type is known as within QML code, 38 | // when the registered extension module is imported. If not specified, the 39 | // name of the Go type provided as the first argument of Init is used instead. 40 | Name string 41 | 42 | // Singleton defines whether a single instance of the type should be used 43 | // for all accesses, as a singleton value. If true, all properties of the 44 | // singleton value are directly accessible under the type name. 45 | Singleton bool 46 | 47 | private struct{} // Force use of fields by name. 48 | } 49 | 50 | var types []*TypeSpec 51 | 52 | // RegisterTypes registers the provided list of type specifications for use 53 | // by QML code. To access the registered types, they must be imported from the 54 | // provided location and major.minor version numbers. 55 | // 56 | // For example, with a location "GoExtensions", major 4, and minor 2, this statement 57 | // imports all the registered types in the module's namespace: 58 | // 59 | // import GoExtensions 4.2 60 | // 61 | // See the documentation on QML import statements for details on these: 62 | // 63 | // http://qt-project.org/doc/qt-5.0/qtqml/qtqml-syntax-imports.html 64 | // 65 | func RegisterTypes(location string, major, minor int, types []TypeSpec) { 66 | for i := range types { 67 | err := registerType(location, major, minor, &types[i]) 68 | if err != nil { 69 | panic(err) 70 | } 71 | } 72 | } 73 | 74 | func registerType(location string, major, minor int, spec *TypeSpec) error { 75 | // Copy and hold a reference to the spec data. 76 | localSpec := *spec 77 | 78 | f := reflect.ValueOf(localSpec.Init) 79 | ft := f.Type() 80 | if ft.Kind() != reflect.Func { 81 | return fmt.Errorf("TypeSpec.Init must be a function, got %#v", localSpec.Init) 82 | } 83 | if ft.NumIn() != 2 { 84 | return fmt.Errorf("TypeSpec.Init's function must accept two arguments: %s", ft) 85 | } 86 | firstArg := ft.In(0) 87 | if firstArg.Kind() != reflect.Ptr || firstArg.Elem().Kind() == reflect.Ptr { 88 | return fmt.Errorf("TypeSpec.Init's function must take a pointer type as the second argument: %s", ft) 89 | } 90 | if ft.In(1) != typeObject { 91 | return fmt.Errorf("TypeSpec.Init's function must take qml.Object as the second argument: %s", ft) 92 | } 93 | customType := typeInfo(reflect.New(firstArg.Elem()).Interface()) 94 | if localSpec.Name == "" { 95 | localSpec.Name = firstArg.Elem().Name() 96 | if localSpec.Name == "" { 97 | panic("cannot determine registered type name; please provide one explicitly") 98 | } 99 | } 100 | 101 | var err error 102 | RunMain(func() { 103 | cloc := C.CString(location) 104 | cname := C.CString(localSpec.Name) 105 | cres := C.int(0) 106 | if localSpec.Singleton { 107 | cres = C.registerSingleton(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) 108 | } else { 109 | cres = C.registerType(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) 110 | } 111 | // It doesn't look like it keeps references to these, but it's undocumented and unclear. 112 | C.free(unsafe.Pointer(cloc)) 113 | C.free(unsafe.Pointer(cname)) 114 | if cres == -1 { 115 | err = fmt.Errorf("QML engine failed to register type; invalid type location or name?") 116 | } else { 117 | types = append(types, &localSpec) 118 | } 119 | }) 120 | 121 | return err 122 | } 123 | 124 | // RegisterConverter registers the convereter function to be called when a 125 | // value with the provided type name is obtained from QML logic. The function 126 | // must return the new value to be used in place of the original value. 127 | func RegisterConverter(typeName string, converter func(engine *Engine, obj Object) interface{}) { 128 | if converter == nil { 129 | delete(converters, typeName) 130 | } else { 131 | converters[typeName] = converter 132 | } 133 | } 134 | 135 | var converters = make(map[string]func(engine *Engine, obj Object) interface{}) 136 | -------------------------------------------------------------------------------- /qmlwindow.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include 4 | // 5 | // #include "capi.h" 6 | // 7 | import "C" 8 | 9 | import ( 10 | "image" 11 | "reflect" 12 | "sync" 13 | "unsafe" 14 | ) 15 | 16 | // Window represents a QML window where components are rendered. 17 | type Window struct { 18 | Common 19 | } 20 | 21 | // Show exposes the window. 22 | func (win *Window) Show() { 23 | RunMain(func() { 24 | C.windowShow(win.addr) 25 | }) 26 | } 27 | 28 | // Hide hides the window. 29 | func (win *Window) Hide() { 30 | RunMain(func() { 31 | C.windowHide(win.addr) 32 | }) 33 | } 34 | 35 | // PlatformId returns the window's platform id. 36 | // 37 | // For platforms where this id might be useful, the value returned will 38 | // uniquely represent the window inside the corresponding screen. 39 | func (win *Window) PlatformId() uintptr { 40 | var id uintptr 41 | RunMain(func() { 42 | id = uintptr(C.windowPlatformId(win.addr)) 43 | }) 44 | return id 45 | } 46 | 47 | // Root returns the root object being rendered. 48 | // 49 | // If the window was defined in QML code, the root object is the window itself. 50 | func (win *Window) Root() Object { 51 | var obj Common 52 | obj.engine = win.engine 53 | RunMain(func() { 54 | obj.setAddr(C.windowRootObject(win.addr)) 55 | }) 56 | return &obj 57 | } 58 | 59 | // Wait blocks the current goroutine until the window is closed. 60 | func (win *Window) Wait() { 61 | // XXX Test this. 62 | var m sync.Mutex 63 | m.Lock() 64 | RunMain(func() { 65 | // TODO Must be able to wait for the same Window from multiple goroutines. 66 | // TODO If the window is not visible, must return immediately. 67 | waitingWindows[win.addr] = &m 68 | C.windowConnectHidden(win.addr) 69 | }) 70 | m.Lock() 71 | } 72 | 73 | var waitingWindows = make(map[unsafe.Pointer]*sync.Mutex) 74 | 75 | //export hookWindowHidden 76 | func hookWindowHidden(addr unsafe.Pointer) { 77 | m, ok := waitingWindows[addr] 78 | if !ok { 79 | panic("window is not waiting") 80 | } 81 | delete(waitingWindows, addr) 82 | m.Unlock() 83 | } 84 | 85 | // Snapshot returns an image with the visible contents of the window. 86 | // The main GUI thread is paused while the data is being acquired. 87 | func (win *Window) Snapshot() image.Image { 88 | // TODO Test this. 89 | var cimage unsafe.Pointer 90 | RunMain(func() { 91 | cimage = C.windowGrabWindow(win.addr) 92 | }) 93 | defer C.delImage(cimage) 94 | 95 | // This should be safe to be done out of the main GUI thread. 96 | var cwidth, cheight C.int 97 | C.imageSize(cimage, &cwidth, &cheight) 98 | 99 | var cbits []byte 100 | cbitsh := (*reflect.SliceHeader)((unsafe.Pointer)(&cbits)) 101 | cbitsh.Data = (uintptr)((unsafe.Pointer)(C.imageConstBits(cimage))) 102 | cbitsh.Len = int(cwidth * cheight * 8) // ARGB 103 | cbitsh.Cap = cbitsh.Len 104 | 105 | image := image.NewRGBA(image.Rect(0, 0, int(cwidth), int(cheight))) 106 | l := int(cwidth * cheight * 4) 107 | for i := 0; i < l; i += 4 { 108 | var c uint32 = *(*uint32)(unsafe.Pointer(&cbits[i])) 109 | image.Pix[i+0] = byte(c >> 16) 110 | image.Pix[i+1] = byte(c >> 8) 111 | image.Pix[i+2] = byte(c) 112 | image.Pix[i+3] = byte(c >> 24) 113 | } 114 | return image 115 | } 116 | -------------------------------------------------------------------------------- /static.go: -------------------------------------------------------------------------------- 1 | // +build static 2 | 3 | package qml 4 | 5 | // #cgo pkg-config: --static 6 | import "C" 7 | -------------------------------------------------------------------------------- /stats.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var stats *Statistics 8 | var statsMutex sync.Mutex 9 | 10 | func Stats() (snapshot Statistics) { 11 | statsMutex.Lock() 12 | snapshot = *stats 13 | statsMutex.Unlock() 14 | return 15 | } 16 | 17 | func CollectStats(enabled bool) { 18 | statsMutex.Lock() 19 | if enabled { 20 | if stats == nil { 21 | stats = &Statistics{} 22 | } 23 | } else { 24 | stats = nil 25 | } 26 | statsMutex.Unlock() 27 | } 28 | 29 | func ResetStats() { 30 | statsMutex.Lock() 31 | old := stats 32 | stats = &Statistics{} 33 | // These are absolute values: 34 | stats.EnginesAlive = old.EnginesAlive 35 | stats.ValuesAlive = old.ValuesAlive 36 | statsMutex.Unlock() 37 | return 38 | } 39 | 40 | type Statistics struct { 41 | EnginesAlive int 42 | ValuesAlive int 43 | ConnectionsAlive int 44 | } 45 | 46 | func (stats *Statistics) enginesAlive(delta int) { 47 | if stats != nil { 48 | statsMutex.Lock() 49 | stats.EnginesAlive += delta 50 | statsMutex.Unlock() 51 | } 52 | } 53 | 54 | func (stats *Statistics) valuesAlive(delta int) { 55 | if stats != nil { 56 | statsMutex.Lock() 57 | stats.ValuesAlive += delta 58 | statsMutex.Unlock() 59 | } 60 | } 61 | 62 | func (stats *Statistics) connectionsAlive(delta int) { 63 | if stats != nil { 64 | statsMutex.Lock() 65 | stats.ConnectionsAlive += delta 66 | statsMutex.Unlock() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /testing.go: -------------------------------------------------------------------------------- 1 | package qml 2 | 3 | // #include 4 | // int mprotect(void *addr, size_t len, int prot); 5 | import "C" 6 | 7 | import ( 8 | "bytes" 9 | "encoding/binary" 10 | "reflect" 11 | "unsafe" 12 | 13 | "github.com/limetext/qml-go/cdata" 14 | ) 15 | 16 | const pageSize = 4096 17 | 18 | func qmain() { 19 | Run(func() error { tmain(); return nil }) 20 | } 21 | 22 | func tmain() { tstub() } 23 | func tstub() { tstub() } 24 | 25 | func SetupTesting() { 26 | ptr := func(f func()) uintptr { return reflect.ValueOf(f).Pointer() } 27 | rmain, mmain := cdata.Addrs() 28 | fset(rmain, mmain, ptr(qmain)) 29 | fset(ptr(tmain), ptr(tstub), mmain) 30 | } 31 | 32 | const ( 33 | protREAD = 1 34 | protWRITE = 2 35 | protEXEC = 4 36 | ) 37 | 38 | func fset(target, old, new uintptr) { 39 | pageOffset := target % pageSize 40 | pageAddr := target - pageOffset 41 | 42 | var mem []byte 43 | memh := (*reflect.SliceHeader)(unsafe.Pointer(&mem)) 44 | memh.Data = pageAddr 45 | memh.Len = pageSize * 2 46 | memh.Cap = pageSize * 2 47 | 48 | oldAddr := make([]byte, 8) 49 | newAddr := make([]byte, 8) 50 | 51 | binary.LittleEndian.PutUint64(oldAddr, uint64(old)) 52 | binary.LittleEndian.PutUint64(newAddr, uint64(new)) 53 | 54 | // BSD's syscall package misses Mprotect. Use cgo instead. 55 | C.mprotect(unsafe.Pointer(pageAddr), C.size_t(len(mem)), protEXEC|protREAD|protWRITE) 56 | defer C.mprotect(unsafe.Pointer(pageAddr), C.size_t(len(mem)), protEXEC|protREAD) 57 | 58 | delta := make([]byte, 4) 59 | for i, c := range mem[pageOffset:] { 60 | if c == 0xe8 && int(pageOffset)+i+5 < len(mem) { 61 | instrAddr := pageAddr + pageOffset + uintptr(i) 62 | binary.LittleEndian.PutUint32(delta, uint32(old-instrAddr-5)) 63 | if bytes.Equal(mem[int(pageOffset)+i+1:int(pageOffset)+i+5], delta) { 64 | binary.LittleEndian.PutUint32(mem[int(pageOffset)+i+1:], uint32(new-instrAddr-5)) 65 | return 66 | } 67 | } 68 | } 69 | panic("cannot setup qml package for testing") 70 | } 71 | --------------------------------------------------------------------------------