Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cgo fixes via @amlwwalker via @SjB #186

Open
wants to merge 89 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
85e55c7
New API with Run on main thread.
niemeyer May 1, 2014
a664ad4
s/qml.v0/qml.v1/
niemeyer May 2, 2014
74294f0
Move the gl package under work-in-progress.
niemeyer Aug 13, 2014
1b0d88b
Update all examples with new API.
niemeyer Aug 13, 2014
534150a
update README for v1 branch
jhawk28 Aug 14, 2014
dbdeaea
cdata: use g->m
niemeyer Aug 14, 2014
f020d78
Changed examples url to match current branch
Aug 14, 2014
4457ebd
cpp/capi.cpp: fix ImageProvider leak
cookieo9 Aug 16, 2014
f84f9ae
update requirements for OS X
adg Aug 20, 2014
7b344dd
Merge pull request #88 from cookieo9/memfix
niemeyer Aug 20, 2014
fcf0740
Merge pull request #87 from nf/v1
niemeyer Aug 20, 2014
6e78849
Merge pull request #81 from jhawk28/patch-1
niemeyer Aug 20, 2014
5f7fdd0
Merge pull request #82 from perrito666/v1
niemeyer Aug 20, 2014
4f4a7f5
Handle Paint panics to workaround Go issue #8588.
niemeyer Aug 25, 2014
97c4e8c
New GL API.
niemeyer Apr 21, 2014
8e569b4
Port GL examples to new API.
niemeyer Aug 27, 2014
539bf5a
Use native Go types for meaningless GL types.
niemeyer Aug 28, 2014
43aa533
Move common GL types to glbase.
niemeyer Aug 28, 2014
c74beaa
Start introducing types for well known objects.
niemeyer Aug 28, 2014
b8b5c15
Drop types from consecutive params when possible.
niemeyer Aug 28, 2014
8c84461
Split func tweaking logic and start doc importing.
niemeyer Aug 28, 2014
8e7aff4
Commit current gl packages for publishing.
niemeyer Aug 28, 2014
a598350
Port examples to latest API tweak.
niemeyer Aug 28, 2014
9031cc6
Drop explicit linking with GL libraries.
niemeyer Aug 29, 2014
4432d5f
Update README to use qml.v1
owenthereal Aug 29, 2014
265c7b0
Add Clampf and Clampd to glbase.
niemeyer Sep 1, 2014
f59a4bb
Add back explicit GL linking to es2.
niemeyer Sep 1, 2014
1efc244
Booleans are now native. Boolean/TRUE/FALSE gone.
niemeyer Sep 1, 2014
0792804
More glbase types, richer func tweaks.
niemeyer Sep 2, 2014
00ff374
Unmix glresult and result in funcReturnResult.
niemeyer Sep 2, 2014
c9be844
Simplify language.
niemeyer Sep 2, 2014
4e2a8e0
Polished a few traditional ES2 functions.
niemeyer Sep 2, 2014
df4c093
Add ES2 painting example with shaders.
niemeyer Sep 2, 2014
6a397ef
Polish VertexAttribPointer.
niemeyer Sep 3, 2014
7dd7202
Convert many size-agnostic int32s to plain ints.
niemeyer Sep 3, 2014
45b5540
Simple tweak reordering.
niemeyer Sep 3, 2014
6b0feaf
Polish the whole Uniform* family of functions.
niemeyer Sep 3, 2014
5cee1b3
Drop doc link from functions already documented.
niemeyer Sep 3, 2014
79bf6cb
Polished GetProgram{iv,InfoLog}.
niemeyer Sep 3, 2014
2233843
Custom types for {render,frame}buffer and plurals.
niemeyer Sep 4, 2014
5f68d72
Polish a few Gen* and Delete* GL functions.
niemeyer Sep 4, 2014
46984f3
Fix bug in the selection of GL constants.
niemeyer Sep 4, 2014
4fd76df
Postpone type initialization if happening in Paint.
niemeyer Sep 4, 2014
2fcb6e2
Fix GL test in the suite.
niemeyer Sep 4, 2014
ea1e5fb
Make ObjectByName work with Go types too.
niemeyer Sep 5, 2014
0691e15
Safety check on ObjectByName.
niemeyer Sep 5, 2014
e3d7ffd
Force consts on all GL profiles to be processed.
niemeyer Sep 6, 2014
a98beac
Fix handling of glbase.Sync.
niemeyer Sep 6, 2014
6b4ad68
Convert offset in VertexAttribPointer to uintptr.
niemeyer Sep 6, 2014
b89e5bc
Workaround issue #84 (QTBUG-41193).
niemeyer Sep 9, 2014
cedade8
Merge pull request #92 from jingweno/patch-1
niemeyer Sep 10, 2014
8d74b65
README: another v0 => v1 reference
niemeyer Sep 10, 2014
ab659ec
README: use dev packages rather than ubuntu-sdk
niemeyer Sep 10, 2014
364da65
Do not reuse JS-owned wrapper values.
niemeyer Sep 10, 2014
5bad8a5
Implement mprotect function for Windows.
niemeyer Sep 11, 2014
824784c
Fix simple naming mistake
Sep 11, 2014
888d1e8
mmemwin: PAGE_READ => PAGE_READONLY
niemeyer Sep 12, 2014
b35cbc7
Ported some of the qtquickcontrols examples
cristim Sep 21, 2014
65cbb45
Support bundling of resources into the binary.
niemeyer Sep 26, 2014
76a2703
Add high-level summary to genqrc documentation.
niemeyer Sep 26, 2014
250377a
Documentation updates.
niemeyer Sep 26, 2014
40739e1
Documentation spacing fixes.
niemeyer Sep 26, 2014
e55ddbe
Update genqrc documentation after help text.
niemeyer Sep 26, 2014
f0a005b
Merge pull request #100 from GeertJohan/patch-1
niemeyer Oct 2, 2014
b94596a
Move cdata logic to assembly in Go 1.4+.
niemeyer Oct 6, 2014
7fdf7e3
Update setup.sh
lomoalbert Oct 8, 2014
ab36fb4
Update README.md
lomoalbert Oct 8, 2014
871e3a7
Merge pull request #110 from vzever/v1
niemeyer Oct 9, 2014
18fd325
README: fix requirements to refer to Go >= 1.2
niemeyer Oct 13, 2014
6e34c23
Merge branch 'v1' of github.com:go-qml/qml into v1
niemeyer Oct 13, 2014
b65658d
Update setup.sh
lomoalbert Oct 8, 2014
07cb71e
Update README.md
lomoalbert Oct 8, 2014
ad9c0dd
Fix bug in resource packing.
niemeyer Oct 20, 2014
929da27
Merge branch 'v1' of github.com:go-qml/qml into v1
niemeyer Oct 20, 2014
1116cb9
Merge pull request #105 from cristim/v1
niemeyer Oct 24, 2014
154c0d1
Make sure context.file is not null before calling strlen
tsdgeos Feb 9, 2015
2ee7e5f
Merge pull request #144 from tsdgeos/v1
niemeyer Feb 9, 2015
826359a
Porting go-qml to Go 1.6
SjB Apr 5, 2016
01021bc
change datatype the foldr from uintptr to C.GoRef
SjB Apr 6, 2016
2628b57
refactor valueFold.
SjB Apr 6, 2016
a4363f7
added reference lookup for signal function
SjB Apr 6, 2016
ea70551
added reference lookup for go TypeSpec type
SjB Apr 6, 2016
0309d2d
fix missing goRef function
SjB Apr 6, 2016
d4c4a72
fix forgotten dereferenced datap pointer.
SjB Jul 1, 2016
f9db098
fixed MouseArea On Event call back refrence error
SjB Jul 21, 2016
17ea716
adding changes to work with 1.6
Mar 4, 2017
ab29fd7
Merge branch 'master' into go1.6-port
Mar 16, 2017
28c538d
updating readme
Mar 16, 2017
7d9d06b
Lining up genqrc between go-qml and amlwwalker forks
jackman0 Mar 29, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
This software is licensed under the LGPLv3, included below.

As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.

Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.


GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.


This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

0. Additional Definitions.

As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

1. Exception to Section 3 of the GNU GPL.

You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

2. Conveying Modified Versions.

If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or

b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.

3. Object Code Incorporating Material from Library Header Files.

The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.

b) Accompany the object code with a copy of the GNU GPL and this license
document.

4. Combined Works.

You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.

b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.

c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.

d) Do one of the following:

0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.

1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.

e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)

5. Combined Libraries.

You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.

b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.

6. Revised Versions of the GNU Lesser General Public License.

The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
164 changes: 164 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# QML support for the Go language

## amlwwalker/qml

* I have made the `go1.6-port` branch the master branch here as it seems more relevant in this day and age...
* It is not my work, but I have been using it for a while so please shout if I can help!



Original Documentation
-------------

The introductory documentation as well as the detailed API documentation is
available at [gopkg.in/qml.v1](http://godoc.org/gopkg.in/qml.v1).


Blog posts
----------

Some relevant blog posts:

* [Announcing qml v1 for Go](http://blog.labix.org/2014/08/13/announcing-qml-v1-for-go)
* [Packing resources into Go qml binaries](http://blog.labix.org/2014/09/26/packing-resources-into-go-qml-binaries)
* [Go qml contest results](http://blog.labix.org/2014/04/25/qml-contest-results)
* [Arbitrary Qt extensions with Go qml](http://blog.labix.org/2014/03/21/arbitrary-qt-extensions-with-go-qml)
* [The new Go qml OpenGL API](http://blog.labix.org/2014/08/29/the-new-go-qml-opengl-api)
* [QML components with Go and OpenGL](http://blog.labix.org/2013/12/23/qml-components-with-go-and-opengl)


Videos
------

These introductory videos demonstrate the use of Go QML:

* [Initial demo and overview](http://youtu.be/FVQlMrPa7lI)
* [Initial demo running on an Ubuntu Touch phone](http://youtu.be/HB-3o8Cysec)
* [Spinning Gopher with Go + QML + OpenGL](http://youtu.be/qkH7_dtOyPk)
* [SameGame QML tutorial in Go](http://youtu.be/z8noX48hiMI)


Community
---------

Please join the [mailing list](https://groups.google.com/forum/#!forum/go-qml) for
following relevant development news and discussing project details.


Installation
------------

To try the alpha release you'll need:

* Go >= 1.2, for the C++ support of _go build_
* Qt 5.0.X or 5.1.X with the development files
* The Qt headers qmetaobject_p.h and qmetaobjectbuilder_p.h, for the dynamic meta object support

See below for more details about getting these requirements installed in different environments and operating systems.

After the requirements are satisfied, _go get_ should work as usual:

go get gopkg.in/qml.v1


Requirements on Ubuntu
----------------------

If you are using Ubuntu, the [Ubuntu SDK](http://developer.ubuntu.com/get-started/) will take care of the Qt dependencies:

$ sudo add-apt-repository ppa:ubuntu-sdk-team/ppa
$ sudo apt-get update
$ sudo apt-get install qtdeclarative5-dev qtbase5-private-dev qtdeclarative5-private-dev libqt5opengl5-dev qtdeclarative5-qtquick2-plugin

and Go >= 1.2 may be installed using [godeb](http://blog.labix.org/2013/06/15/in-flight-deb-packages-of-go):

$ # Pick the right one for your system: 386 or amd64
$ ARCH=amd64
$ wget -q https://godeb.s3.amazonaws.com/godeb-$ARCH.tar.gz
$ tar xzvf godeb-$ARCH.tar.gz
godeb
$ sudo mv godeb /usr/local/bin
$ godeb install
$ go get gopkg.in/qml.v1


Requirements on Ubuntu Touch
----------------------------

After following the [installation instructions](https://wiki.ubuntu.com/Touch/Install) for Ubuntu Touch,
run the following commands to get a working build environment inside the device:

$ adb shell
# cd /tmp
# wget https://github.com/go-qml/qml/raw/v1/cmd/ubuntu-touch/setup.sh
# /bin/bash setup.sh
# su - phablet
$

At the end of setup.sh, the phablet user will have GOPATH=$HOME in the environment,
the qml package will be built, and the particle example will be built and run. For
stopping it from the command line, run as the phablet user:

$ ubuntu-app-stop gopkg.in.qml.particle-example

for running it again:

$ ubuntu-app-launch gopkg.in.qml.particle-example

These commands depend on the following file, installed by setup.sh:

~/.local/share/applications/gopkg.in.qml.particle-example.desktop


Requirements on Mac OS X
------------------------

On Mac OS X you'll need QT5. It's easiest to install with Homebrew, a
third-party package management system for OS X.

Installation instructions for Homebrew are here:

http://brew.sh/

Then, install the qt5 and pkg-config packages:

$ brew install qt5 pkg-config

Then, force brew to "link" qt5 (this makes it available under /usr/local):

$ brew link --force qt5

And finally, fetch and install go-qml:

$ go get gopkg.in/qml.v1


Requirements on Windows
-----------------------

On Windows you'll need the following:

* [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)
* [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
* [Go >= 1.2](http://golang.org/doc/install)

Then, assuming Qt was installed under `C:\Qt5.1.1\`, set up the following environment variables in the respective configuration:

CPATH += C:\Qt5.1.1\5.1.1\mingw48_32\include
LIBRARY_PATH += C:\Qt5.1.1\5.1.1\mingw48_32\lib
PATH += C:\Qt5.1.1\5.1.1\mingw48_32\bin

After reopening the shell for the environment changes to take effect, this should work:

go get gopkg.in/qml.v1


Requirements everywhere else
----------------------------

If your operating system does not offer these dependencies readily,
you may still have success installing [Go >= 1.2](http://golang.org/doc/install)
and [Qt 5.0.2](http://download.qt-project.org/archive/qt/5.0/5.0.2/)
directly from the upstreams. Note that you'll likely have to adapt
environment variables to reflect the custom installation path for
these libraries. See the instructions above for examples.
12 changes: 12 additions & 0 deletions all.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#include "cpp/capi.cpp"
#include "cpp/govalue.cpp"
#include "cpp/govaluetype.cpp"
#include "cpp/idletimer.cpp"
#include "cpp/connector.cpp"

#include "cpp/moc_all.cpp"

#ifdef _WIN32
#include "cpp/mmemwin.cpp"
#endif
719 changes: 719 additions & 0 deletions bridge.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions cdata/cdata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Package cdata supports the implementation of the qml package.
package cdata

func Ref() uintptr

func Addrs() (uintptr, uintptr)
18 changes: 18 additions & 0 deletions cdata/cdata12.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// +build !go1.4

#include "runtime.h"

void ·Ref(uintptr ref) {
ref = (uintptr)g->m;
FLUSH(&ref);
}

void runtime·main(void);
void main·main(void);

void ·Addrs(uintptr rmain, uintptr mmain) {
rmain = (uintptr)runtime·main;
mmain = (uintptr)main·main;
FLUSH(&rmain);
FLUSH(&mmain);
}
17 changes: 17 additions & 0 deletions cdata/cdata14_386.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// +build go1.4

#include "textflag.h"

TEXT ·Ref(SB),NOSPLIT,$4-4
CALL runtime·acquirem(SB)
MOVL 0(SP), AX
MOVL AX, ret+0(FP)
CALL runtime·releasem(SB)
RET

TEXT ·Addrs(SB),NOSPLIT,$0-8
MOVL $runtime·main(SB), AX
MOVL AX, ret+0(FP)
MOVL $runtime·main_main(SB), AX
MOVL AX, ret+8(FP)
RET
17 changes: 17 additions & 0 deletions cdata/cdata14_amd64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// +build go1.4

#include "textflag.h"

TEXT ·Ref(SB),NOSPLIT,$8-8
CALL runtime·acquirem(SB)
MOVQ 0(SP), AX
MOVQ AX, ret+0(FP)
CALL runtime·releasem(SB)
RET

TEXT ·Addrs(SB),NOSPLIT,$0-16
MOVQ $runtime·main(SB), AX
MOVQ AX, ret+0(FP)
MOVQ $runtime·main_main(SB), AX
MOVQ AX, ret+8(FP)
RET
18 changes: 18 additions & 0 deletions cdata/cdata14_arm.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// +build go1.4

#include "textflag.h"

TEXT ·Ref(SB),NOSPLIT,$4-4
BL runtime·acquirem(SB)
MOVW 4(R13), R0
MOVW R0, ret+0(FP)
MOVW R0, 4(R13)
BL runtime·releasem(SB)
RET

TEXT ·Addrs(SB),NOSPLIT,$0-8
MOVW $runtime·main(SB), R0
MOVW R0, ret+0(FP)
MOVW $runtime·main_main(SB), R0
MOVW R0, ret+4(FP)
RET
42 changes: 42 additions & 0 deletions cdata/cdata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cdata

import (
"runtime"
"sync"
"testing"
)

type refPair struct {
ref1, ref2 uintptr
}

func TestRef(t *testing.T) {
const N = 10
runtime.LockOSThread()
exit := sync.WaitGroup{}
exit.Add(1)
defer exit.Done()
wg := sync.WaitGroup{}
wg.Add(N)
ch := make(chan refPair)
for i := 0; i < N; i++ {
go func() {
runtime.LockOSThread()
wg.Done()
ch <- refPair{Ref(), Ref()}
exit.Wait()
}()
}
wg.Wait()
refs := make(map[uintptr]bool)
for i := 0; i < N; i++ {
pair := <-ch
if pair.ref1 != pair.ref2 {
t.Fatalf("found inconsistent ref: %d != %d", pair.ref1, pair.ref2)
}
if refs[pair.ref1] {
t.Fatalf("found duplicated ref: %d", pair.ref1)
}
refs[pair.ref1] = true
}
}
Binary file added cmd/genqrc/genqrc
Binary file not shown.
218 changes: 218 additions & 0 deletions cmd/genqrc/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@

// XXX: The documentation is duplicated here and in the the doc variable
// below. Update both at the same time.

// Command genqrc packs resource files into the Go binary.
//
// Usage: genqrc [options] <subdir1> [<subdir2> ...]
//
// The genqrc tool packs all resource files under the provided subdirectories into
// a single qrc.go file that may be built into the generated binary. Bundled files
// may then be loaded by Go or QML code under the URL "qrc:///some/path", where
// "some/path" matches the original path for the resource file locally.
//
// For example, the following will load a .qml file from the resource pack, and
// that file may in turn reference other content (code, images, etc) in the pack:
//
// component, err := engine.LoadFile("qrc://path/to/file.qml")
//
// Starting with Go 1.4, this tool may be conveniently run by the "go generate"
// subcommand by adding a line similar to the following one to any existent .go
// file in the project (assuming the subdirectories ./code/ and ./images/ exist):
//
// //go:generate genqrc code images
//
// Then, just run "go generate" to update the qrc.go file.
//
// During development, the generated qrc.go can repack the filesystem content at
// runtime to avoid the process of regenerating the qrc.go file and rebuilding the
// application to test every minor change made. Runtime repacking is enabled by
// setting the QRC_REPACK environment variable to 1:
//
// export QRC_REPACK=1
//
// This does not update the static content in the qrc.go file, though, so after
// the changes are performed, genqrc must be run again to update the content that
// will ship with built binaries.
package main

import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"text/template"

"gopkg.in/qml.v1"
)

const doc = `
Usage: genqrc [options] <subdir1> [<subdir2> ...]
The genqrc tool packs all resource files under the provided subdirectories into
a single qrc.go file that may be built into the generated binary. Bundled files
may then be loaded by Go or QML code under the URL "qrc:///some/path", where
"some/path" matches the original path for the resource file locally.
For example, the following will load a .qml file from the resource pack, and
that file may in turn reference other content (code, images, etc) in the pack:
component, err := engine.LoadFile("qrc://path/to/file.qml")
Starting with Go 1.4, this tool may be conveniently run by the "go generate"
subcommand by adding a line similar to the following one to any existent .go
file in the project (assuming the subdirectories ./code/ and ./images/ exist):
//go:generate genqrc code images
Then, just run "go generate" to update the qrc.go file.
During development, the generated qrc.go can repack the filesystem content at
runtime to avoid the process of regenerating the qrc.go file and rebuilding the
application to test every minor change made. Runtime repacking is enabled by
setting the QRC_REPACK environment variable to 1:
export QRC_REPACK=1
This does not update the static content in the qrc.go file, though, so after
the changes are performed, genqrc must be run again to update the content that
will ship with built binaries.
`

// XXX: The documentation is duplicated here and in the the package comment
// above. Update both at the same time.

var packageName = flag.String("package", "main", "package name that qrc.go will be under (not needed for go generate)")

func main() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s", doc)
flag.PrintDefaults()
}
flag.Parse()
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}

func run() error {
subdirs := flag.Args()
if len(subdirs) == 0 {
return fmt.Errorf("must provide at least one subdirectory path")
}

var rp qml.ResourcesPacker

for _, subdir := range flag.Args() {
err := filepath.Walk(subdir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
rp.Add(filepath.ToSlash(path), data)
return nil
})
if err != nil {
return err
}
}

resdata := rp.Pack().Bytes()

f, err := os.Create("qrc.go")
if err != nil {
return err
}
defer f.Close()

data := templateData{
PackageName: *packageName,
SubDirs: subdirs,
ResourcesData: resdata,
}

// $GOPACKAGE is set automatically by go generate.
if pkgname := os.Getenv("GOPACKAGE"); pkgname != "" {
data.PackageName = pkgname
}

return tmpl.Execute(f, data)
}

type templateData struct {
PackageName string
SubDirs []string
ResourcesData []byte
}

func buildTemplate(name, content string) *template.Template {
return template.Must(template.New(name).Parse(content))
}

var tmpl = buildTemplate("qrc.go", `package {{.PackageName}}
// This file is automatically generated by gopkg.in/qml.v1/cmd/genqrc
import (
"io/ioutil"
"os"
"path/filepath"
"gopkg.in/qml.v1"
)
func init() {
var r *qml.Resources
var err error
if os.Getenv("QRC_REPACK") == "1" {
err = qrcRepackResources()
if err != nil {
panic("cannot repack qrc resources: " + err.Error())
}
r, err = qml.ParseResources(qrcResourcesRepacked)
} else {
r, err = qml.ParseResourcesString(qrcResourcesData)
}
if err != nil {
panic("cannot parse bundled resources data: " + err.Error())
}
qml.LoadResources(r)
}
func qrcRepackResources() error {
subdirs := {{printf "%#v" .SubDirs}}
var rp qml.ResourcesPacker
for _, subdir := range subdirs {
err := filepath.Walk(subdir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
rp.Add(filepath.ToSlash(path), data)
return nil
})
if err != nil {
return err
}
}
qrcResourcesRepacked = rp.Pack().Bytes()
return nil
}
var qrcResourcesRepacked []byte
var qrcResourcesData = {{printf "%q" .ResourcesData}}
`)
15 changes: 15 additions & 0 deletions cmd/ubuntu-touch/particle.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Path=/home/phablet/src/gopkg.in/qml.v0/examples/particle/
Exec=./particle
Icon=properties
Name=Particle Example
X-Ubuntu-Touch=true
X-Ubuntu-StageHint=SideStage

# Copy this file to:
#
# ~phablet/.local/share/applications/gopkg.in.qml.particle-example.desktop
41 changes: 41 additions & 0 deletions cmd/ubuntu-touch/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh

set -e

if [ "$USER" != "root" ]; then
echo 'This script must be run as root.'
exit 1
fi

echo 'Remounting root as read-write ------------------------------------------------'

mount -o remount,rw /

echo 'Installing Go and dependencies -----------------------------------------------'

apt-get update
apt-get install -y \
golang-go g++ git pkg-config ubuntu-app-launch\
qtbase5-private-dev qtdeclarative5-private-dev libqt5opengl5-dev
apt-get clean

echo 'Setting up environment for phablet user --------------------------------------'

echo 'export GOPATH=$HOME' >> ~phablet/.bash_profile

echo 'Fetching the qml package -----------------------------------------------------'

su -l phablet -c 'go get gopkg.in/qml.v0'

echo 'Installing the .desktop file for the particle example ------------------------'

APP_ID='gopkg.in.qml.particle-example'
cp ~phablet/src/gopkg.in/qml.v*/cmd/ubuntu-touch/particle.desktop ~phablet/.local/share/applications/$APP_ID.desktop

echo 'Building and launching particle example --------------------------------------'

su -l phablet -c 'cd $HOME/src/gopkg.in/qml.v0/examples/particle; go build'

echo 'Launching particle example ---------------------------------------------------'

su -l phablet -c "ubuntu-app-launch $APP_ID"
874 changes: 874 additions & 0 deletions cpp/capi.cpp

Large diffs are not rendered by default.

212 changes: 212 additions & 0 deletions cpp/capi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#ifndef CAPI_H
#define CAPI_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

// It's surprising that MaximumParamCount is privately defined within qmetaobject.cpp.
// Must fix the objectInvoke function if this is changed.
// This is Qt's MaximuParamCount - 1, as it does not take the result value in account.
enum { MaxParams = 10 };

typedef void QApplication_;
typedef void QMetaObject_;
typedef void QObject_;
typedef void QVariant_;
typedef void QVariantList_;
typedef void QString_;
typedef void QQmlEngine_;
typedef void QQmlContext_;
typedef void QQmlComponent_;
typedef void QQmlListProperty_;
typedef void QQuickWindow_;
typedef void QQuickView_;
typedef void QMessageLogContext_;
typedef void QImage_;
typedef void GoValue_;
typedef void GoAddr;
typedef uintptr_t GoRef;
typedef uintptr_t GoTypeSpec_;

typedef char error;
error *errorf(const char *format, ...);
void panicf(const char *format, ...);

typedef enum {
DTUnknown = 0, // Has an unsupported type.
DTInvalid = 1, // Does not exist or similar.

DTString = 10,
DTBool = 11,
DTInt64 = 12,
DTInt32 = 13,
DTUint64 = 14,
DTUint32 = 15,
DTUintptr = 16,
DTFloat64 = 17,
DTFloat32 = 18,
DTColor = 19,

DTGoAddr = 100,
DTObject = 101,
DTValueMap = 102,
DTValueList = 103,
DTVariantList = 104,
DTListProperty = 105,

// Used in type information, not in an actual data value.
DTAny = 201, // Can hold any of the above types.
DTMethod = 202
} DataType;

typedef struct {
DataType dataType;
char data[8];
int len;
} DataValue;

typedef struct {
char *memberName; // points to memberNames
DataType memberType;
int reflectIndex;
int reflectGetIndex;
int reflectSetIndex;
int metaIndex;
int addrOffset;
char *methodSignature;
char *resultSignature;
int numIn;
int numOut;
} GoMemberInfo;

typedef struct {
char *typeName;
GoMemberInfo *fields;
GoMemberInfo *methods;
GoMemberInfo *members; // fields + methods
GoMemberInfo *paint; // in methods too
int fieldsLen;
int methodsLen;
int membersLen;
char *memberNames;

QMetaObject_ *metaObject;
} GoTypeInfo;

typedef struct {
int severity;
const char *text;
int textLen;
const char *file;
int fileLen;
int line;
} LogMessage;

void newGuiApplication();
void applicationExec();
void applicationExit();
void applicationFlushAll();

void idleTimerInit(int32_t *guiIdleRun);
void idleTimerStart();

void *currentThread();
void *appThread();

QQmlEngine_ *newEngine(QObject_ *parent);
QQmlContext_ *engineRootContext(QQmlEngine_ *engine);
void engineSetOwnershipCPP(QQmlEngine_ *engine, QObject_ *object);
void engineSetOwnershipJS(QQmlEngine_ *engine, QObject_ *object);
void engineSetContextForObject(QQmlEngine_ *engine, QObject_ *object);
void engineAddImageProvider(QQmlEngine_ *engine, QString_ *providerId, void *imageFunc);

void contextGetProperty(QQmlContext_ *context, QString_ *name, DataValue *value);
void contextSetProperty(QQmlContext_ *context, QString_ *name, DataValue *value);
void contextSetObject(QQmlContext_ *context, QObject_ *value);
QQmlContext_ *contextSpawn(QQmlContext_ *context);

void delObject(QObject_ *object);
void delObjectLater(QObject_ *object);
const char *objectTypeName(QObject_ *object);
int objectGetProperty(QObject_ *object, const char *name, DataValue *result);
error *objectSetProperty(QObject_ *object, const char *name, DataValue *value);
void objectSetParent(QObject_ *object, QObject_ *parent);
error *objectInvoke(QObject_ *object, const char *method, int methodLen, DataValue *result, DataValue *params, int paramsLen);
void objectFindChild(QObject_ *object, QString_ *name, DataValue *result);
QQmlContext_ *objectContext(QObject_ *object);
int objectIsComponent(QObject_ *object);
int objectIsWindow(QObject_ *object);
int objectIsView(QObject_ *object);
error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, GoRef func, int argsLen);
error *objectGoRef(QObject_ *object, GoRef *ref);

QQmlComponent_ *newComponent(QQmlEngine_ *engine, QObject_ *parent);
void componentLoadURL(QQmlComponent_ *component, const char *url, int urlLen);
void componentSetData(QQmlComponent_ *component, const char *data, int dataLen, const char *url, int urlLen);
char *componentErrorString(QQmlComponent_ *component);
QObject_ *componentCreate(QQmlComponent_ *component, QQmlContext_ *context);
QQuickWindow_ *componentCreateWindow(QQmlComponent_ *component, QQmlContext_ *context);

void windowShow(QQuickWindow_ *win);
void windowHide(QQuickWindow_ *win);
uintptr_t windowPlatformId(QQuickWindow_ *win);
void windowConnectHidden(QQuickWindow_ *win);
QObject_ *windowRootObject(QQuickWindow_ *win);
QImage_ *windowGrabWindow(QQuickWindow_ *win);

QImage_ *newImage(int width, int height);
void delImage(QImage_ *image);
void imageSize(QImage_ *image, int *width, int *height);
unsigned char *imageBits(QImage_ *image);
const unsigned char *imageConstBits(QImage_ *image);

QString_ *newString(const char *data, int len);
void delString(QString_ *s);

GoValue_ *newGoValue(GoRef ref, GoTypeInfo *typeInfo, QObject_ *parent);
void goValueActivate(GoValue_ *value, GoTypeInfo *typeInfo, int addrOffset);

void packDataValue(QVariant_ *var, DataValue *result);
void unpackDataValue(DataValue *value, QVariant_ *result);

QVariantList_ *newVariantList(DataValue *list, int len);

QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);

int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec);
int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec);

void installLogHandler();

void hookIdleTimer();
void hookLogHandler(LogMessage *message);
void hookGoValueReadField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int getIndex, int setIndex, DataValue *result);
void hookGoValueWriteField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int setIndex, DataValue *assign);
void hookGoValueCallMethod(QQmlEngine_ *engine, GoRef ref, int memberIndex, DataValue *result);
void hookGoValueDestroyed(QQmlEngine_ *engine, GoRef ref);
void hookGoValuePaint(QQmlEngine_ *engine, GoRef ref, intptr_t reflextIndex);
QImage_ *hookRequestImage(void *imageFunc, char *id, int idLen, int width, int height);
GoRef hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ spec);
void hookWindowHidden(QObject_ *addr);
void hookSignalCall(QQmlEngine_ *engine, GoRef func, DataValue *params);
void hookSignalDisconnect(GoRef func);
void hookPanic(char *message);
int hookListPropertyCount(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);
QObject_ *hookListPropertyAt(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, int i);
void hookListPropertyAppend(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, QObject_ *obj);
void hookListPropertyClear(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);

void registerResourceData(int version, char *tree, char *name, char *data);
void unregisterResourceData(int version, char *tree, char *name, char *data);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // CAPI_H

// vim:ts=4:et
46 changes: 46 additions & 0 deletions cpp/connector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <QObject>

#include "connector.h"
#include "capi.h"

Connector::~Connector()
{
hookSignalDisconnect(func);
}

void Connector::invoke()
{
panicf("should never get called");
}

int Connector::qt_metacall(QMetaObject::Call c, int idx, void **a)
{
if (c == QMetaObject::InvokeMetaMethod && idx == metaObject()->methodOffset()) {
DataValue args[MaxParams];
QObject *plain = NULL;
for (int i = 0; i < argsLen; i++) {
int paramType = method.parameterType(i);
if (paramType == 0 && a[1 + i] != NULL) {
const char *typeName = method.parameterTypes()[i].constData();
void *addr = a[1 + i];
if (typeName[strlen(typeName)-1] == '*') {
addr = *(void **)addr;
}
plain = new PlainObject(typeName, addr, plain);
QVariant var = QVariant::fromValue((QObject *)plain);
packDataValue(&var, &args[i]);
} else {
QVariant var(method.parameterType(i), a[1 + i]);
packDataValue(&var, &args[i]);
}
}
hookSignalCall(engine, func, args);
if (plain != NULL) {
delete plain;
}
return -1;
}
return standard_qt_metacall(c, idx, a);
}

// vim:ts=4:sw=4:et
58 changes: 58 additions & 0 deletions cpp/connector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef CONNECTOR_H
#define CONNECTOR_H

#include <QObject>

#include <stdint.h>

class Connector : public QObject
{
Q_OBJECT

public:

Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, GoRef func, int argsLen)
: QObject(sender), engine(engine), method(method), func(func), argsLen(argsLen) {};

virtual ~Connector();

// MOC HACK: s/Connector::qt_metacall/Connector::standard_qt_metacall/
int standard_qt_metacall(QMetaObject::Call c, int idx, void **a);

public slots:

void invoke();

private:

QQmlEngine *engine;
QMetaMethod method;
GoRef func;
int argsLen;
};

class PlainObject : public QObject
{
Q_OBJECT

Q_PROPERTY(QString plainType READ getPlainType)
Q_PROPERTY(void *plainAddr READ getPlainAddr)

QString plainType;
void *plainAddr;

public:

PlainObject(QObject *parent = 0)
: QObject(parent) {};

PlainObject(const char *plainType, void *plainAddr, QObject *parent = 0)
: QObject(parent), plainType(plainType), plainAddr(plainAddr) {};

QString getPlainType() { return plainType; };
void *getPlainAddr() { return plainAddr; };
};

#endif // CONNECTOR_H

// vim:ts=4:sw=4:et
236 changes: 236 additions & 0 deletions cpp/govalue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
#include <private/qmetaobjectbuilder_p.h>

#include <QtOpenGL/QtOpenGL>
#include <QtOpenGL/QGLFunctions>

#include <QtQml/QtQml>
#include <QQmlEngine>
#include <QDebug>

#include "govalue.h"
#include "capi.h"

class GoValueMetaObject : public QAbstractDynamicMetaObject
{
public:
GoValueMetaObject(QObject* value, GoRef ref, GoTypeInfo *typeInfo);

void activatePropIndex(int propIndex);

protected:
int metaCall(QMetaObject::Call c, int id, void **a);

private:
QObject *value;
GoRef ref;
GoTypeInfo *typeInfo;
};

GoValueMetaObject::GoValueMetaObject(QObject *value, GoRef ref, GoTypeInfo *typeInfo)
: value(value), ref(ref), typeInfo(typeInfo)
{
//d->parent = static_cast<QAbstractDynamicMetaObject *>(priv->metaObject);
*static_cast<QMetaObject *>(this) = *metaObjectFor(typeInfo);

QObjectPrivate *objPriv = QObjectPrivate::get(value);
objPriv->metaObject = this;
}

int GoValueMetaObject::metaCall(QMetaObject::Call c, int idx, void **a)
{
//qWarning() << "GoValueMetaObject::metaCall" << c << idx;
switch (c) {
case QMetaObject::ReadProperty:
case QMetaObject::WriteProperty:
{
// TODO Cache propertyOffset, methodOffset (and maybe qmlEngine)
int propOffset = propertyOffset();
if (idx < propOffset) {
return value->qt_metacall(c, idx, a);
}
GoMemberInfo *memberInfo = typeInfo->fields;
for (int i = 0; i < typeInfo->fieldsLen; i++) {
if (memberInfo->metaIndex == idx) {
if (c == QMetaObject::ReadProperty) {
DataValue result;
hookGoValueReadField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectGetIndex, memberInfo->reflectSetIndex, &result);
if (memberInfo->memberType == DTListProperty) {
if (result.dataType != DTListProperty) {
panicf("reading DTListProperty field returned non-DTListProperty result");
}
QQmlListProperty<QObject> *in = *reinterpret_cast<QQmlListProperty<QObject> **>(result.data);
QQmlListProperty<QObject> *out = reinterpret_cast<QQmlListProperty<QObject> *>(a[0]);
*out = *in;
// TODO Could provide a single variable in the stack to ReadField instead.
delete in;
} else {
QVariant *out = reinterpret_cast<QVariant *>(a[0]);
unpackDataValue(&result, out);
}
} else {
DataValue assign;
QVariant *in = reinterpret_cast<QVariant *>(a[0]);
packDataValue(in, &assign);
hookGoValueWriteField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectSetIndex, &assign);
activate(value, methodOffset() + (idx - propOffset), 0);
}
return -1;
}
memberInfo++;
}
QMetaProperty prop = property(idx);
qWarning() << "Property" << prop.name() << "not found!?";
break;
}
case QMetaObject::InvokeMetaMethod:
{
if (idx < methodOffset()) {
return value->qt_metacall(c, idx, a);
}
GoMemberInfo *memberInfo = typeInfo->methods;
for (int i = 0; i < typeInfo->methodsLen; i++) {
if (memberInfo->metaIndex == idx) {
// args[0] is the result if any.
DataValue args[1 + MaxParams];
for (int i = 1; i < memberInfo->numIn+1; i++) {
packDataValue(reinterpret_cast<QVariant *>(a[i]), &args[i]);
}
hookGoValueCallMethod(qmlEngine(value), ref, memberInfo->reflectIndex, args);
if (memberInfo->numOut > 0) {
unpackDataValue(&args[0], reinterpret_cast<QVariant *>(a[0]));
}
return -1;
}
memberInfo++;
}
QMetaMethod m = method(idx);
qWarning() << "Method" << m.name() << "not found!?";
break;
}
default:
break; // Unhandled.
}
return -1;
}

void GoValueMetaObject::activatePropIndex(int propIndex)
{
// Properties are added first, so the first fieldLen methods are in
// fact the signals of the respective properties.
int relativeIndex = propIndex - propertyOffset();
activate(value, methodOffset() + relativeIndex, 0);
}

GoValue::GoValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent)
: ref(ref), typeInfo(typeInfo)
{
valueMeta = new GoValueMetaObject(this, ref, typeInfo);
setParent(parent);
}

GoValue::~GoValue()
{
hookGoValueDestroyed(qmlEngine(this), ref);
}

void GoValue::activate(int propIndex)
{
valueMeta->activatePropIndex(propIndex);
}

GoPaintedValue::GoPaintedValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent)
: ref(ref), typeInfo(typeInfo)
{
valueMeta = new GoValueMetaObject(this, ref, typeInfo);
setParent(parent);

QQuickItem::setFlag(QQuickItem::ItemHasContents, true);
QQuickPaintedItem::setRenderTarget(QQuickPaintedItem::FramebufferObject);
}

GoPaintedValue::~GoPaintedValue()
{
hookGoValueDestroyed(qmlEngine(this), ref);
}

void GoPaintedValue::activate(int propIndex)
{
valueMeta->activatePropIndex(propIndex);
}

void GoPaintedValue::paint(QPainter *painter)
{
painter->beginNativePainting();
hookGoValuePaint(qmlEngine(this), ref, typeInfo->paint->reflectIndex);
painter->endNativePainting();
}

QMetaObject *metaObjectFor(GoTypeInfo *typeInfo)
{
if (typeInfo->metaObject) {
return reinterpret_cast<QMetaObject *>(typeInfo->metaObject);
}

QMetaObjectBuilder mob;
if (typeInfo->paint) {
mob.setSuperClass(&QQuickPaintedItem::staticMetaObject);
} else {
mob.setSuperClass(&QObject::staticMetaObject);
}
mob.setClassName(typeInfo->typeName);
mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);

GoMemberInfo *memberInfo;

memberInfo = typeInfo->fields;
int relativePropIndex = mob.propertyCount();
for (int i = 0; i < typeInfo->fieldsLen; i++) {
mob.addSignal("__" + QByteArray::number(relativePropIndex) + "()");
const char *typeName = "QVariant";
if (memberInfo->memberType == DTListProperty) {
typeName = "QQmlListProperty<QObject>";
}
QMetaPropertyBuilder propb = mob.addProperty(memberInfo->memberName, typeName, relativePropIndex);
propb.setWritable(true);
memberInfo->metaIndex = relativePropIndex;
memberInfo++;
relativePropIndex++;
}

memberInfo = typeInfo->methods;
int relativeMethodIndex = mob.methodCount();
for (int i = 0; i < typeInfo->methodsLen; i++) {
if (*memberInfo->resultSignature) {
mob.addMethod(memberInfo->methodSignature, memberInfo->resultSignature);
} else {
mob.addMethod(memberInfo->methodSignature);
}
memberInfo->metaIndex = relativeMethodIndex;
memberInfo++;
relativeMethodIndex++;
}

// TODO Support default properties.
//mob.addClassInfo("DefaultProperty", "objects");

QMetaObject *mo = mob.toMetaObject();

// Turn the relative indexes into absolute indexes.
memberInfo = typeInfo->fields;
int propOffset = mo->propertyOffset();
for (int i = 0; i < typeInfo->fieldsLen; i++) {
memberInfo->metaIndex += propOffset;
memberInfo++;
}
memberInfo = typeInfo->methods;
int methodOffset = mo->methodOffset();
for (int i = 0; i < typeInfo->methodsLen; i++) {
memberInfo->metaIndex += methodOffset;
memberInfo++;
}

typeInfo->metaObject = mo;
return mo;
}

// vim:ts=4:sw=4:et:ft=cpp
56 changes: 56 additions & 0 deletions cpp/govalue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef GOVALUE_H
#define GOVALUE_H

// Unfortunatley we need access to private bits, because the
// whole dynamic meta-object concept is sadly being hidden
// away, and without it this package wouldn't exist.
#include <private/qmetaobject_p.h>

#include <QQuickPaintedItem>
#include <QPainter>

#include "capi.h"

class GoValueMetaObject;

QMetaObject *metaObjectFor(GoTypeInfo *typeInfo);

class GoValue : public QObject
{
Q_OBJECT

public:
GoRef ref;
GoTypeInfo *typeInfo;

GoValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent);
virtual ~GoValue();

void activate(int propIndex);

private:
GoValueMetaObject *valueMeta;
};

class GoPaintedValue : public QQuickPaintedItem
{
Q_OBJECT

public:
GoRef ref;
GoTypeInfo *typeInfo;

GoPaintedValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent);
virtual ~GoPaintedValue();

void activate(int propIndex);

virtual void paint(QPainter *painter);

private:
GoValueMetaObject *valueMeta;
};

#endif // GOVALUE_H

// vim:ts=4:sw=4:et:ft=cpp
254 changes: 254 additions & 0 deletions cpp/govaluetype.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#include "govaluetype.h"

#define DEFINE_GOVALUETYPE(N) \
template<> QMetaObject GoValueType<N>::staticMetaObject = QMetaObject(); \
template<> GoTypeInfo *GoValueType<N>::typeInfo = 0; \
template<> GoTypeSpec_ GoValueType<N>::typeSpec = 0;

#define DEFINE_GOPAINTEDVALUETYPE(N) \
template<> QMetaObject GoPaintedValueType<N>::staticMetaObject = QMetaObject(); \
template<> GoTypeInfo *GoPaintedValueType<N>::typeInfo = 0; \
template<> GoTypeSpec_ GoPaintedValueType<N>::typeSpec = 0;

DEFINE_GOVALUETYPE(1)
DEFINE_GOVALUETYPE(2)
DEFINE_GOVALUETYPE(3)
DEFINE_GOVALUETYPE(4)
DEFINE_GOVALUETYPE(5)
DEFINE_GOVALUETYPE(6)
DEFINE_GOVALUETYPE(7)
DEFINE_GOVALUETYPE(8)
DEFINE_GOVALUETYPE(9)
DEFINE_GOVALUETYPE(10)
DEFINE_GOVALUETYPE(11)
DEFINE_GOVALUETYPE(12)
DEFINE_GOVALUETYPE(13)
DEFINE_GOVALUETYPE(14)
DEFINE_GOVALUETYPE(15)
DEFINE_GOVALUETYPE(16)
DEFINE_GOVALUETYPE(17)
DEFINE_GOVALUETYPE(18)
DEFINE_GOVALUETYPE(19)
DEFINE_GOVALUETYPE(20)
DEFINE_GOVALUETYPE(21)
DEFINE_GOVALUETYPE(22)
DEFINE_GOVALUETYPE(23)
DEFINE_GOVALUETYPE(24)
DEFINE_GOVALUETYPE(25)
DEFINE_GOVALUETYPE(26)
DEFINE_GOVALUETYPE(27)
DEFINE_GOVALUETYPE(28)
DEFINE_GOVALUETYPE(29)
DEFINE_GOVALUETYPE(30)

DEFINE_GOPAINTEDVALUETYPE(1)
DEFINE_GOPAINTEDVALUETYPE(2)
DEFINE_GOPAINTEDVALUETYPE(3)
DEFINE_GOPAINTEDVALUETYPE(4)
DEFINE_GOPAINTEDVALUETYPE(5)
DEFINE_GOPAINTEDVALUETYPE(6)
DEFINE_GOPAINTEDVALUETYPE(7)
DEFINE_GOPAINTEDVALUETYPE(8)
DEFINE_GOPAINTEDVALUETYPE(9)
DEFINE_GOPAINTEDVALUETYPE(10)
DEFINE_GOPAINTEDVALUETYPE(11)
DEFINE_GOPAINTEDVALUETYPE(12)
DEFINE_GOPAINTEDVALUETYPE(13)
DEFINE_GOPAINTEDVALUETYPE(14)
DEFINE_GOPAINTEDVALUETYPE(15)
DEFINE_GOPAINTEDVALUETYPE(16)
DEFINE_GOPAINTEDVALUETYPE(17)
DEFINE_GOPAINTEDVALUETYPE(18)
DEFINE_GOPAINTEDVALUETYPE(19)
DEFINE_GOPAINTEDVALUETYPE(20)
DEFINE_GOPAINTEDVALUETYPE(21)
DEFINE_GOPAINTEDVALUETYPE(22)
DEFINE_GOPAINTEDVALUETYPE(23)
DEFINE_GOPAINTEDVALUETYPE(24)
DEFINE_GOPAINTEDVALUETYPE(25)
DEFINE_GOPAINTEDVALUETYPE(26)
DEFINE_GOPAINTEDVALUETYPE(27)
DEFINE_GOPAINTEDVALUETYPE(28)
DEFINE_GOPAINTEDVALUETYPE(29)
DEFINE_GOPAINTEDVALUETYPE(30)

static int goValueTypeN = 0;
static int goPaintedValueTypeN = 0;

template<int N>
int registerSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) {
GoValueType<N>::init(info, spec);
return qmlRegisterSingletonType< GoValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* {
QObject *singleton = new GoValueType<N>();
QQmlEngine::setContextForObject(singleton, qmlEngine->rootContext());
return singleton;
});
}

template<int N>
int registerPaintedSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) {
GoPaintedValueType<N>::init(info, spec);
return qmlRegisterSingletonType< GoPaintedValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* {
QObject *singleton = new GoPaintedValueType<N>();
QQmlEngine::setContextForObject(singleton, qmlEngine->rootContext());
return singleton;
});
}

#define GOVALUETYPE_CASE_SINGLETON(N) \
case N: return registerSingletonN<N>(location, major, minor, name, info, spec);
#define GOPAINTEDVALUETYPE_CASE_SINGLETON(N) \
case N: return registerPaintedSingletonN<N>(location, major, minor, name, info, spec);

int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec)
{
if (!info->paint) {
switch (++goValueTypeN) {
GOVALUETYPE_CASE_SINGLETON(1)
GOVALUETYPE_CASE_SINGLETON(2)
GOVALUETYPE_CASE_SINGLETON(3)
GOVALUETYPE_CASE_SINGLETON(4)
GOVALUETYPE_CASE_SINGLETON(5)
GOVALUETYPE_CASE_SINGLETON(6)
GOVALUETYPE_CASE_SINGLETON(7)
GOVALUETYPE_CASE_SINGLETON(8)
GOVALUETYPE_CASE_SINGLETON(9)
GOVALUETYPE_CASE_SINGLETON(10)
GOVALUETYPE_CASE_SINGLETON(11)
GOVALUETYPE_CASE_SINGLETON(12)
GOVALUETYPE_CASE_SINGLETON(13)
GOVALUETYPE_CASE_SINGLETON(14)
GOVALUETYPE_CASE_SINGLETON(15)
GOVALUETYPE_CASE_SINGLETON(16)
GOVALUETYPE_CASE_SINGLETON(17)
GOVALUETYPE_CASE_SINGLETON(18)
GOVALUETYPE_CASE_SINGLETON(19)
GOVALUETYPE_CASE_SINGLETON(20)
GOVALUETYPE_CASE_SINGLETON(21)
GOVALUETYPE_CASE_SINGLETON(22)
GOVALUETYPE_CASE_SINGLETON(23)
GOVALUETYPE_CASE_SINGLETON(24)
GOVALUETYPE_CASE_SINGLETON(25)
GOVALUETYPE_CASE_SINGLETON(26)
GOVALUETYPE_CASE_SINGLETON(27)
GOVALUETYPE_CASE_SINGLETON(28)
GOVALUETYPE_CASE_SINGLETON(29)
GOVALUETYPE_CASE_SINGLETON(30)
}
} else {
switch (++goPaintedValueTypeN) {
GOPAINTEDVALUETYPE_CASE_SINGLETON(1)
GOPAINTEDVALUETYPE_CASE_SINGLETON(2)
GOPAINTEDVALUETYPE_CASE_SINGLETON(3)
GOPAINTEDVALUETYPE_CASE_SINGLETON(4)
GOPAINTEDVALUETYPE_CASE_SINGLETON(5)
GOPAINTEDVALUETYPE_CASE_SINGLETON(6)
GOPAINTEDVALUETYPE_CASE_SINGLETON(7)
GOPAINTEDVALUETYPE_CASE_SINGLETON(8)
GOPAINTEDVALUETYPE_CASE_SINGLETON(9)
GOPAINTEDVALUETYPE_CASE_SINGLETON(10)
GOPAINTEDVALUETYPE_CASE_SINGLETON(11)
GOPAINTEDVALUETYPE_CASE_SINGLETON(12)
GOPAINTEDVALUETYPE_CASE_SINGLETON(13)
GOPAINTEDVALUETYPE_CASE_SINGLETON(14)
GOPAINTEDVALUETYPE_CASE_SINGLETON(15)
GOPAINTEDVALUETYPE_CASE_SINGLETON(16)
GOPAINTEDVALUETYPE_CASE_SINGLETON(17)
GOPAINTEDVALUETYPE_CASE_SINGLETON(18)
GOPAINTEDVALUETYPE_CASE_SINGLETON(19)
GOPAINTEDVALUETYPE_CASE_SINGLETON(20)
GOPAINTEDVALUETYPE_CASE_SINGLETON(21)
GOPAINTEDVALUETYPE_CASE_SINGLETON(22)
GOPAINTEDVALUETYPE_CASE_SINGLETON(23)
GOPAINTEDVALUETYPE_CASE_SINGLETON(24)
GOPAINTEDVALUETYPE_CASE_SINGLETON(25)
GOPAINTEDVALUETYPE_CASE_SINGLETON(26)
GOPAINTEDVALUETYPE_CASE_SINGLETON(27)
GOPAINTEDVALUETYPE_CASE_SINGLETON(28)
GOPAINTEDVALUETYPE_CASE_SINGLETON(29)
GOPAINTEDVALUETYPE_CASE_SINGLETON(30)
}
}
panicf("too many registered types; please contact the Go QML developers");
return 0;
}

#define GOVALUETYPE_CASE(N) \
case N: GoValueType<N>::init(info, spec); return qmlRegisterType< GoValueType<N> >(location, major, minor, name);
#define GOPAINTEDVALUETYPE_CASE(N) \
case N: GoPaintedValueType<N>::init(info, spec); return qmlRegisterType< GoPaintedValueType<N> >(location, major, minor, name);

int registerType(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec)
{
if (!info->paint) {
switch (++goValueTypeN) {
GOVALUETYPE_CASE(1)
GOVALUETYPE_CASE(2)
GOVALUETYPE_CASE(3)
GOVALUETYPE_CASE(4)
GOVALUETYPE_CASE(5)
GOVALUETYPE_CASE(6)
GOVALUETYPE_CASE(7)
GOVALUETYPE_CASE(8)
GOVALUETYPE_CASE(9)
GOVALUETYPE_CASE(10)
GOVALUETYPE_CASE(11)
GOVALUETYPE_CASE(12)
GOVALUETYPE_CASE(13)
GOVALUETYPE_CASE(14)
GOVALUETYPE_CASE(15)
GOVALUETYPE_CASE(16)
GOVALUETYPE_CASE(17)
GOVALUETYPE_CASE(18)
GOVALUETYPE_CASE(19)
GOVALUETYPE_CASE(20)
GOVALUETYPE_CASE(21)
GOVALUETYPE_CASE(22)
GOVALUETYPE_CASE(23)
GOVALUETYPE_CASE(24)
GOVALUETYPE_CASE(25)
GOVALUETYPE_CASE(26)
GOVALUETYPE_CASE(27)
GOVALUETYPE_CASE(28)
GOVALUETYPE_CASE(29)
GOVALUETYPE_CASE(30)
}
} else {
switch (++goPaintedValueTypeN) {
GOPAINTEDVALUETYPE_CASE(1)
GOPAINTEDVALUETYPE_CASE(2)
GOPAINTEDVALUETYPE_CASE(3)
GOPAINTEDVALUETYPE_CASE(4)
GOPAINTEDVALUETYPE_CASE(5)
GOPAINTEDVALUETYPE_CASE(6)
GOPAINTEDVALUETYPE_CASE(7)
GOPAINTEDVALUETYPE_CASE(8)
GOPAINTEDVALUETYPE_CASE(9)
GOPAINTEDVALUETYPE_CASE(10)
GOPAINTEDVALUETYPE_CASE(11)
GOPAINTEDVALUETYPE_CASE(12)
GOPAINTEDVALUETYPE_CASE(13)
GOPAINTEDVALUETYPE_CASE(14)
GOPAINTEDVALUETYPE_CASE(15)
GOPAINTEDVALUETYPE_CASE(16)
GOPAINTEDVALUETYPE_CASE(17)
GOPAINTEDVALUETYPE_CASE(18)
GOPAINTEDVALUETYPE_CASE(19)
GOPAINTEDVALUETYPE_CASE(20)
GOPAINTEDVALUETYPE_CASE(21)
GOPAINTEDVALUETYPE_CASE(22)
GOPAINTEDVALUETYPE_CASE(23)
GOPAINTEDVALUETYPE_CASE(24)
GOPAINTEDVALUETYPE_CASE(25)
GOPAINTEDVALUETYPE_CASE(26)
GOPAINTEDVALUETYPE_CASE(27)
GOPAINTEDVALUETYPE_CASE(28)
GOPAINTEDVALUETYPE_CASE(29)
GOPAINTEDVALUETYPE_CASE(30)
}
}
panicf("too many registered types; please contact the Go QML developers");
return 0;
}

// vim:sw=4:st=4:et:ft=cpp
48 changes: 48 additions & 0 deletions cpp/govaluetype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef GOVALUETYPE_H
#define GOVALUETYPE_H

#include "govalue.h"

template <int N>
class GoValueType : public GoValue
{
public:

GoValueType()
: GoValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {};

static void init(GoTypeInfo *info, GoTypeSpec_ spec)
{
typeInfo = info;
typeSpec = spec;
static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo);
};

static GoTypeSpec_ typeSpec;
static GoTypeInfo *typeInfo;
static QMetaObject staticMetaObject;
};

template <int N>
class GoPaintedValueType : public GoPaintedValue
{
public:

GoPaintedValueType()
: GoPaintedValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {};

static void init(GoTypeInfo *info, GoTypeSpec_ spec)
{
typeInfo = info;
typeSpec = spec;
static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo);
};

static GoTypeSpec_ typeSpec;
static GoTypeInfo *typeInfo;
static QMetaObject staticMetaObject;
};

#endif // GOVALUETYPE_H

// vim:ts=4:sw=4:et
58 changes: 58 additions & 0 deletions cpp/idletimer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <QBasicTimer>
#include <QThread>
#include <QDebug>
#include <mutex>

#include "capi.h"

class IdleTimer : public QObject
{
Q_OBJECT

public:

static IdleTimer *singleton() {
static IdleTimer singleton;
return &singleton;
}

void init(int32_t *guiIdleRun)
{
this->guiIdleRun = guiIdleRun;
}

Q_INVOKABLE void start()
{
timer.start(0, this);
}

protected:

void timerEvent(QTimerEvent *event)
{
__sync_synchronize();
if (*guiIdleRun > 0) {
hookIdleTimer();
} else {
timer.stop();
}
}

private:

int32_t *guiIdleRun;

QBasicTimer timer;
};

void idleTimerInit(int32_t *guiIdleRun)
{
IdleTimer::singleton()->init(guiIdleRun);
}

void idleTimerStart()
{
QMetaObject::invokeMethod(IdleTimer::singleton(), "start", Qt::QueuedConnection);
}

// vim:ts=4:sw=4:et:ft=cpp
27 changes: 27 additions & 0 deletions cpp/mmemwin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <windows.h>

#define protREAD 1
#define protWRITE 2
#define protEXEC 4

extern "C" {

int mprotect(void *addr, size_t len, int prot)
{
DWORD wprot = 0;
if (prot & protWRITE) {
wprot = PAGE_READWRITE;
} else if (prot & protREAD) {
wprot = PAGE_READONLY;
}
if (prot & protEXEC) {
wprot <<= 4;
}
DWORD oldwprot;
if (!VirtualProtect(addr, len, wprot, &oldwprot)) {
return -1;
}
return 0;
}

} // extern "C"
4 changes: 4 additions & 0 deletions cpp/moc_all.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file is automatically generated by cpp/update-moc.sh
#include "cpp/moc_connector.cpp"
#include "cpp/moc_govalue.cpp"
#include "cpp/moc_idletimer.cpp"
211 changes: 211 additions & 0 deletions cpp/moc_connector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/****************************************************************************
** Meta object code from reading C++ file 'connector.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.2.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include "connector.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'connector.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.2.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_Connector_t {
QByteArrayData data[3];
char stringdata[19];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_Connector_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_Connector_t qt_meta_stringdata_Connector = {
{
QT_MOC_LITERAL(0, 0, 9),
QT_MOC_LITERAL(1, 10, 6),
QT_MOC_LITERAL(2, 17, 0)
},
"Connector\0invoke\0\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_Connector[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount

// slots: name, argc, parameters, tag, flags
1, 0, 19, 2, 0x0a,

// slots: parameters
QMetaType::Void,

0 // eod
};

void Connector::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Connector *_t = static_cast<Connector *>(_o);
switch (_id) {
case 0: _t->invoke(); break;
default: ;
}
}
Q_UNUSED(_a);
}

const QMetaObject Connector::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_Connector.data,
qt_meta_data_Connector, qt_static_metacall, 0, 0}
};


const QMetaObject *Connector::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *Connector::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Connector.stringdata))
return static_cast<void*>(const_cast< Connector*>(this));
return QObject::qt_metacast(_clname);
}

int Connector::standard_qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 1)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 1;
}
return _id;
}
struct qt_meta_stringdata_PlainObject_t {
QByteArrayData data[3];
char stringdata[33];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_PlainObject_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_PlainObject_t qt_meta_stringdata_PlainObject = {
{
QT_MOC_LITERAL(0, 0, 11),
QT_MOC_LITERAL(1, 12, 9),
QT_MOC_LITERAL(2, 22, 9)
},
"PlainObject\0plainType\0plainAddr\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_PlainObject[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
2, 14, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount

// properties: name, type, flags
1, QMetaType::QString, 0x00095001,
2, QMetaType::VoidStar, 0x00095001,

0 // eod
};

void PlainObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}

const QMetaObject PlainObject::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_PlainObject.data,
qt_meta_data_PlainObject, qt_static_metacall, 0, 0}
};


const QMetaObject *PlainObject::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *PlainObject::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_PlainObject.stringdata))
return static_cast<void*>(const_cast< PlainObject*>(this));
return QObject::qt_metacast(_clname);
}

int PlainObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;

#ifndef QT_NO_PROPERTIES
if (_c == QMetaObject::ReadProperty) {
void *_v = _a[0];
switch (_id) {
case 0: *reinterpret_cast< QString*>(_v) = getPlainType(); break;
case 1: *reinterpret_cast< void**>(_v) = getPlainAddr(); break;
}
_id -= 2;
} else if (_c == QMetaObject::WriteProperty) {
_id -= 2;
} else if (_c == QMetaObject::ResetProperty) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyDesignable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyScriptable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyStored) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyEditable) {
_id -= 2;
} else if (_c == QMetaObject::QueryPropertyUser) {
_id -= 2;
} else if (_c == QMetaObject::RegisterPropertyMetaType) {
if (_id < 2)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 2;
}
#endif // QT_NO_PROPERTIES
return _id;
}
QT_END_MOC_NAMESPACE
155 changes: 155 additions & 0 deletions cpp/moc_govalue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/****************************************************************************
** Meta object code from reading C++ file 'govalue.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.2.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include "govalue.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'govalue.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.2.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_GoValue_t {
QByteArrayData data[1];
char stringdata[9];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_GoValue_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_GoValue_t qt_meta_stringdata_GoValue = {
{
QT_MOC_LITERAL(0, 0, 7)
},
"GoValue\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_GoValue[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount

0 // eod
};

void GoValue::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}

const QMetaObject GoValue::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_GoValue.data,
qt_meta_data_GoValue, qt_static_metacall, 0, 0}
};


const QMetaObject *GoValue::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *GoValue::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_GoValue.stringdata))
return static_cast<void*>(const_cast< GoValue*>(this));
return QObject::qt_metacast(_clname);
}

int GoValue::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
return _id;
}
struct qt_meta_stringdata_GoPaintedValue_t {
QByteArrayData data[1];
char stringdata[16];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_GoPaintedValue_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_GoPaintedValue_t qt_meta_stringdata_GoPaintedValue = {
{
QT_MOC_LITERAL(0, 0, 14)
},
"GoPaintedValue\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_GoPaintedValue[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount

0 // eod
};

void GoPaintedValue::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}

const QMetaObject GoPaintedValue::staticMetaObject = {
{ &QQuickPaintedItem::staticMetaObject, qt_meta_stringdata_GoPaintedValue.data,
qt_meta_data_GoPaintedValue, qt_static_metacall, 0, 0}
};


const QMetaObject *GoPaintedValue::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *GoPaintedValue::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_GoPaintedValue.stringdata))
return static_cast<void*>(const_cast< GoPaintedValue*>(this));
return QQuickPaintedItem::qt_metacast(_clname);
}

int GoPaintedValue::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QQuickPaintedItem::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
return _id;
}
QT_END_MOC_NAMESPACE
108 changes: 108 additions & 0 deletions cpp/moc_idletimer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/****************************************************************************
** Meta object code from reading C++ file 'idletimer.cpp'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.2.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'idletimer.cpp' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.2.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_IdleTimer_t {
QByteArrayData data[3];
char stringdata[18];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_IdleTimer_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_IdleTimer_t qt_meta_stringdata_IdleTimer = {
{
QT_MOC_LITERAL(0, 0, 9),
QT_MOC_LITERAL(1, 10, 5),
QT_MOC_LITERAL(2, 16, 0)
},
"IdleTimer\0start\0\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_IdleTimer[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
1, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount

// methods: name, argc, parameters, tag, flags
1, 0, 19, 2, 0x02,

// methods: parameters
QMetaType::Void,

0 // eod
};

void IdleTimer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
IdleTimer *_t = static_cast<IdleTimer *>(_o);
switch (_id) {
case 0: _t->start(); break;
default: ;
}
}
Q_UNUSED(_a);
}

const QMetaObject IdleTimer::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_IdleTimer.data,
qt_meta_data_IdleTimer, qt_static_metacall, 0, 0}
};


const QMetaObject *IdleTimer::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *IdleTimer::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_IdleTimer.stringdata))
return static_cast<void*>(const_cast< IdleTimer*>(this));
return QObject::qt_metacast(_clname);
}

int IdleTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 1)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 1;
}
return _id;
}
QT_END_MOC_NAMESPACE
2 changes: 2 additions & 0 deletions cpp/private/qmetaobject_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "private/qtheader.h"
#include QT_PRIVATE_HEADER(QtCore,qmetaobject_p.h)
2 changes: 2 additions & 0 deletions cpp/private/qmetaobjectbuilder_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "private/qtheader.h"
#include QT_PRIVATE_HEADER(QtCore,qmetaobjectbuilder_p.h)
2 changes: 2 additions & 0 deletions cpp/private/qobject_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "private/qtheader.h"
#include QT_PRIVATE_HEADER(QtCore,qobject_p.h)
70 changes: 70 additions & 0 deletions cpp/private/qtheader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#ifndef QTPRIVATE_H
#define QTPRIVATE_H

#include <QtCore/qglobal.h>

#define QT_MAJOR_ (QT_VERSION>>16)
#define QT_MINOR_ (QT_VERSION>>8&0xFF)
#define QT_MICRO_ (QT_VERSION&0xFF)

#if QT_MAJOR_ == 5
#define QT_MAJOR 5
#else
#error Unupported Qt major version. Please report.
#endif

#if QT_MINOR_ == 0
#define QT_MINOR 0
#elif QT_MINOR_ == 1
#define QT_MINOR 1
#elif QT_MINOR_ == 2
#define QT_MINOR 2
#elif QT_MINOR_ == 3
#define QT_MINOR 3
#elif QT_MINOR_ == 4
#define QT_MINOR 4
#elif QT_MINOR_ == 5
#define QT_MINOR 5
#elif QT_MINOR_ == 6
#define QT_MINOR 6
#elif QT_MINOR_ == 7
#define QT_MINOR 7
#elif QT_MINOR_ == 8
#define QT_MINOR 8
#elif QT_MINOR_ == 9
#define QT_MINOR 9
#elif QT_MINOR_ == 10
#define QT_MINOR 10
#else
#error Unupported Qt minor version. Please report.
#endif

#if QT_MICRO_ == 0
#define QT_MICRO 0
#elif QT_MICRO_ == 1
#define QT_MICRO 1
#elif QT_MICRO_ == 2
#define QT_MICRO 2
#elif QT_MICRO_ == 3
#define QT_MICRO 3
#elif QT_MICRO_ == 4
#define QT_MICRO 4
#elif QT_MICRO_ == 5
#define QT_MICRO 5
#elif QT_MICRO_ == 6
#define QT_MICRO 6
#elif QT_MICRO_ == 7
#define QT_MICRO 7
#elif QT_MICRO_ == 8
#define QT_MICRO 8
#elif QT_MICRO_ == 9
#define QT_MICRO 9
#elif QT_MICRO_ == 10
#define QT_MICRO 10
#else
#error Unupported Qt micro version. Please report.
#endif

#define QT_PRIVATE_HEADER(dir,file) <dir/QT_MAJOR.QT_MINOR.QT_MICRO/dir/private/file>

#endif // QTPRIVATE_H
19 changes: 19 additions & 0 deletions cpp/update-moc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh

set -e
cd `dirname $0`

subdir=`basename $PWD`

export QT_SELECT=5

ALL=moc_all.cpp

echo "// This file is automatically generated by cpp/update-moc.sh" > $ALL

for file in `grep -l Q_''OBJECT *`; do
mocfile=`echo $file | awk -F. '{print("moc_"$1".cpp")}'`
mochack=`sed -n 's,^ *// MOC HACK: \(.*\),\1,p' $file`
moc $file | sed "$mochack" > $mocfile
echo "#include \"$subdir/$mocfile\"" >> $ALL
done
14 changes: 14 additions & 0 deletions cpptest/cpptest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <string.h>

#include "cpptest.h"
#include "testtype.h"

TestType_ *newTestType()
{
return new TestType();
}

int plainTestTypeN(PlainTestType_ *plain)
{
return static_cast<PlainTestType *>(plain)->n;
}
30 changes: 30 additions & 0 deletions cpptest/cpptest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Package cpptest is an internal test helper.
package cpptest

// #cgo CXXFLAGS: -std=c++0x -Wall -fno-strict-aliasing -I..
// #cgo LDFLAGS: -lstdc++
//
// #cgo pkg-config: Qt5Core
//
// #include "cpptest.h"
//
import "C"

import (
"unsafe"

"gopkg.in/qml.v1"
)

func NewTestType(engine *qml.Engine) qml.Object {
var obj qml.Object
qml.RunMain(func() {
addr := C.newTestType()
obj = qml.CommonOf(addr, engine)
})
return obj
}

func PlainTestTypeN(obj qml.Object) int {
return int(C.plainTestTypeN(unsafe.Pointer(obj.Property("plainAddr").(uintptr))))
}
23 changes: 23 additions & 0 deletions cpptest/cpptest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef UONEAUTH_H
#define UONEAUTH_H

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>

typedef void TestType_;
typedef void PlainTestType_;

#ifdef __cplusplus
extern "C" {
#endif

TestType_ *newTestType();

int plainTestTypeN(PlainTestType_ *plain);

#ifdef __cplusplus
}
#endif

#endif // UONEAUTH_H
202 changes: 202 additions & 0 deletions cpptest/moc_testtype.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/****************************************************************************
** Meta object code from reading C++ file 'testtype.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.2.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include "testtype.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'testtype.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.2.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_TestType_t {
QByteArrayData data[10];
char stringdata[119];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
offsetof(qt_meta_stringdata_TestType_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData) \
)
static const qt_meta_stringdata_TestType_t qt_meta_stringdata_TestType = {
{
QT_MOC_LITERAL(0, 0, 8),
QT_MOC_LITERAL(1, 9, 15),
QT_MOC_LITERAL(2, 25, 0),
QT_MOC_LITERAL(3, 26, 13),
QT_MOC_LITERAL(4, 40, 5),
QT_MOC_LITERAL(5, 46, 15),
QT_MOC_LITERAL(6, 62, 15),
QT_MOC_LITERAL(7, 78, 20),
QT_MOC_LITERAL(8, 99, 9),
QT_MOC_LITERAL(9, 109, 8)
},
"TestType\0plainEmittedCpy\0\0PlainTestType\0"
"plain\0plainEmittedRef\0plainEmittedPtr\0"
"const PlainTestType*\0emitPlain\0voidAddr\0"
};
#undef QT_MOC_LITERAL

static const uint qt_meta_data_TestType[] = {

// content:
7, // revision
0, // classname
0, 0, // classinfo
4, 14, // methods
1, 44, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
3, // signalCount

// signals: name, argc, parameters, tag, flags
1, 1, 34, 2, 0x06,
5, 1, 37, 2, 0x06,
6, 1, 40, 2, 0x06,

// methods: name, argc, parameters, tag, flags
8, 0, 43, 2, 0x02,

// signals: parameters
QMetaType::Void, 0x80000000 | 3, 4,
QMetaType::Void, 0x80000000 | 3, 4,
QMetaType::Void, 0x80000000 | 7, 4,

// methods: parameters
QMetaType::Void,

// properties: name, type, flags
9, QMetaType::VoidStar, 0x00095001,

0 // eod
};

void TestType::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
TestType *_t = static_cast<TestType *>(_o);
switch (_id) {
case 0: _t->plainEmittedCpy((*reinterpret_cast< const PlainTestType(*)>(_a[1]))); break;
case 1: _t->plainEmittedRef((*reinterpret_cast< const PlainTestType(*)>(_a[1]))); break;
case 2: _t->plainEmittedPtr((*reinterpret_cast< const PlainTestType*(*)>(_a[1]))); break;
case 3: _t->emitPlain(); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
void **func = reinterpret_cast<void **>(_a[1]);
{
typedef void (TestType::*_t)(const PlainTestType );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&TestType::plainEmittedCpy)) {
*result = 0;
}
}
{
typedef void (TestType::*_t)(const PlainTestType & );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&TestType::plainEmittedRef)) {
*result = 1;
}
}
{
typedef void (TestType::*_t)(const PlainTestType * );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&TestType::plainEmittedPtr)) {
*result = 2;
}
}
}
}

const QMetaObject TestType::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_TestType.data,
qt_meta_data_TestType, qt_static_metacall, 0, 0}
};


const QMetaObject *TestType::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

void *TestType::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_TestType.stringdata))
return static_cast<void*>(const_cast< TestType*>(this));
return QObject::qt_metacast(_clname);
}

int TestType::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 4)
qt_static_metacall(this, _c, _id, _a);
_id -= 4;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 4)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 4;
}
#ifndef QT_NO_PROPERTIES
else if (_c == QMetaObject::ReadProperty) {
void *_v = _a[0];
switch (_id) {
case 0: *reinterpret_cast< void**>(_v) = getVoidAddr(); break;
}
_id -= 1;
} else if (_c == QMetaObject::WriteProperty) {
_id -= 1;
} else if (_c == QMetaObject::ResetProperty) {
_id -= 1;
} else if (_c == QMetaObject::QueryPropertyDesignable) {
_id -= 1;
} else if (_c == QMetaObject::QueryPropertyScriptable) {
_id -= 1;
} else if (_c == QMetaObject::QueryPropertyStored) {
_id -= 1;
} else if (_c == QMetaObject::QueryPropertyEditable) {
_id -= 1;
} else if (_c == QMetaObject::QueryPropertyUser) {
_id -= 1;
} else if (_c == QMetaObject::RegisterPropertyMetaType) {
if (_id < 1)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 1;
}
#endif // QT_NO_PROPERTIES
return _id;
}

// SIGNAL 0
void TestType::plainEmittedCpy(const PlainTestType _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

// SIGNAL 1
void TestType::plainEmittedRef(const PlainTestType & _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}

// SIGNAL 2
void TestType::plainEmittedPtr(const PlainTestType * _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 2, _a);
}
QT_END_MOC_NAMESPACE
45 changes: 45 additions & 0 deletions cpptest/testtype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef TESTTYPE_H
#define TESTTYPE_H

#include <QObject>

class PlainTestType {

public:

PlainTestType(int n) : n(n) {};

int n;
};

class TestType : public QObject
{
Q_OBJECT

Q_PROPERTY(void *voidAddr READ getVoidAddr)

void *voidAddr;

public:

TestType(QObject *parent = 0) : QObject(parent), voidAddr((void*)42) {};

void *getVoidAddr() { return voidAddr; };

Q_INVOKABLE void emitPlain() {
PlainTestType plain = PlainTestType(42);
emit plainEmittedCpy(plain);
emit plainEmittedRef(plain);
emit plainEmittedPtr(&plain);
};

signals:

void plainEmittedCpy(const PlainTestType plain);
void plainEmittedRef(const PlainTestType &plain);
void plainEmittedPtr(const PlainTestType *plain);
};

#endif // TESTTYPE_H

// vim:ts=4:sw=4:et
12 changes: 12 additions & 0 deletions cpptest/update-moc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

set -e
cd `dirname $0`

export QT_SELECT=5

for file in `grep -l Q_''OBJECT *`; do
mocfile=`echo $file | awk -F. '{print("moc_"$1".cpp")}'`
mochack=`sed -n 's,^ *// MOC HACK: \(.*\),\1,p' $file`
moc $file | sed "$mochack" > $mocfile
done
530 changes: 530 additions & 0 deletions datatype.go

Large diffs are not rendered by default.

199 changes: 199 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// Package qml offers graphical QML application support for the Go language.
//
// Attention
//
// This package is in an alpha stage, and still in heavy development. APIs may
// change, and things may break.
//
// At this time contributors and developers that are interested in tracking the
// development closely are encouraged to use it. If you'd prefer a more stable
// release, please hold on a bit and subscribe to the mailing list for news. It's
// in a pretty good state, so it shall not take too long.
//
// See http://github.com/go-qml/qml for details.
//
//
// Introduction
//
// The qml package enables Go programs to display and manipulate graphical content
// using Qt's QML framework. QML uses a declarative language to express structure
// and style, and supports JavaScript for in-place manipulation of the described
// content. When using the Go qml package, such QML content can also interact with
// Go values, making use of its exported fields and methods, and even explicitly
// creating new instances of registered Go types.
//
// A simple Go application that integrates with QML may perform the following steps
// for offering a graphical interface:
//
// * Call qml.Run from function main providing a function with the logic below
// * Create an engine for loading and running QML content (see NewEngine)
// * Make Go values and types available to QML (see Context.SetVar and RegisterType)
// * Load QML content (see Engine.LoadString and Engine.LoadFile)
// * Create a new window for the content (see Component.CreateWindow)
// * Show the window and wait for it to be closed (see Window.Show and Window.Wait)
//
// Some of these topics are covered below, and may also be observed in practice
// in the following examples:
//
// https://github.com/go-qml/qml/tree/v1/examples
//
//
// Simple example
//
// The following logic demonstrates loading a QML file into a window:
//
// func main() {
// err := qml.Run(run)
// ...
// }
//
// func run() error {
// engine := qml.NewEngine()
// component, err := engine.LoadFile("file.qml")
// if err != nil {
// return err
// }
// win := component.CreateWindow(nil)
// win.Show()
// win.Wait()
// return nil
// }
//
// Handling QML objects in Go
//
// Any QML object may be manipulated by Go via the Object interface. That
// interface is implemented both by dynamic QML values obtained from a running
// engine, and by Go types in the qml package that represent QML values, such as
// Window, Context, and Engine.
//
// For example, the following logic creates a window and prints its width
// whenever it's made visible:
//
// win := component.CreateWindow(nil)
// win.On("visibleChanged", func(visible bool) {
// if (visible) {
// fmt.Println("Width:", win.Int("width"))
// }
// })
//
// Information about the methods, properties, and signals that are available for QML
// objects may be obtained in the Qt documentation. As a reference, the "visibleChanged"
// signal and the "width" property used in the example above are described at:
//
// http://qt-project.org/doc/qt-5.0/qtgui/qwindow.html
//
// When in doubt about what type is being manipulated, the Object.TypeName method
// provides the type name of the underlying value.
//
//
// Publishing Go values to QML
//
// The simplest way of making a Go value available to QML code is setting it
// as a variable of the engine's root context, as in:
//
// context := engine.Context()
// context.SetVar("person", &Person{Name: "Ale"})
//
// This logic would enable the following QML code to successfully run:
//
// import QtQuick 2.0
// Item {
// Component.onCompleted: console.log("Name is", person.name)
// }
//
//
// Publishing Go types to QML
//
// While registering an individual Go value as described above is a quick way to get
// started, it is also fairly limited. For more flexibility, a Go type may be
// registered so that QML code can natively create new instances in an arbitrary
// position of the structure. This may be achieved via the RegisterType function, as
// the following example demonstrates:
//
// qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{
// Init: func(p *Person, obj qml.Object) { p.Name = "<none>" },
// }})
//
// With this logic in place, QML code can create new instances of Person by itself:
//
// import QtQuick 2.0
// import GoExtensions 1.0
// Item{
// Person {
// id: person
// name: "Ale"
// }
// Component.onCompleted: console.log("Name is", person.name)
// }
//
//
// Lowercasing of names
//
// Independently from the mechanism used to publish a Go value to QML code, its methods
// and fields are available to QML logic as methods and properties of the
// respective QML object representing it. As required by QML, though, the Go
// method and field names are lowercased according to the following scheme when
// being accesed from QML:
//
// value.Name => value.name
// value.UPPERName => value.upperName
// value.UPPER => value.upper
//
//
// Setters and getters
//
// While QML code can directly read and write exported fields of Go values, as described
// above, a Go type can also intercept writes to specific fields by declaring a setter
// method according to common Go conventions. This is often useful for updating the
// internal state or the visible content of a Go-defined type.
//
// For example:
//
// type Person struct {
// Name string
// }
//
// func (p *Person) SetName(name string) {
// fmt.Println("Old name is", p.Name)
// p.Name = name
// fmt.Println("New name is", p.Name)
// }
//
// In the example above, whenever QML code attempts to update the Person.Name field
// via any means (direct assignment, object declarations, etc) the SetName method
// is invoked with the provided value instead.
//
// A setter method may also be used in conjunction with a getter method rather
// than a real type field. A method is only considered a getter in the presence
// of the respective setter, and according to common Go conventions it must not
// have the Get prefix.
//
// Inside QML logic, the getter and setter pair is seen as a single object property.
//
//
// Painting
//
// Custom types implemented in Go may have displayable content by defining
// a Paint method such as:
//
// func (p *Person) Paint(painter *qml.Painter) {
// // ... OpenGL calls with the gopkg.in/qml.v1/gl/<VERSION> package ...
// }
//
// A simple example is available at:
//
// https://github.com/go-qml/qml/tree/v1/examples/painting
//
//
// Packing resources into the Go qml binary
//
// Resource files (qml code, images, etc) may be packed into the Go qml application
// binary to simplify its handling and distribution. This is done with the genqrc tool:
//
// http://gopkg.in/qml.v1/cmd/genqrc#usage
//
// The following blog post provides more details:
//
// http://blog.labix.org/2014/09/26/packing-resources-into-go-qml-binaries
//
package qml
5 changes: 0 additions & 5 deletions error.go

This file was deleted.

5 changes: 5 additions & 0 deletions examples/controls/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
basiclayouts/basiclayouts
gallery/gallery
splitview/splitview
tableview/tableview
touch/touch
8 changes: 8 additions & 0 deletions examples/controls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
These examples were ported from [qtquickcontrols](git@gitorious.org:qt/qtquickcontrols.git).

Only the basic ones were ported, in order to demonstrate how easy it is to create a full-fledged UI with Go and QML.

There were a few more, but they that had native modules and those were omitted due to laziness.

In order to run them you might need some extra Qt5 plugins. On Ubuntu those can be installed using this command:
sudo apt-get install qtdeclarative5-controls-plugin qtdeclarative5-xmllistmodel-plugin
29 changes: 29 additions & 0 deletions examples/controls/basiclayouts/basiclayouts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"fmt"
"gopkg.in/qml.v1"
"os"
)

func main() {
if err := qml.Run(run); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}

func run() error {
engine := qml.NewEngine()

controls, err := engine.LoadFile("main.qml")
if err != nil {
return err
}

window := controls.CreateWindow(nil)

window.Show()
window.Wait()
return nil
}
116 changes: 116 additions & 0 deletions examples/controls/basiclayouts/main.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/





import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0

ApplicationWindow {
visible: true
title: "Basic layouts"
property int margin: 11
width: mainLayout.implicitWidth + 2 * margin
height: mainLayout.implicitHeight + 2 * margin
minimumWidth: mainLayout.Layout.minimumWidth + 2 * margin
minimumHeight: mainLayout.Layout.minimumHeight + 2 * margin

ColumnLayout {
id: mainLayout
anchors.fill: parent
anchors.margins: margin
GroupBox {
id: rowBox
title: "Row layout"
Layout.fillWidth: true

RowLayout {
id: rowLayout
anchors.fill: parent
TextField {
placeholderText: "This wants to grow horizontally"
Layout.fillWidth: true
}
Button {
text: "Button"
}
}
}

GroupBox {
id: gridBox
title: "Grid layout"
Layout.fillWidth: true

GridLayout {
id: gridLayout
rows: 3
flow: GridLayout.TopToBottom
anchors.fill: parent

Label { text: "Line 1" }
Label { text: "Line 2" }
Label { text: "Line 3" }

TextField { }
TextField { }
TextField { }

TextArea {
text: "This widget spans over three rows in the GridLayout.\n"
+ "All items in the GridLayout are implicitly positioned from top to bottom."
Layout.rowSpan: 3
Layout.fillHeight: true
Layout.fillWidth: true
}
}
}
TextArea {
id: t3
text: "This fills the whole cell"
Layout.minimumHeight: 30
Layout.fillHeight: true
Layout.fillWidth: true
}
}
}
48 changes: 48 additions & 0 deletions examples/controls/gallery/content/AboutDialog.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Dialogs 1.1

MessageDialog {
icon: StandardIcon.Information
text: "QtQuick.Controls gallery example"
detailedText: "This example demonstrates most of the available Qt Quick Controls."
title: "About Gallery"
}
122 changes: 122 additions & 0 deletions examples/controls/gallery/content/ChildWindow.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/





import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.1

Window {
id: window1

width: 400
height: 400

title: "child window"
flags: Qt.Dialog

Rectangle {
color: syspal.window
anchors.fill: parent

Label {
id: dimensionsText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: parent.width
horizontalAlignment: Text.AlignHCenter
}

Label {
id: availableDimensionsText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: dimensionsText.bottom
width: parent.width
horizontalAlignment: Text.AlignHCenter
}

Label {
id: closeText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: availableDimensionsText.bottom
text: "This is a new Window, press the\nbutton below to close it again."
}
Button {
anchors.horizontalCenter: closeText.horizontalCenter
anchors.top: closeText.bottom
id: closeWindowButton
text:"Close"
width: 98
tooltip:"Press me, to close this window again"
onClicked: window1.visible = false
}
Button {
anchors.horizontalCenter: closeText.horizontalCenter
anchors.top: closeWindowButton.bottom
id: maximizeWindowButton
text:"Maximize"
width: 98
tooltip:"Press me, to maximize this window again"
onClicked: window1.visibility = Window.Maximized;
}
Button {
anchors.horizontalCenter: closeText.horizontalCenter
anchors.top: maximizeWindowButton.bottom
id: normalizeWindowButton
text:"Normalize"
width: 98
tooltip:"Press me, to normalize this window again"
onClicked: window1.visibility = Window.Windowed;
}
Button {
anchors.horizontalCenter: closeText.horizontalCenter
anchors.top: normalizeWindowButton.bottom
id: minimizeWindowButton
text:"Minimize"
width: 98
tooltip:"Press me, to minimize this window again"
onClicked: window1.visibility = Window.Minimized;
}
}
}

Loading