Compare commits

...

52 Commits

Author SHA1 Message Date
09149e0566
Merge pull request #225 from rcalixte/private_signals
Add private signals
2025-05-25 15:07:29 +12:00
Rick Calixte
e6b61cd339
lcdclock6: Update with private signal 2025-05-24 15:26:54 -04:00
Rick Calixte
93ce2040d8
qt: Rebuild (Add private signals) 2025-05-24 15:25:56 -04:00
Rick Calixte
3621373888
emitgo.go: Add projection of private signals 2025-05-24 15:24:11 -04:00
Rick Calixte
2019f402a0
emitcabi.go: Add projection of private signals 2025-05-24 15:17:28 -04:00
Rick Calixte
0e6905c39e
clang2il.go: Populate private signals 2025-05-23 21:59:49 -04:00
Rick Calixte
82826d7a21
intermediate.go: Add PrivateSignals field 2025-05-23 21:54:26 -04:00
5ac6083a3d
Merge pull request #224 from rcalixte/add_lcdclock6
lcdclock6: Add Qt 6 lcdclock example
2025-05-22 17:43:18 +12:00
Rick Calixte
fc7a764931
lcdclock6: Add Qt 6 lcdclock example 2025-05-21 18:36:40 -04:00
8aedac421d
Merge pull request #221 from mappu/miqt-uic-morefeatures
miqt-uic: Support nested layouts, support QIcon theme images
2025-05-10 17:12:43 +12:00
d7c54b4574 miqt-uic: support nested layouts 2025-05-10 13:11:18 +12:00
b3b914ede8 miqt-uic: support icon themes 2025-05-10 13:11:18 +12:00
2fc549206b
Merge pull request #220 from mrex/miqt-docker-podman-support
replace "localhost/" prefix when searching for images to support Podman
2025-05-10 12:00:11 +12:00
mrex
32875ef65f
replace "localhost/" prefix when searching for images to support Podman 2025-05-09 22:08:46 +02:00
7a6bac85b4
Merge pull request #213 from mappu/miqt-uic-updates
miqt-uic: Fix SizePolicy, fix SetObjectName, fix nested QMenus
2025-05-04 14:49:24 +12:00
66aeefc77a miqt-uic: support nested QMenu 2025-05-04 14:16:50 +12:00
1498f05fa5 miqt-uic: fix setObjectName for qt6 2025-05-04 14:16:39 +12:00
d802e345fe miqt-uic: support SizePolicy 2025-05-04 14:15:58 +12:00
9d4cabc099
Merge pull request #208 from mappu/miqt-docker-cmd
Add miqt-docker helper command, add one-command Android builds
2025-05-01 22:41:32 +12:00
9fc6ff9c25 github/ci: remove GOCACHE steps that keep loading obsolete caches 2025-05-01 22:05:01 +12:00
2c44746902 github/ci: simplify steps using miqt-docker, reinstate android-qt6 test 2025-05-01 22:05:01 +12:00
95434b416e doc/README: the qt5-6 is not a module, so you can't use go mod edit 2025-05-01 22:05:01 +12:00
b55dd5e9c1 doc/README: add note re Android QFileDialog behaviour 2025-05-01 22:05:01 +12:00
9747acc50b doc/README: group into sections 2025-05-01 22:05:01 +12:00
a01b7391ba doc/README: use context-free docker builds, remove dockerignore 2025-05-01 22:05:01 +12:00
901d2e0aa0 doc/README: add miqt-docker instructions 2025-05-01 22:04:58 +12:00
a82e43585d miqt-docker: update README, simplify usage output 2025-05-01 22:02:19 +12:00
f0ce7984ce miqt-docker: windows compatibility 2025-05-01 22:01:20 +12:00
6d176bc410 miqt-docker: update usage text and README 2025-05-01 22:01:20 +12:00
66e0973242 examples/android: merge with helloworld[6] as they are now identical 2025-05-01 22:01:14 +12:00
a4a4074948 android: major rework for all-in-one android support 2025-04-29 22:48:09 +12:00
687579d76f miqt-docker: set $HOME to /tmp inside container 2025-04-29 22:47:21 +12:00
6984b83aea miqt-docker: add -minify-build task 2025-04-29 22:46:50 +12:00
34e7429fe1 miqt-docker: add -windows-build task 2025-04-29 22:46:36 +12:00
c6ff8e0533 miqt-docker: support 'native', add -build task, conditional isatty 2025-04-29 22:46:16 +12:00
b2536be8d5 miqt-docker: change wildcard from * to - to avoid shell interpretation 2025-04-29 22:43:13 +12:00
d075984e77 miqt-docker: auto cleanup old container versions 2025-04-29 22:42:48 +12:00
ded180f77b Makefile: simplify to use miqt-docker 2025-04-26 18:52:30 +12:00
b3d5f541f0 miqt-docker: conditionally use -it if parent was a tty 2025-04-26 18:52:30 +12:00
69190ece2c miqt-docker: use -it to ensure ^C signals make it through 2025-04-26 17:47:34 +12:00
8328ca7e12 gitignore: remove some obsolete local excludes 2025-04-26 17:33:11 +12:00
c7b7e8fdfb pkg-config: move into docs/, delete the example files 2025-04-26 17:32:57 +12:00
7dd11c6d9b docker/genbindings: inline pkg-config defintions for context-free builds 2025-04-26 17:23:27 +12:00
e7892c780e miqt-docker: create local GOCACHE/GOMODCACHE if they do not yet exist 2025-04-26 17:22:53 +12:00
540b306715 miqt-docker: initial commit 2025-04-26 12:06:46 +12:00
da7c82a719
Merge pull request #205 from rcalixte/qt_pdf
Add Qt PDF
2025-04-24 21:51:43 +12:00
Rick Calixte
4e841e0053
README: Add Qt PDF packages 2025-04-20 14:15:48 -04:00
Rick Calixte
72ad16086a
genbindings.Dockerfile: Add Qt PDF packages 2025-04-20 13:25:26 -04:00
Rick Calixte
fdb15300e8
pdf: Add Qt PDF examples 2025-04-20 13:15:14 -04:00
Rick Calixte
c43c65ee2a
.gitignore: Add Qt PDF Examples 2025-04-20 13:12:13 -04:00
Rick Calixte
5a39358a1e
qt: Rebuild (Add Qt PDF) 2025-04-20 13:11:21 -04:00
Rick Calixte
4cba7b0c99
config-libraries.go: Add Qt PDF
* Closes #200
2025-04-20 13:10:39 -04:00
191 changed files with 39007 additions and 676 deletions

View File

@ -1,33 +0,0 @@
cmd/genbindings/cachedir
*.exe
cmd/handbindings/handbindings
cmd/handbindings/bindings_test/direct
cmd/handbindings/bindings_test/testapp
cmd/genbindings/genbindings
cmd/miqt-uic/miqt-uic
cmd/miqt-rcc/miqt-rcc
examples/goroutine6/goroutine6
examples/helloworld/helloworld
examples/helloworld6/helloworld6
examples/mdoutliner/mdoutliner
examples/mdoutliner6/mdoutliner6
examples/windowsmanifest/windowsmanifest
examples/uidesigner/uidesigner
examples/trivialwizard6/trivialwizard6
examples/subclass/subclass
examples/modelview/modelview
examples/modelview_color6/modelview_color6
examples/libraries/extras-scintillaedit/extras-scintillaedit
examples/libraries/qt-multimedia/qt-multimedia
examples/libraries/qt-network/qt-network
examples/libraries/qt-printsupport/qt-printsupport
examples/libraries/qt-script/qt-script
examples/libraries/qt-svg/qt-svg
examples/libraries/qt-webengine/qt-webengine
examples/libraries/qt-webkit/qt-webkit
examples/libraries/qt6-multimedia/qt6-multimedia
examples/libraries/qt6-webengine/qt6-webengine
examples/libraries/restricted-extras-qscintilla/restricted-extras-qscintilla

View File

@ -14,6 +14,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
# WARNING: This loads the cache but does not commit back any new changes to
# it unless the cache is invalidated in GitHub
# It will help to do that every time a new Qt library is added
- name: Cache clang ASTs
uses: actions/cache@v4
with:
@ -33,14 +36,12 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: linux64-buildall-gocache
# This uses the `genbindings` container in miqt-docker
- name: Rebuild all libraries and examples
run: make build-all
- name: Run marshalling test suite
run: cmd/miqt-docker/miqt-docker genbindings /bin/bash -c 'cd examples/marshalling && env QT_QPA_PLATFORM=offscreen go test -v'
miqt_linux64_qt5:
runs-on: ubuntu-24.04
@ -49,18 +50,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Linux64 docker build
run: docker build -t miqt/linux64:qt5 -f docker/linux64-go1.19-qt5.15-dynamic.Dockerfile .
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: linux64-qt5-gocache
- name: Linux64 bindings compile and test
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/linux64:qt5 /bin/bash -c 'cd qt && go build && cd ../examples/marshalling && env QT_QPA_PLATFORM=offscreen go test -v'
- name: Linux64 bindings compile
run: |
make cmd/miqt-docker/miqt-docker
cd qt && ../cmd/miqt-docker/miqt-docker linux64-go1.19-qt5.15-dynamic go build
miqt_linux64_qt6_4:
runs-on: ubuntu-24.04
@ -68,17 +62,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Linux64 docker build
run: docker build -t miqt/linux64:qt64 -f docker/linux64-go1.19-qt6.4-dynamic.Dockerfile .
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: linux64-qt64-gocache
- name: Linux64 bindings compile
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/linux64:qt64 /bin/bash -c 'cd qt6 && go build'
run: |
make cmd/miqt-docker/miqt-docker
cd qt6 && ../cmd/miqt-docker/miqt-docker linux64-go1.19-qt6.4-dynamic go build
miqt_linux64_qt6_8:
runs-on: ubuntu-24.04
@ -86,18 +73,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Linux64 docker build
run: docker build -t miqt/linux64:qt68 -f docker/linux64-go1.23-qt6.8-dynamic.Dockerfile .
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: linux64-qt68-gocache
- name: Linux64 bindings compile
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/linux64:qt68 /bin/bash -c 'cd qt6 && go build'
run: |
make cmd/miqt-docker/miqt-docker
cd qt6 && ../cmd/miqt-docker/miqt-docker linux64-go1.23-qt6.8-dynamic go build
miqt_win32_qt5:
runs-on: ubuntu-24.04
@ -105,18 +85,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: win32-qt5-gocache
- name: Win32 docker build
run: docker build -t miqt/win32:qt5 -f docker/win32-cross-go1.23-qt5.15-static.Dockerfile .
- name: Win32 bindings compile
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/win32:qt5 /bin/bash -c 'cd qt && go build && cd ../examples/helloworld && go build'
run: |
make cmd/miqt-docker/miqt-docker
cmd/miqt-docker/miqt-docker win32-cross-go1.23-qt5.15-static /bin/bash -c 'cd qt && go build && cd ../examples/helloworld && go build'
miqt_win64_qt5:
runs-on: ubuntu-24.04
@ -124,18 +97,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: win64-qt5-gocache
- name: Win64 docker build
run: docker build -t miqt/win64:qt5 -f docker/win64-cross-go1.23-qt5.15-static.Dockerfile .
- name: Win64 bindings compile
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/win64:qt5 /bin/bash -c 'cd qt && go build && cd ../examples/helloworld && go build'
run: |
make cmd/miqt-docker/miqt-docker
cmd/miqt-docker/miqt-docker win64-cross-go1.23-qt5.15-static /bin/bash -c 'cd qt && go build && cd ../examples/helloworld && go build'
miqt_win64_qt68:
runs-on: ubuntu-24.04
@ -144,17 +110,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: win64-qt68-gocache
- name: Win64 docker build
run: docker build -t miqt/win64:qt68 -f docker/win64-cross-go1.23-qt6.8-dynamic.Dockerfile .
- name: Win64 bindings compile
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src miqt/win64:qt68 /bin/bash -c 'cd qt6 && go build && cd ../examples/helloworld6 && go build'
run: |
make cmd/miqt-docker/miqt-docker
cmd/miqt-docker/miqt-docker win64-cross-go1.23-qt6.8-dynamic /bin/bash -c 'cd qt6 && go build && cd ../examples/helloworld6 && go build'
miqt_android_qt5:
runs-on: ubuntu-24.04
@ -162,58 +121,24 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Android compile
run: |
make cmd/miqt-docker/miqt-docker
cd examples/helloworld
../../cmd/miqt-docker/miqt-docker android-armv8a-go1.23-qt5.15-dynamic -android-build
test -f helloworld.apk
- name: Android armv8a docker build
run: docker build -t miqt/android:qt5 -f docker/android-armv8a-go1.23-qt5.15-dynamic.Dockerfile .
miqt_android_qt6:
runs-on: ubuntu-24.04
- name: Cache GOCACHE
uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: android-qt5-armv8a-gocache
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Android compile app as c-shared my_go_app.so
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src/examples/android miqt/android:qt5 go build -buildmode c-shared -ldflags "-s -w -extldflags -Wl,-soname,my_go_app.so" -o android-build/libs/arm64-v8a/my_go_app.so
- name: Android generate libRealAppName.so linking stub
run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src/examples/android miqt/android:qt5 android-stub-gen.sh my_go_app.so AndroidMain android-build/libs/arm64-v8a/libRealAppName_arm64-v8a.so
- name: Android generate json packaging metadata
run: docker run --rm -v $(pwd):/src -w /src/examples/android miqt/android:qt5 android-mktemplate.sh RealAppName deployment-settings.json
- name: Android build APK package
run: docker run --rm -v $(pwd):/src -w /src/examples/android miqt/android:qt5 androiddeployqt --input ./deployment-settings.json --output ./android-build/
- name: Verify that package exists
run: test -f examples/android/android-build/build/outputs/apk/debug/android-build-debug.apk
# miqt_android_qt6:
# runs-on: ubuntu-24.04
#
# steps:
# - name: Checkout
# uses: actions/checkout@v4
#
# - name: Android armv8a docker build
# run: docker build -t miqt/android:qt6 -f docker/android-armv8a-go1.23-qt6.6-dynamic.Dockerfile .
#
# - name: Cache GOCACHE
# uses: actions/cache@v4
# with:
# path: ~/.cache/go-build
# key: android-qt6-armv8a-gocache
#
# - name: Android compile app as c-shared my_go_app.so
# run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src/examples/android6 miqt/android:qt6 go build -buildmode c-shared -ldflags "-s -w -extldflags -Wl,-soname,my_go_app.so" -o android-build/libs/arm64-v8a/my_go_app.so
#
# - name: Android generate libRealAppName.so linking stub
# run: docker run -v ~/.cache/go-build:/root/.cache/go-build -v $PWD:/src -w /src/examples/android6 miqt/android:qt6 android-stub-gen.sh my_go_app.so AndroidMain android-build/libs/arm64-v8a/libRealAppName_arm64-v8a.so --qt6
#
# - name: Android generate json packaging metadata
# run: docker run --rm -v $(pwd):/src -w /src/examples/android6 miqt/android:qt6 android-mktemplate.sh RealAppName deployment-settings.json
#
# - name: Android build APK package
# run: docker run --rm -v $(pwd):/src -w /src/examples/android6 miqt/android:qt6 androiddeployqt --input ./deployment-settings.json --output ./android-build/
#
# - name: Verify that package exists
# run: test -f examples/android6/android-build/build/outputs/apk/debug/android-build-debug.apk
- name: Android compile
run: |
make cmd/miqt-docker/miqt-docker
cd examples/helloworld6
../../cmd/miqt-docker/miqt-docker android-armv8a-go1.23-qt6.6-dynamic -android-build
test -f helloworld6.apk

13
.gitignore vendored
View File

@ -1,15 +1,6 @@
# cache files for genbindings
cmd/genbindings/cachedir/
# docker files
container-build-cache/
# local genbindings configuration
cmd/genbindings/genbindings.local*
# local pkg-config configuration
pkg-config/*.pc
# binaries
*.exe
@ -17,6 +8,7 @@ cmd/handbindings/handbindings
cmd/handbindings/bindings_test/direct
cmd/handbindings/bindings_test/testapp
cmd/genbindings/genbindings
cmd/miqt-docker/miqt-docker
cmd/miqt-uic/miqt-uic
cmd/miqt-rcc/miqt-rcc
@ -24,6 +16,7 @@ examples/goroutine6/goroutine6
examples/helloqml6/helloqml6
examples/helloworld/helloworld
examples/helloworld6/helloworld6
examples/lcdclock6/lcdclock6
examples/mdoutliner/mdoutliner
examples/mdoutliner6/mdoutliner6
examples/windowsmanifest/windowsmanifest
@ -35,6 +28,7 @@ examples/modelview_color6/modelview_color6
examples/libraries/extras-scintillaedit/extras-scintillaedit
examples/libraries/qt-multimedia/qt-multimedia
examples/libraries/qt-network/qt-network
examples/libraries/qt-pdf/qt-pdf
examples/libraries/qt-printsupport/qt-printsupport
examples/libraries/qt-script/qt-script
examples/libraries/qt-svg/qt-svg
@ -43,6 +37,7 @@ examples/libraries/qt-webkit/qt-webkit
examples/libraries/qt6-multimedia/qt6-multimedia
examples/libraries/qt6-network/qt6-network
examples/libraries/qt6-network-sctp/qt6-network-sctp
examples/libraries/qt6-pdf/qt6-pdf
examples/libraries/qt6-webengine/qt6-webengine
examples/libraries/restricted-extras-charts6/restricted-extras-charts6
examples/libraries/restricted-extras-qscintilla/restricted-extras-qscintilla

View File

@ -1,40 +1,23 @@
BUILDSTAMPS := docker/genbindings.docker-buildstamp
DOCKER := docker
SHELL := /bin/bash
# DOCKEREXEC runs the target command in the `genbindings` docker container.
# It mounts in the current GOCACHE and GOMODCACHE.
DOCKEREXEC = mkdir -p "$$(go env GOCACHE)" && \
mkdir -p "$$(go env GOMODCACHE)" && \
$(DOCKER) run \
--user "$$(id -u):$$(id -g)" \
-v "$$(go env GOCACHE):/.cache/go-build" \
-v "$$(go env GOMODCACHE):/go/pkg/mod" \
-v "$$PWD:/src" \
-w /src \
miqt/genbindings:latest \
/bin/bash -c
GO := go
.PHONY: all
all: genbindings
docker/genbindings.docker-buildstamp: docker/genbindings.Dockerfile
$(DOCKER) build -t miqt/genbindings:latest -f docker/genbindings.Dockerfile .
touch $@
.PHONY: clean
clean:
$(DOCKER) image rm -f miqt/genbindings:latest
rm -f $(BUILDSTAMPS)
cmd/miqt-docker/miqt-docker: go.mod cmd/miqt-docker/*.go docker/*.Dockerfile
$(GO) build -o cmd/miqt-docker/miqt-docker ./cmd/miqt-docker
.PHONY: clean-cache
clean-cache:
rm -f cmd/genbindings/cachedir/*.json
cmd/genbindings/genbindings: go.mod cmd/genbindings/*.go
$(GO) build -o cmd/genbindings/genbindings ./cmd/genbindings
.PHONY: genbindings
genbindings: $(BUILDSTAMPS)
$(DOCKEREXEC) 'cd cmd/genbindings && go build && ./genbindings'
genbindings: cmd/miqt-docker/miqt-docker cmd/genbindings/genbindings
cd cmd/genbindings && ../miqt-docker/miqt-docker genbindings ./genbindings
.PHONY: build-all
build-all: $(BUILDSTAMPS)
$(DOCKEREXEC) 'go build ./...'
build-all: cmd/miqt-docker/miqt-docker
./cmd/miqt-docker/miqt-docker genbindings go build ./...

View File

@ -53,6 +53,8 @@ Make sure to compile with `go build -ldflags "-s -w"`. This reduces the `hellowo
Then, it's possible to reduce the size further with `upx --best` to 2MB or `upx --lzma` to 1.4MB.
You can also try `miqt-docker native -minify-build` to use aggressive `CFLAGS`.
### Q2. Can I release a proprietary, commercial app with this binding?
Yes. You must also meet your Qt license obligations: either use Qt dynamically-linked dll/so/dylib files under the LGPL, or, purchase a Qt commercial license for static linking.
@ -63,7 +65,7 @@ The first time MIQT is used, your `go build` would take [about 10 minutes](https
If you are compiling your app within a Dockerfile, you could cache the build step by running `go install github.com/mappu/miqt/qt`.
If you are compiling your app with a one-shot `docker run` command, the compile speed can be improved if you also bind-mount the Docker container's `GOCACHE` directory: `-v $(pwd)/container-build-cache:/root/.cache/go-build`
If you are compiling your app with a one-shot `docker run` command, the compile speed can be improved if you also bind-mount the Docker container's `GOCACHE` directory: `-v $(pwd)/container-build-cache:/root/.cache/go-build`. The `miqt-docker` helper app does this automatically.
See also [issue #8](https://github.com/mappu/miqt/issues/8).
@ -84,27 +86,29 @@ MIQT is a clean-room binding that does not use any code from other Qt bindings.
Most functions are implemented 1:1. [The Qt documentation](https://doc.qt.io/qt-5/classes.html) should be used.
The `QByteArray`, `QString`, `QList<T>`, `QVector<T>`, `QMap<K,V>`, `QHash<K,V>` types are projected as plain Go `[]byte`, `string`, `[]T`, and `map[K]V`. Therefore, you can't call any of the Qt type's methods, you must use some Go equivalent method instead.
Container types:
- The `QByteArray`, `QString`, `QList<T>`, `QVector<T>`, `QMap<K,V>`, `QHash<K,V>` types are projected as plain Go `[]byte`, `string`, `[]T`, and `map[K]V`. Therefore, you can't call any of the Qt type's methods, you must use some Go equivalent method instead.
- Go strings are internally converted to QString using `QString::fromUtf8`. Therefore, the Go string must be UTF-8 to avoid [mojibake](https://en.wikipedia.org/wiki/Mojibake). If the Go string contains binary data, the conversion would corrupt such bytes into U+FFFD (<28>). On return to Go space, this becomes `\xEF\xBF\xBD`.
- The iteration order of a Qt `QMap`/`QHash` will differ from the Go map iteration order. `QMap` is iterated by key order, but Go maps and `QHash` iterate in an undefined internal order.
- The iteration order of a Qt QMap/QHash will differ from the Go map iteration order. QMap is iterated by key order, but Go maps and QHash iterate in an undefined internal order.
Where Qt returns a C++ object by value (e.g. `QSize`), the binding may have moved it to the heap, and in Go this may be represented as a pointer type. In such cases, a Go finalizer is added to automatically delete the heap object. This means code using MIQT can look basically similar to the Qt C++ equivalent code.
The `connect(sourceObject, sourceSignal, targetObject, targetSlot)` is projected as `targetObject.onSourceSignal(func()...)`.
Memory management:
- Where Qt returns a C++ object by value (e.g. `QSize`), the binding may have moved it to the heap, and in Go this may be represented as a pointer type. In such cases, a Go finalizer is added to automatically delete the heap object. This means code using MIQT can look basically similar to the Qt C++ equivalent code.
Events and signals:
- The `connect(sourceObject, sourceSignal, targetObject, targetSlot)` is projected as `targetObject.onSourceSignal(func()...)`.
- You can also override virtual methods like PaintEvent in the same way. Your callback `func()` receives `super()` as a first argument that can be used to call the base class implementation.
Qt class inherited types are projected as a Go embedded struct. For example, to pass a `var myLabel *qt.QLabel` to a function taking only the `*qt.QWidget` base class, write `myLabel.QWidget`.
Class pointers:
- Qt class inherited types are projected as a Go embedded struct. For example, to pass a `var myLabel *qt.QLabel` to a function taking only the `*qt.QWidget` base class, write `myLabel.QWidget`.
- When a Qt subclass adds a method overload (e.g. `QMenu::addAction(QString)` vs `QWidget::addAction(QAction*)`), the base class version is shadowed and can only be called via `myQMenu.QWidget.AddAction(QAction*)`.
- A MIQT pointer points to a Go struct, not to the raw C++ Qt widget class. Therefore `QTabWidget.CurrentWidget() == MyTab` will never compare equal because `CurrentWidget()` created a new Go struct wrapping the same C++ pointer. You can compare `QTabWidget.CurrentIndex()`, or, you can use: `QTabWidget.CurrentWidget().UnsafePointer() == MyTab.UnsafePointer()`.
The Go runtime migrates goroutines between OS threads, but Qt expects fixed OS threads to be used for each QObject. When you first call `qt.NewQApplication` in MIQT, that will be considered the [Qt main thread](https://doc.qt.io/qt-6/thread-basics.html#gui-thread-and-worker-thread) and will automatically signal the Go runtime to bind to a fixed OS thread using `runtime.LockOSThread()`.
Multithreading:
- The Go runtime migrates goroutines between OS threads, but Qt expects fixed OS threads to be used for each QObject. When you first call `qt.NewQApplication` in MIQT, that will be considered the [Qt main thread](https://doc.qt.io/qt-6/thread-basics.html#gui-thread-and-worker-thread) and will automatically signal the Go runtime to bind to a fixed OS thread using `runtime.LockOSThread()`.
- When accessing Qt objects from inside another goroutine, it's safest to use `(qt6/mainthread).Wait()` or `Start()` to access the Qt objects from Qt's main thread.
- When accessing Qt objects from inside another goroutine, it's safest to use `(qt6/mainthread).Wait()` to access the Qt objects from Qt's main thread.
Android:
- A `QFileDialog` may return a filepath of the form `content://...`. Such paths can be opened with `qt.QFile` but not with Go `os.Open()`; you can pass the handle to Go using `os.NewFile(QFile.Handle(), "name")`.
Some C++ idioms that were difficult to project were omitted from the binding. But, this can be improved in the future.
@ -118,20 +122,22 @@ MIQT has a custom implementation of Qt `uic` and `rcc` tools, to allow using [Qt
MIQT uses `pkg-config` to find all used Qt libraries. Every Qt library should have a definition file in `.pc` format, which provides CGO with the necessary `CXXFLAGS`/`LDFLAGS`. Your Qt development environment already included the necessary `.pc` definition files.
You can use the `PKG_CONFIG_PATH` environment variable to override where CGO looks for `.pc` files. [Read more »](pkg-config/README.md)
You can use the `PKG_CONFIG_PATH` environment variable to override where CGO looks for `.pc` files. [Read more »](doc/pkg-config.md)
### Q8. How can I upgrade a MIQT app from Qt 5 to Qt 6?
The import path changes from `github.com/mappu/miqt/qt` to `github.com/mappu/miqt/qt6`, but most basic classes are the same.
You can replace the import path in two ways:
1. Add a go.mod directive: Run `go mod edit -replace github.com/mappu/miqt/qt=github.com/mappu/miqt/qt6`
2. Or, update all imports: Run `find . -type f -name .go -exec sed -i 's_"github.com/mappu/miqt/qt"_qt "github.com/mappu/miqt/qt6"_' {} \;`
You can update all imports by running `find . -type f -name .go -exec sed -i 's_"github.com/mappu/miqt/qt"_qt "github.com/mappu/miqt/qt6"_' {} \;`
### Q9. How can I add bindings for another Qt library?
Fork this repository and add your library to the `genbindings/config-libraries` file. [Read more »](cmd/genbindings/README.md)
### Q10. Is there an easy build tool?
You can use the ordinary `go get` and `go build` commands. To help with cross-compilation, you can use the optional `miqt-docker` tool. [Read more »](cmd/miqt-docker/README.md)
## Building
### Linux (native)
@ -149,7 +155,7 @@ For dynamic linking, with the system Qt (Qt 5):
apt install qtbase5-dev build-essential golang-go
# Debian / Ubuntu (Full)
apt install qtbase5-dev libqscintilla2-qt5-dev libqt5svg5-dev libqt5webchannel5-dev libqt5webkit5-dev qtbase5-private-dev qtmultimedia5-dev qtwebengine5-dev qtwebengine5-private-dev build-essential golang-go
apt install qtbase5-dev libqscintilla2-qt5-dev libqt5svg5-dev libqt5webchannel5-dev libqt5webkit5-dev qtbase5-private-dev qtmultimedia5-dev qtpdf5-dev qtwebengine5-dev qtwebengine5-private-dev build-essential golang-go
```
For dynamic linking, with the system Qt (Qt 6):
@ -159,10 +165,10 @@ For dynamic linking, with the system Qt (Qt 6):
apt install qt6-base-dev build-essential golang-go
# Debian / Ubuntu (Full)
apt install qt6-base-dev libqscintilla2-qt6-dev qt6-base-private-dev qt6-charts-dev qt6-multimedia-dev qt6-svg-dev qt6-webchannel-dev qt6-webengine-dev qt6-declarative-dev qml6-module-qtquick-{controls,shapes,layouts,templates,window} build-essential golang-go
apt install qt6-base-dev libqscintilla2-qt6-dev qt6-base-private-dev qt6-charts-dev qt6-multimedia-dev qt6-pdf-dev qt6-svg-dev qt6-webchannel-dev qt6-webengine-dev qt6-declarative-dev qml6-module-qtquick-{controls,shapes,layouts,templates,window} build-essential golang-go
# Fedora
dnf install qt6-qtbase-devel qscintilla-qt6-devel qt6-qtcharts-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qtwebchannel-devel qt6-qtwebengine-devel qt6-qtdeclarative-devel golang
dnf install qt6-qtbase-devel qscintilla-qt6-devel qt6-qtcharts-devel qt6-qtmultimedia-devel qt6-qtpdf-devel qt6-qtsvg-devel qt6-qtwebchannel-devel qt6-qtwebengine-devel qt6-qtdeclarative-devel golang
# Manjaro
pamac install qt6-base qscintilla-qt6 qt6-charts qt6-multimedia qt6-svg qt6-webchannel qt6-webengine qt6-declarative go
@ -180,6 +186,13 @@ pacman -S pkg-config gcc go qt6-base qscintilla-qt6 qt6-charts qt6-multimedia qt
go build -ldflags '-s -w'
```
### Windows (Docker with miqt-docker)
```bash
go install github.com/mappu/miqt/cmd/miqt-docker
miqt-docker win64-qt6-static -windows-build # or -qt5- or -static
```
### Windows (native)
*Tested with Fsu0413 Qt 5.15 / Clang 18.1 native compilation*
@ -236,14 +249,14 @@ Static linking is also available by installing the `mingw-w64-ucrt-x86_64-qt5-st
For static linking:
1. Build the necessary docker container for cross-compilation:
- `docker build -t miqt/win64-cross:latest -f docker/win64-cross-go1.23-qt5.15-static.Dockerfile .`
- In the `docker/` directory: docker build -t miqt/win64-cross:latest -f win64-cross-go1.23-qt5.15-static.Dockerfile .`
2. Build your application:
- `docker run --rm -v $(pwd):/src -w /src miqt/win64-cross:latest go build --tags=windowsqtstatic -ldflags '-s -w -H windowsgui'`
For dynamic linking:
1. Build the necessary docker container for cross-compilation:
- `docker build -t miqt/win64-dynamic:latest -f docker/win64-cross-go1.23-qt5.15-dynamic.Dockerfile .`
- In the `docker/` directory: `docker build -t miqt/win64-dynamic:latest -f win64-cross-go1.23-qt5.15-dynamic.Dockerfile .`
2. Build your application:
- `docker run --rm -v $(pwd):/src -w /src miqt/win64-dynamic:latest go build -ldflags '-s -w -H windowsgui'`
3. Copy necessary Qt LGPL libraries and plugin files.
@ -260,7 +273,7 @@ To add an icon and other properties to the .exe, you can use [the go-winres tool
pkg install git
pkg install devel/pkgconf
pkg install go
pkg install qt6-base qt6-charts qt6-multimedia qt6-svg qt6-webchannel qt6-webengine qt6-declarative qscintilla2-qt6
pkg install qt6-base qt6-charts qt6-multimedia qt6-pdf qt6-svg qt6-webchannel qt6-webengine qt6-declarative qscintilla2-qt6
go build -ldflags '-s -w'
```
@ -290,44 +303,26 @@ Installing `qt@5` from Homebrew may be very slow if Homebrew chooses to do a fro
For dynamic linking:
1. Build the necessary docker container for cross-compilation:
- `docker build -t miqt/osxcross:latest -f docker/macos-cross-x86_64-sdk14.5-go1.19-qt5.15-dynamic.Dockerfile .`
- In the `docker/` directory: `docker build -t miqt/osxcross:latest -f macos-cross-x86_64-sdk14.5-go1.19-qt5.15-dynamic.Dockerfile .`
2. Build your application:
- `docker run --rm -v $(pwd):/src -w /src miqt/osxcross:latest go build -ldflags '-s -w'`
3. Copy necessary Qt LGPL libraries and plugin files.
See FAQ Q3 for advice about docker performance.
### Android (Docker)
### Android (Docker with miqt-docker)
*Tested with Raymii Qt 5.15 / Android SDK 31 / Android NDK 22*
*Tested with Qt.io Qt 6.6 / Android SDK 33 / Android NDK 25*
*Tested with Raymii Qt 5.15 / Android SDK 31 / Android NDK 22 and with Qt.io Qt 6.6 / Android SDK 33 / Android NDK 25*
MIQT supports compiling for Android. Some extra steps are required to bridge the Java, C++, Go worlds.
![](doc/android-architecture.png)
1. Modify your main function to [support `c-shared` build mode](https://pkg.go.dev/cmd/go#hdr-Build_modes).
- Package `main` must have an empty `main` function.
- Rename your `main` function to `AndroidMain` and add a comment `//export AndroidMain`.
- Ensure to `import "C"`.
- Check `examples/android` to see how to support both Android and desktop platforms.
2. Build the necessary docker container for cross-compilation:
- (Qt 5) `docker build -t miqt/android:latest -f docker/android-armv8a-go1.23-qt5.15-dynamic.Dockerfile .`
- (Qt 6) `docker build -t miqt/android:latest -f docker/android-armv8a-go1.23-qt6.6-dynamic.Dockerfile .`
3. Build your application as `.so` format:
- `docker run --rm -v $(pwd):/src -w /src miqt/android:latest go build -buildmode c-shared -ldflags "-s -w -extldflags -Wl,-soname,my_go_app.so" -o android-build/libs/arm64-v8a/my_go_app.so`
4. Build the Qt linking stub:
- (Qt 5) `docker run --rm -v $(pwd):/src -w /src miqt/android:latest android-stub-gen.sh my_go_app.so AndroidMain android-build/libs/arm64-v8a/libRealAppName_arm64-v8a.so`
- (Qt 6) Add `--qt6` final argument
- The linking stub is needed because Qt for Android will itself only call a function named `main`, but `c-shared` can't create one.
5. Build the [androiddeployqt](https://doc.qt.io/qt-6/android-deploy-qt-tool.html) configuration file:
- `docker run --rm -v $(pwd):/src -w /src miqt/android:latest android-mktemplate.sh RealAppName deployment-settings.json`
6. Build the android package:
- `docker run --rm -v $(pwd):/src -w /src miqt/android:latest androiddeployqt --input ./deployment-settings.json --output ./android-build/`
- By default, the resulting `.apk` is generated at `android-build/build/outputs/apk/debug/android-build-debug.apk`.
- You can build in release mode by adding `--release`
```bash
go install github.com/mappu/miqt/cmd/miqt-docker
miqt-docker android-qt5 -android-build # or android-qt6
```
See FAQ Q3 for advice about docker performance.
This produces a `.apk` in the current directory. A default manifest, icon, and keystore will be created. If you customize the `AndroidManifest.xml` file or images, they will be used for the next build.
For repeated builds, only steps 3 and 6 are needed. If you customize the `AndroidManifest.xml` file or images, they will be used for the next `androiddeployqt` run.
Advanced users may customize the build process or manually invoke `androiddeployqt`. You can invoke it inside the container environment via `miqt-docker android-qt5 androiddeployqt ...`. For more information, see the `android-build.sh` file that `miqt-docker` is running.

View File

@ -1,66 +0,0 @@
#!/bin/bash
#
# android-mktemplate generates a template json file suitable for use with the
# androiddeployqt tool.
set -eu
# QT_PATH is already pre-set in our docker container environment. Includes trailing slash.
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
QT_ANDROID=${QT_ANDROID:-$QT_PATH}
ndk_version() {
ls /opt/android-sdk/ndk/ | tail -n1
}
target_sdk_version() {
ls /opt/android-sdk/platforms | tail -n1 | sed -re 's/android-//'
}
build_tools_version() {
ls /opt/android-sdk/build-tools | tail -n1
}
extra_libs() {
if [[ -d /opt/android_openssl ]] ; then
# Our miqt Qt5 container includes these extra .so libraries
# However, the aqtinstall-based Qt 6 container does not use them
echo "/opt/android_openssl/ssl_1.1/arm64-v8a/libssl_1_1.so,/opt/android_openssl/ssl_1.1/arm64-v8a/libcrypto_1_1.so"
fi
}
main() {
if [[ $# -ne 2 ]] ; then
echo "Usage: android-mktemplate.sh appname output.json" >&2
exit 1
fi
local ARG_APPNAME="$1"
local ARG_DESTFILE="$2"
# Available fields are documented in the template file at
# @ref /usr/local/Qt-5.15.13/mkspecs/features/android/android_deployment_settings.prf
cat > "${ARG_DESTFILE}" <<EOF
{
"_description": "Generated by miqt/android-mktemplate",
"application-binary": "${ARG_APPNAME}",
"architectures": {
"arm64-v8a" : "aarch64-linux-android"
},
"android-extra-libs": "$(extra_libs)",
"android-min-sdk-version": "23",
"android-target-sdk-version": "$(target_sdk_version)",
"ndk": "/opt/android-sdk/ndk/$(ndk_version)",
"ndk-host": "linux-x86_64",
"qt": "${QT_ANDROID}",
"sdk": "/opt/android-sdk",
"sdkBuildToolsRevision": "$(build_tools_version)",
"stdcpp-path": "/opt/android-sdk/ndk/$(ndk_version)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/",
"tool-prefix": "llvm",
"toolchain-prefix": "llvm",
"useLLVM": true
}
EOF
}
main "$@"

View File

@ -1,106 +0,0 @@
#!/bin/bash
#
# android-stub-gen generates a .so that runs an exported function from another
# so file. This is because Qt for Android always tries to run `main`, but Go's
# c-shared build mode cannot export a function named `main`.
set -eu
main() {
if [[ $# -ne 3 && $# -ne 4 ]] ; then
echo "Usage: android-gen-stub.sh src.so function-name dest.so [--qt6|--qt5]" >&2
exit 1
fi
local ARG_SOURCE_SOFILE="$1"
local ARG_FUNCTIONNAME="$2"
local ARG_DEST_SOFILE="$3"
local ARG_QTVERSION="${4:---qt5}"
local tmpdir=$(mktemp -d)
trap "rm -r ${tmpdir}" EXIT
echo "- Using temporary directory: ${tmpdir}"
echo "Generating stub..."
cat > $tmpdir/miqtstub.cpp <<EOF
#include <android/log.h>
#include <dlfcn.h>
#include <stdlib.h>
typedef void goMainFunc_t();
int main(int argc, char** argv) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "Starting up");
void* handle = dlopen("$(basename "$ARG_SOURCE_SOFILE")", RTLD_LAZY);
if (handle == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle opening so: %s", dlerror());
exit(1);
}
void* goMain = dlsym(handle, "${ARG_FUNCTIONNAME}");
if (goMain == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle looking for function: %s", dlerror());
exit(1);
}
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Found target, calling");
// Cast to function pointer and call
goMainFunc_t* f = (goMainFunc_t*)goMain;
f();
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Target function returned");
return 0;
}
EOF
# Compile
# Link with Qt libraries so that androiddeployqt detects us as being the
# main shared library
if [[ $ARG_QTVERSION == '--qt5' ]] ; then
# QT_PATH is already pre-set in our docker container environment. Includes trailing slash.
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
echo "- Found Qt path: ${QT_PATH}"
$CXX -shared \
-ldl \
-llog \
-L${QT_PATH}plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
$(pkg-config --libs Qt5Widgets) \
$(pkg-config --libs Qt5AndroidExtras) \
$tmpdir/miqtstub.cpp \
"-Wl,-soname,$(basename "$ARG_DEST_SOFILE")" \
-o "$ARG_DEST_SOFILE"
elif [[ $ARG_QTVERSION == '--qt6' ]] ; then
# QT_ANDROID is already pre-set in our docker container environment. Does NOT include trailing slash
QT_ANDROID=${QT_ANDROID:-/opt/Qt/6.6.1/android_arm64_v8a}
echo "- Found Qt path: ${QT_ANDROID}"
# There is no AndroidExtras in Qt 6
$CXX -shared \
-ldl \
-llog \
-L${QT_ANDROID}/plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
$(pkg-config --libs Qt6Widgets) \
$tmpdir/miqtstub.cpp \
"-Wl,-soname,$(basename "$ARG_DEST_SOFILE")" \
-o "$ARG_DEST_SOFILE"
else
echo "Unknown Qt version argument "${ARG_QTVERSION}" (expected --qt5 or --qt6)" >&2
exit 1
fi
echo "Done."
}
main "$@"

View File

@ -38,7 +38,7 @@ You should check the following configuration:
1. Git clone this repository
2. In `docker/genbindings.Dockerfile`, add your library's headers and pkg-config file.
- If your library does not include a pkg-config file, [you must create one.](pkg-config/README.md)
- If your library does not include a pkg-config file, [you must create one.](../../doc/pkg-config.md)
3. Patch `cmd/genbindings/config-libraries.go` to add a new `generate` block for your target library
4. Run `genbindings` to regenerate all bindings
- The first run must populate clang ASTs into a cache directory and may be slower, but it is fast afterwards

View File

@ -461,6 +461,15 @@ nextMethod:
return CppClass{}, err
}
// Check for private signal
if i, ok := isPrivateSignal(&mm); ok {
// Remove only the QPrivateSignal parameter, keep other parameters
mm.Parameters = append(mm.Parameters[:i], mm.Parameters[i+1:]...)
mm.IsSignal = true
ret.PrivateSignals = append(ret.PrivateSignals, mm)
continue nextMethod
}
mm.IsSignal = isSignal && !mm.IsStatic && AllowSignal(mm)
mm.IsProtected = (visibility == VsProtected)
@ -515,6 +524,17 @@ func isExplicitlyDeleted(node map[string]interface{}) bool {
return false
}
// isPrivateSignal checks if a method is a private signal by looking for a
// QPrivateSignal parameter
func isPrivateSignal(method *CppMethod) (int, bool) {
for i, param := range method.Parameters {
if strings.HasSuffix(param.ParameterType, "::QPrivateSignal") {
return i, true
}
}
return -1, false
}
// processEnum parses a Clang enum into our CppEnum intermediate format.
func processEnum(node map[string]interface{}, addNamePrefix string) (CppEnum, error) {
var ret CppEnum

View File

@ -200,6 +200,22 @@ func ProcessLibraries(clangBin, outDir, extraLibsDir string) {
ClangMatchSameHeaderDefinitionOnly,
)
// Qt 5 PDF
// Depends on QtCore/Gui/Widgets
generate(
"qt/pdf",
[]string{
"/usr/include/x86_64-linux-gnu/qt5/QtPdf",
"/usr/include/x86_64-linux-gnu/qt5/QtPdfWidgets",
},
AllowAllHeaders,
clangBin,
pkgConfigCflags("Qt5PdfWidgets"),
outDir,
ClangMatchSameHeaderDefinitionOnly,
)
// Depends on QtCore/Gui/Widgets, QPrintSupport
generate(
"qt-restricted-extras/qscintilla",
@ -434,6 +450,23 @@ func ProcessLibraries(clangBin, outDir, extraLibsDir string) {
ClangMatchSameHeaderDefinitionOnly,
)
// Qt 6 PDF
generate(
"qt6/pdf",
[]string{
"/usr/include/x86_64-linux-gnu/qt6/QtPdf",
"/usr/include/x86_64-linux-gnu/qt6/QtPdfWidgets",
},
AllowAllHeaders,
clangBin,
"--std=c++17 "+pkgConfigCflags("Qt6PdfWidgets"),
outDir,
ClangMatchSameHeaderDefinitionOnly,
)
// Qt 6 Charts
// Depends on QtCore/Gui/Widgets
generate(

View File

@ -889,6 +889,10 @@ extern "C" {
}
}
for _, m := range c.PrivateSignals {
ret.WriteString(fmt.Sprintf("%s %s(%s* self, intptr_t slot);\n", m.ReturnType.RenderTypeCabi(), cabiConnectName(c, m), className))
}
// delete
if c.CanDelete {
ret.WriteString(fmt.Sprintf("void %s(%s* self);\n", cabiDeleteName(c), className))
@ -970,7 +974,9 @@ extern "C" {
`)
for _, c := range src.Classes {
for _, m := range c.Methods {
methodsAndPrivateSignals := append(c.Methods, c.PrivateSignals...)
for _, m := range methodsAndPrivateSignals {
if m.IsSignal {
callback := "void " + cabiCallbackName(c, m) + "(intptr_t"
@ -1446,6 +1452,32 @@ extern "C" {
}
}
for _, m := range c.PrivateSignals {
exactSignal := `&` + c.ClassName + `::` + m.CppCallTarget()
paramArgs := []string{"slot"}
paramArgDefs := []string{"intptr_t cb"}
var signalCode string
for i, p := range m.Parameters {
signalCode += emitAssignCppToCabi(fmt.Sprintf("\t\t%s sigval%d = ", p.RenderTypeCabi(), i+1), p, p.cParameterName())
paramArgs = append(paramArgs, fmt.Sprintf("sigval%d", i+1))
paramArgDefs = append(paramArgDefs, p.RenderTypeCabi()+" "+p.cParameterName())
}
signalCode += "\t\t" + cabiCallbackName(c, m) + "(" + strings.Join(paramArgs, `, `) + ");\n"
ret.WriteString(
`void ` + cabiConnectName(c, m) + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
"\t" + cppClassName + `::connect(self, ` + exactSignal + `, self, [=](` + emitParametersCpp(m) + `) {` + "\n" +
signalCode +
"\t});\n" +
"}\n" +
"\n",
)
}
// Delete
// If we subclassed, our class destructor is always virtual. Therefore
// we can delete from the self ptr without any dynamic_cast<>

View File

@ -1130,6 +1130,45 @@ import "C"
}
for _, m := range c.PrivateSignals {
gfs.imports["unsafe"] = struct{}{}
gfs.imports["runtime/cgo"] = struct{}{}
var cgoNamedParams []string
var paramNames []string
conversion := ""
if len(m.Parameters) > 0 {
conversion = "// Convert all CABI parameters to Go parameters\n"
}
for i, pp := range m.Parameters {
cgoNamedParams = append(cgoNamedParams, pp.goParameterName()+" "+pp.parameterTypeCgo())
paramNames = append(paramNames, fmt.Sprintf("slotval%d", i+1))
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.goParameterName()) + "\n"
}
goCbType := `func(` + gfs.emitParametersGo(m.Parameters) + `)`
callbackName := cabiCallbackName(c, m)
ret.WriteString(`func (this *` + goClassName + `) On` + m.goMethodName() + `(slot ` + goCbType + `) {
C.` + cabiConnectName(c, m) + `(this.h, C.intptr_t(cgo.NewHandle(slot)) )
}
//export ` + callbackName + `
func ` + callbackName + `(cb C.intptr_t` + ifv(len(m.Parameters) > 0, ", ", "") + strings.Join(cgoNamedParams, `, `) + `) {
gofunc, ok := cgo.Handle(cb).Value().(` + goCbType + `)
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
` + conversion + `
gofunc(` + strings.Join(paramNames, `, `) + ` )
}
`)
}
if c.CanDelete {
gfs.imports["runtime"] = struct{}{} // Finalizer

View File

@ -412,6 +412,7 @@ type CppClass struct {
ChildClassdefs []CppClass
ChildEnums []CppEnum
PrivateMethods []string
PrivateSignals []CppMethod
}
// VirtualMethods checks if the class has any virtual methods. This requires global

63
cmd/miqt-docker/README.md Normal file
View File

@ -0,0 +1,63 @@
# miqt-docker
This is an optional helper program to quickly run a dockerized MIQT cross-compiler
environment. Many containers are available targeting different OSes and Qt versions.
It also has some built-in commands that can be run either dockerized or natively.
## Usage
Run `miqt-docker` with no arguments to see full usage instructions and all
available embedded dockerfiles:
```bash
Usage: miqt-docker ENVIRONMENT COMMAND...
COMMAND may be any shell command (e.g. go build); or /bin/bash to get an
interactive terminal; or one of the following predefined tasks:
-build Run 'go build' with usual MIQT flags
-minify-build Run 'go build' with special minification flags
-windows-build Run 'go build' with special Windows support
-android-build Build an Android APK (using the android-qt5 or android-qt6
container environments)
Environment variables:
DOCKER Override the path to docker
Available container environments: (use - as wildcard character)
[...]
```
You can specify the environment using a short form of the name. For example,
`win64-static` will be expanded to the regex `/win64.+static/` and pick the
best available match with the highest version number (`win64-cross-go1.24-qt6.8-static`
at time of writing).
This allows you to pin platforms and major versions in build commands while
automatically upgrading to minor versions.
Example build commands:
```bash
miqt-docker macos go build -ldflags '-s -w'
miqt-docker native -minify-build
miqt-docker win64-qt6-static -windows-build
miqt-docker win64-qt6-static /bin/bash
miqt-docker android-qt6 -android-build
```
## Comparison to manual Docker commands
You can create a dockerized MIQT build environment yourself using the Dockerfiles
in the `docker/` directory. The benefit of miqt-docker is:
- Embeds all available MIQT docker containers
- Use glob matches to automatically pick the highest version container for target
- Automatically build new docker containers or reuse existing, based on content hash of the Dockerfile
- Consistently named docker images across multiple projects using MIQT
- Automatically bind source code volume from current go.mod / go.work / git repository and preserve relative working directory
- Handles bind-mounting the GOCACHE and GOMODCACHE directories for fast rebuilds
- Handles using the proper uid+gid on Linux
- Automatically detect sudo requirement on Linux
- Convenient predefined tasks
- Advanced build support for Android

View File

@ -0,0 +1,415 @@
#!/bin/bash
#
# android-build.sh allows building a MIQT Go application for Android.
# For details, see the top-level README.md file.
set -Eeuo pipefail
# QT_PATH is pre-set in the Qt 5 docker container environment. Includes trailing slash
# QT_ANDROID is pre-set in the Qt 6 docker container environment
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
QT_ANDROID=${QT_ANDROID:-$QT_PATH}
export LC_ALL=C.UTF-8
# get_app_name returns the android app's name. This affects the default name
# in deployment-settings.json and the generated lib.so names.
# You can still customise the package name and the package ID in the xml
# files after generation.
get_app_name() {
basename "$(pwd)"
}
get_stub_soname() {
# libRealAppName_arm64-v8a.so
echo "lib$(get_app_name)_arm64-v8a.so"
}
get_go_soname() {
echo "libMiqtGolangApp_arm64-v8a.so"
}
ndk_version() {
ls /opt/android-sdk/ndk/ | tail -n1
}
target_sdk_version() {
ls /opt/android-sdk/platforms | tail -n1 | sed -re 's/android-//'
}
build_tools_version() {
ls /opt/android-sdk/build-tools | tail -n1
}
# extra_libs returns a comma-separated list of extra libraries to include in
# the apk package
extra_libs() {
if [[ -d /opt/android_openssl ]] ; then
# Our miqt Qt5 container includes these extra .so libraries
# However, the aqtinstall-based Qt 6 container does not use them
echo "/opt/android_openssl/ssl_1.1/arm64-v8a/libssl_1_1.so,/opt/android_openssl/ssl_1.1/arm64-v8a/libcrypto_1_1.so"
fi
}
# generate_template_contents produces a deployment settings JSON file that is
# understood by the androiddeployqt program.
# Available fields are documented in the template file at:
# @ref /usr/local/Qt-5.15.13/mkspecs/features/android/android_deployment_settings.prf
generate_template_contents() {
cat <<EOF
{
"_description": "Generated by miqt/android-mktemplate",
"application-binary": "$(get_app_name)",
"architectures": {
"arm64-v8a" : "aarch64-linux-android"
},
"android-extra-libs": "$(extra_libs)",
"android-min-sdk-version": "23",
"android-target-sdk-version": "$(target_sdk_version)",
"ndk": "/opt/android-sdk/ndk/$(ndk_version)",
"ndk-host": "linux-x86_64",
"qt": "${QT_ANDROID}",
"sdk": "/opt/android-sdk",
"sdkBuildToolsRevision": "$(build_tools_version)",
"stdcpp-path": "/opt/android-sdk/ndk/$(ndk_version)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/",
"tool-prefix": "llvm",
"toolchain-prefix": "llvm",
"useLLVM": true
}
EOF
}
# pkg_config_dependencies echoes the pkg-config packages that are needed as
# a baseline for the detected Qt version.
# It's not smart enough to discover other Qt packages yet.
pkg_config_dependencies() {
local QT_VERSION=$(detect_miqt_qt_version)
if [[ $QT_VERSION == 'qt5' ]] ; then
echo Qt5Widgets
echo Qt5AndroidExtras
elif [[ $QT_VERSION == 'qt6' ]] ; then
# There is no AndroidExtras in Qt 6
echo Qt6Widgets
fi
}
# android_stub_gen generates a .so that runs an exported function from another
# so file. This is because Qt for Android always tries to run `main`, but Go's
# c-shared build mode cannot export a function named `main`.
android_stub_gen() {
local STUBNAME="miqt-stub-$(date +%s).cpp"
cat > $STUBNAME <<EOF
#include <android/log.h>
#include <dlfcn.h>
#include <stdlib.h>
typedef void goMainFunc_t();
int main(int argc, char** argv) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "Starting up");
void* handle = dlopen("$(get_go_soname)", RTLD_LAZY);
if (handle == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle opening so: %s", dlerror());
exit(1);
}
void* goMain = dlsym(handle, "AndroidMain");
if (goMain == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle looking for function: %s", dlerror());
exit(1);
}
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Found target, calling");
// Cast to function pointer and call
goMainFunc_t* f = (goMainFunc_t*)goMain;
f();
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Target function returned");
return 0;
}
EOF
# Compile
# Link with Qt libraries so that androiddeployqt detects us as being the
# main shared library
$CXX -shared \
-ldl \
-llog \
-L${QT_ANDROID}/plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
$(pkg-config --libs $(pkg_config_dependencies)) \
${STUBNAME} \
"-Wl,-soname,$(basename "$(get_stub_soname)")" \
-o "android-build/libs/arm64-v8a/$(get_stub_soname)"
rm "${STUBNAME}"
}
# require_is_main_package verifies that this is the main Go package.
require_is_main_package() {
if ! grep -Fq 'package main' *.go ; then
echo "This doesn't seem to be the main package" >&2
exit 1
fi
}
# patch_app_main sets up the startup go files so that the go program can be
# built either as c-shared for Android or as a normal program for desktop OSes.
patch_app_main() {
# Replace func main() with app_main()
for srcfile in *.go ; do
sed -i -re 's/^func main\(\) \{/func app_main() {/' "$srcfile"
done
# Add shim startup files
cat <<EOF > startup_android.go
//go:build android
// +build android
package main
import "C" // Required for export support
//export AndroidMain
func AndroidMain() {
app_main()
}
func main() {
// Must be empty
}
EOF
cat <<EOF > startup_other.go
//go:build !android
// +build !android
package main
func main() {
app_main()
}
EOF
gofmt -w startup_android.go || true
gofmt -w startup_other.go || true
# Done
}
# unpatch_app_main undoes the transformation from patch_app_main.
unpatch_app_main() {
# Replace func main() with app_main()
for srcfile in *.go ; do
sed -i -re 's/^func app_main\(\) \{/func main() {/' "$srcfile"
done
# Remove extra startup files
rm startup_android.go || true
rm startup_other.go || true
}
# build_app_so compiles the Go app as a c-shared .so.
build_app_so() {
go build \
-buildmode c-shared \
-ldflags "-s -w -extldflags -Wl,-soname,$(get_go_soname)" \
-o "android-build/libs/arm64-v8a/$(get_go_soname)"
}
sdkmanager() {
echo /opt/android-sdk/cmdline-tools/*/bin/sdkmanager
}
# build_apk calls androiddeployqt to package the android-build directory into
# the final apk.
build_apk() {
# Qt 6 androiddeployqt: Understands the QT_ANDROID_KEYSTORE_STORE_PASS in env
# Qt 5 androiddeployqt: Doesn't - any use of `--sign keystore alias` here
# requires stdin prompt but doesn't pass androiddeployqt's stdin through
# to jarsigner subprocess
# Either way, don't sign the app here, rely on separate jarsigner command
# Work around an issue with Qt 6 sporadically failing to detect that
# we have a valid Qt platform plugin
# TODO why does this happen? Is it related to file sort ordering?
# It really does fix itself after multiple attempts (usually less than 5)
# - When it fails: Error: qmlimportscanner not found at /qmlimportscanner
# - When it works: Error: qmlimportscanner not found at libexec/qmlimportscanner
while ! androiddeployqt \
--input ./deployment-settings.json \
--output ./android-build/ \
--release \
2> >(tee /tmp/androiddeployqt.stderr.log >&2) ; do
if grep -Fq 'Make sure the app links to Qt Gui library' /tmp/androiddeployqt.stderr.log ; then
echo "Detected temporary problem with Qt plugin detection. Retrying..."
sleep 1
else
# real error
exit 1
fi
done
local OUTAPK=$(get_app_name).apk
rm "$OUTAPK" || true
# Zipalign
echo "Zipalign..."
/opt/android-sdk/build-tools/*/zipalign \
-p 4 \
./android-build/build/outputs/apk/release/android-build-release-unsigned.apk \
"$OUTAPK"
# Sign
echo "Signing..."
#jarsigner \
# -verbose \
# -sigalg SHA256withRSA -digestalg SHA256 \
# -keystore ./android.keystore \
# "$OUTAPK" \
# "${QT_ANDROID_KEYSTORE_ALIAS}" \
# -storepass:env QT_ANDROID_KEYSTORE_STORE_PASS \
# -keypass:env QT_ANDROID_KEYSTORE_KEY_PASS
/opt/android-sdk/build-tools/*/apksigner \
sign \
--ks ./android.keystore \
--ks-key-alias "${QT_ANDROID_KEYSTORE_ALIAS}" \
--ks-pass env:QT_ANDROID_KEYSTORE_STORE_PASS \
--key-pass env:QT_ANDROID_KEYSTORE_KEY_PASS \
"$OUTAPK"
}
# detect_env_qt_version detects the system's current Qt version.
detect_env_qt_version() {
if qmake --version | fgrep -q 'Qt version 5' ; then
echo "qt5"
return 0
elif qmake --version | fgrep -q 'Qt version 6' ; then
echo "qt6"
return 0
else
echo "Missing Qt tools in PATH" >&2
exit 1
fi
}
# detect_miqt_qt_version echoes either "qt5", "qt6", or exits bash.
detect_miqt_qt_version() {
local IS_QT5=false
if grep -qF '"github.com/mappu/miqt/qt"' *.go ; then
IS_QT5=true
fi
local IS_QT6=false
if grep -qF '"github.com/mappu/miqt/qt6"' *.go ; then
IS_QT6=true
fi
if [[ $IS_QT5 == true && $IS_QT6 == true ]] ; then
echo "Found qt5 and qt6 imports, confused about what to do next" >&2
exit 1
elif [[ $IS_QT5 == true ]] ; then
echo "qt5"
return 0
elif [[ $IS_QT6 == true ]] ; then
echo "qt6"
return 0
else
echo "Found neither qt5 nor qt6 imports. Is this a MIQT Qt app?" >&2
exit 1
fi
}
generate_default_keystore() {
local GENPASS=storepass_$(cat /dev/urandom | head -c64 | md5sum | cut -d' ' -f1)
keytool \
-genkeypair \
-dname "cn=Miqt, ou=Miqt, o=Miqt, c=US" \
-keyalg RSA \
-alias miqt \
-keypass "${GENPASS}" \
-keystore ./android.keystore \
-storepass "${GENPASS}" \
-validity 20000
echo "QT_ANDROID_KEYSTORE_PATH=./android.keystore" > android.keystore.env
echo "QT_ANDROID_KEYSTORE_ALIAS=miqt" >> android.keystore.env
echo "QT_ANDROID_KEYSTORE_STORE_PASS=${GENPASS}" >> android.keystore.env
echo "QT_ANDROID_KEYSTORE_KEY_PASS=${GENPASS}" >> android.keystore.env
}
# main is the entrypoint for android-build.sh.
main() {
if [[ $(detect_env_qt_version) != $(detect_miqt_qt_version) ]] ; then
echo "The system is $(detect_env_qt_version) but the app uses $(detect_miqt_qt_version). Is this the right container?" >&2
exit 1
fi
require_is_main_package
# Rebuild deployment-settings.json
if [[ ! -f deployment-settings.json ]] ; then
echo "Generating deployment-settings.json..."
generate_template_contents > deployment-settings.json
fi
mkdir -p android-build/libs/arm64-v8a
if [[ ! -f android-build/libs/arm64-v8a/$(get_stub_soname) ]] ; then
echo "Generating stub so..."
android_stub_gen
fi
# Rebuild miqt_golang_app.so
echo "Compiling Go app..."
patch_app_main
build_app_so
unpatch_app_main
# Keypair
if [[ ! -f android.keystore || ! -f android.keystore.env ]] ; then
echo "Signing keystore not found, generating a default one..."
generate_default_keystore
fi
# Load keypair credentials into exported env vars
set -o allexport
source android.keystore.env
set +o allexport
# Generate .apk
echo "Packaging APK..."
build_apk
echo "Complete"
}
main "$@"

108
cmd/miqt-docker/docker.go Normal file
View File

@ -0,0 +1,108 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"io"
"log"
"os"
"os/exec"
"regexp"
)
var (
needsSudo bool
)
// dockerImage describes an image available in the docker daemon.
type dockerImage struct {
ID string
Repository string
Tag string
}
// dockerCommand creates an *exec.Cmd for running docker. It respects the global
// `needsSudo` state.
func dockerCommand(args ...string) *exec.Cmd {
docker := os.Getenv("DOCKER")
if docker == "" {
docker = "docker"
}
if needsSudo {
useArgs := make([]string, 0, len(args)+1)
useArgs = append(useArgs, docker)
useArgs = append(useArgs, args...)
return exec.Command(`sudo`, useArgs...)
}
return exec.Command(docker, args...)
}
// dockerListImages lists all the current docker images.
func dockerListImages() ([]dockerImage, error) {
cmd := dockerCommand(`image`, `ls`, `--format`, `{{json . }}`)
cmd.Stderr = os.Stderr // passthrough
buff, err := cmd.Output()
if err != nil {
if !needsSudo {
// Retry with sudo
log.Println("Retrying with sudo...")
needsSudo = true
return dockerListImages()
}
return nil, err
}
var ret []dockerImage
dec := json.NewDecoder(bytes.NewReader(buff))
for {
var entry dockerImage
err = dec.Decode(&entry)
if err != nil {
if errors.Is(err, io.EOF) {
return ret, nil
}
return nil, err // real error
}
ret = append(ret, entry)
}
}
// dockerFindImage searches all the current docker images to find one named as
// the supplied `repository:tag`.
func dockerFindImage(repository, tag string) (*dockerImage, error) {
images, err := dockerListImages()
if err != nil {
return nil, err
}
re := regexp.MustCompile("^localhost/")
for _, im := range images {
if (im.Repository == repository || re.ReplaceAllString(im.Repository, "") == repository) && im.Tag == tag {
// found it
return &im, nil
}
}
// No match
return nil, os.ErrNotExist
}
// dockerBuild builds the supplied dockerfile and tags it as repository:tag
// as well as repository:latest.
func dockerBuild(dockerfile []byte, repository, tag string) error {
cmd := dockerCommand(`build`, `-t`, repository+`:`+tag, `-t`, repository+`:latest`, `-`)
cmd.Stderr = os.Stderr
cmd.Stdin = bytes.NewReader(dockerfile)
return cmd.Run()
}

View File

@ -0,0 +1,64 @@
package main
import (
"errors"
"fmt"
"path/filepath"
"runtime"
"strings"
)
// highestCommonParent finds the oldest ancestor of a set of paths.
// If there is no common ancestor, returns / on Linux or an error on Windows.
func highestCommonParent(paths []string) (string, error) {
if len(paths) == 0 {
return "", errors.New("no input")
}
parts := strings.Split(paths[0], string(filepath.Separator))
caseSensitive := runtime.GOOS != "windows"
for _, check := range paths {
checkn := strings.Split(check, string(filepath.Separator))
// If this check path is shorter, the common part must also shrink
if len(checkn) < len(parts) {
parts = parts[0:len(checkn)]
}
for i, checkpart := range checkn[0:len(parts)] { // len(parts) is now <= len(checkn) so this is safe
if caseSensitive {
if parts[i] == checkpart {
continue
}
} else {
// case insensitive comparison
if strings.EqualFold(parts[i], checkpart) {
continue
}
}
// Divergence from i: onwards
parts = parts[0:i]
break
}
// Early failure case
if len(parts) == 0 {
break
}
}
isEmpty := len(parts) == 0 || (len(parts) == 1 && parts[0] == "")
if isEmpty {
if runtime.GOOS == "windows" {
return "", fmt.Errorf("Selected paths have no common ancestor: %v", paths)
}
return `/`, nil
}
return strings.Join(parts, string(filepath.Separator)), nil
}

View File

@ -0,0 +1,78 @@
package main
import (
"runtime"
"testing"
)
func TestHighestCommonParent(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("This test uses platform-specific paths")
}
type testCase struct {
input []string
expect string
}
cases := []testCase{
// Single input
testCase{
input: []string{`/foo/bar/baz`},
expect: `/foo/bar/baz`,
},
// Duplicated input
testCase{
input: []string{`/foo/bar/baz`, `/foo/bar/baz`},
expect: `/foo/bar/baz`,
},
// Trailing slashes are preserved if they all included trailing slashes
testCase{
input: []string{`/foo/bar/baz/`, `/foo/bar/baz/`},
expect: `/foo/bar/baz/`,
},
// Common directory
testCase{
input: []string{`/foo/bar/baz`, `/foo/quux`},
expect: `/foo`,
},
// Common directory, multiple inputs
testCase{
input: []string{`/foo/a`, `/foo/b`, `/foo/c`, `/foo/d`},
expect: `/foo`,
},
testCase{
input: []string{`/foo/bar/baz`, `/unrelated`, `/foo/bar/baz`},
expect: `/`,
},
// No leading forwardslash (single input)
testCase{
input: []string{`foo/bar/baz`},
expect: `foo/bar/baz`,
},
// No leading forwardslash (empty output assumes /)
testCase{
input: []string{`foo/bar/baz`, `unrelated`, `foo/bar/baz`},
expect: `/`,
},
}
for idx, tc := range cases {
got, err := highestCommonParent(tc.input)
if err != nil {
t.Errorf("test %d: input(%v) got error=%v", idx, tc.input, err)
continue
}
if got != tc.expect {
t.Errorf("test %d: input(%v) got %q, want %q", idx, tc.input, got, tc.expect)
}
}
}

View File

@ -0,0 +1,24 @@
//+build linux
//go:build linux
package main
import (
"os"
"syscall"
"unsafe"
)
func isatty() bool {
fd := os.Stdout.Fd()
req := syscall.TCGETS
termios := syscall.Termios{}
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(unsafe.Pointer(&termios)))
if errno != 0 {
return false
}
// Successfully got Termios info = stdout is a tty
return true
}

View File

@ -0,0 +1,8 @@
//+build !linux
//go:build !linux
package main
func isatty() bool {
return true
}

296
cmd/miqt-docker/main.go Normal file
View File

@ -0,0 +1,296 @@
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io/fs"
"log"
"os"
"os/exec"
"os/user"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/mappu/miqt/docker"
)
// glob2regex converts the glob pattern into a regexp.
// It only supports `-` as a special character meaning 'anything'.
// The resulting regex is unanchored i.e. can match anywhere within a target string.
func glob2regex(pattern string) *regexp.Regexp {
parts := strings.Split(pattern, `-`)
for i, p := range parts {
parts[i] = regexp.QuoteMeta(p)
}
return regexp.MustCompile(strings.Join(parts, `.*`))
}
// shasum returns the hex sha256 of a byte slice.
func shasum(data []byte) string {
hashdata := sha256.Sum256(data)
return hex.EncodeToString(hashdata[:])
}
// usage displays how to use miqt-docker and then exits the process.
func usage(dockerfiles []fs.DirEntry) {
fmt.Fprint(os.Stderr, `Usage: `+filepath.Base(os.Args[0])+` ENVIRONMENT COMMAND...
COMMAND may be any shell command (e.g. go build); or /bin/bash to get an
interactive terminal; or one of the following special tasks:
-build Run 'go build' with usual MIQT flags
-minify-build Run 'go build' with special minification flags
-windows-build Run 'go build' with special Windows support
-android-build Build an Android APK (using the android-qt5 or android-qt6
container environments)
Environment variables:
DOCKER Override the path to docker
Available container environments: (use - as wildcard character)
native (Run natively without docker)
`)
for _, ff := range dockerfiles {
fmt.Fprintf(os.Stderr, " %s\n", strings.TrimSuffix(ff.Name(), `.Dockerfile`))
}
os.Exit(1)
}
// getDockerRunArgsForGlob returns a []string array of all the {busywork} arguments
// for a `docker {run -e -v ...} go build` command.
// It does glob matching for the target container, and builds it if it does not yet exist.
func getDockerRunArgsForGlob(dockerfiles []fs.DirEntry, containerNameGlob string, isatty bool) ([]string, error) {
requestEnvironment := glob2regex(containerNameGlob)
var match string
for _, ff := range dockerfiles {
if !requestEnvironment.MatchString(ff.Name()) {
continue
}
match = ff.Name()
// continue searching for a later match with higher version number
}
if match == "" {
return nil, fmt.Errorf("No available environment matches the request %q\n", containerNameGlob)
}
if !(match == os.Args[1] || match == os.Args[1]+`.Dockerfile`) {
// An inexact/glob match was involved. Show what it was
log.Printf("Selecting dockerfile: %s", match)
}
dockerFileContent, err := docker.ReadFile(match)
if err != nil {
return nil, err // shouldn't happen
}
dockerfileHash := shasum(dockerFileContent)[:8] // First 8 characters of content hash
// Check to see if this dockerfile has already been turned into an image
containerName := `miqt-docker/` + strings.TrimSuffix(match, `.Dockerfile`)
_, err = dockerFindImage(containerName, dockerfileHash)
if err != nil {
if err != os.ErrNotExist {
return nil, err // real error
}
log.Printf("No matching docker image, creating...")
err = dockerBuild(dockerFileContent, containerName, dockerfileHash)
if err != nil {
return nil, err
}
// Search again
_, err = dockerFindImage(containerName, dockerfileHash)
if err != nil {
return nil, fmt.Errorf("Failed to build container for %s:%s: %w", containerName, dockerfileHash, err) // Any error now is a real error
}
}
// Container match found - clean up older containers for the same tag
allContainers, err := dockerListImages()
if err != nil {
return nil, err
}
for _, ctr := range allContainers {
if ctr.Repository == containerName &&
!(ctr.Tag == dockerfileHash || ctr.Tag == "latest") {
log.Printf("Removing previous version container %s:%s ...", containerName, ctr.Tag)
rmCmd := dockerCommand(`image`, `rm`, containerName+`:`+ctr.Tag)
rmCmd.Stdout = os.Stdout
rmCmd.Stderr = os.Stderr
err = rmCmd.Run()
if err != nil {
log.Printf("Warning: Failed to remove previous container: %v", err.Error())
// log and continue
}
}
}
// Container match found - safe to run our command
fullCommand := []string{"run", "--rm", "-i"}
if isatty {
fullCommand = append(fullCommand, "-t")
}
if runtime.GOOS != "windows" {
userinfo, err := user.Current()
if err != nil {
log.Panic(err)
}
fullCommand = append(fullCommand, `--user`, userinfo.Uid+`:`+userinfo.Gid)
}
// Find the GOMODCACHE and GOCACHE to populate mapped volumes
gomodcache, err := exec.Command(`go`, `env`, `GOMODCACHE`).Output()
if err != nil {
return nil, fmt.Errorf("Finding GOMODCACHE: %w", err)
}
if gomodcache_sz := strings.TrimSpace(string(gomodcache)); len(gomodcache_sz) > 0 {
_ = os.MkdirAll(gomodcache_sz, 0755) // Might not exist if no Go modules have been used yet
fullCommand = append(fullCommand, `-v`, gomodcache_sz+`:/go/pkg/mod`, `-e`, `GOMODCACHE=/go/pkg/mod`)
}
gocache, err := exec.Command(`go`, `env`, `GOCACHE`).Output()
if err != nil {
return nil, fmt.Errorf("Finding GOCACHE: %w", err)
}
if gocache_sz := strings.TrimSpace(string(gocache)); len(gocache_sz) > 0 {
_ = os.MkdirAll(gocache_sz, 0755) // Might not exist if no Go packages have been built yet
fullCommand = append(fullCommand, `-v`, gocache_sz+`:/.cache/go-build`, `-e`, `GOCACHE=/.cache/go-build`)
}
// We need to bind-mount probably not just the current working directory,
// but upwards to the root git repo / go.mod file / go.work file (whichever
// is highest)
var parentPaths []string
gomod, err := exec.Command(`go`, `env`, `GOMOD`).Output()
if err != nil {
return nil, fmt.Errorf("Finding GOMOD: %w", err)
}
if gomod_sz := strings.TrimSpace(string(gomod)); len(gomod_sz) > 0 {
parentPaths = append(parentPaths, gomod_sz)
}
gowork, err := exec.Command(`go`, `env`, `GOWORK`).Output()
if err != nil {
return nil, fmt.Errorf("Finding GOWORK: %w", err)
}
if gowork_sz := strings.TrimSpace(string(gowork)); len(gowork_sz) > 0 {
parentPaths = append(parentPaths, gowork_sz)
}
gitroot, err := exec.Command(`git`, `rev-parse`, `--show-toplevel`).Output()
if err != nil {
// Maybe this isn't a git repository? Git is optional anyway, there are hg/bzr users
// Don't panic
} else {
if gitroot_sz := strings.TrimSpace(string(gitroot)); len(gitroot_sz) > 0 {
parentPaths = append(parentPaths, gitroot_sz)
}
}
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
parentPaths = append(parentPaths, cwd) // It's an option too
basedir, err := highestCommonParent(parentPaths)
if err != nil {
return nil, err
}
relCwd, err := filepath.Rel(basedir, cwd)
if err != nil {
return nil, err
}
// Don't mount directly on /src , otherwise -android-build will not know
// the package name for top-level builds. Use a subfolder within it
mountDir := `/src/` + filepath.Base(cwd)
if runtime.GOOS == "windows" {
// convert C:\foo\bar paths to /c/foo/bar that Docker understands
// Otherwise, you experience "invalid mode" when the : is parsed
basedir = `/` + strings.ToLower(string(basedir[0])) + `/` + strings.ReplaceAll(basedir[3:], `\`, `/`)
// Always forwardslashes for in-docker paths, even on Windows OS
mountDir = strings.ReplaceAll(mountDir, `\`, `/`)
}
fullCommand = append(fullCommand,
`-v`, basedir+`:`+mountDir,
`-w`, path.Join(mountDir, relCwd),
// Final standard docker commands
`-e`, `HOME=/tmp`,
containerName+`:`+dockerfileHash,
)
return fullCommand, nil
}
func main() {
dockerfiles, err := docker.Dockerfiles.ReadDir(`.`)
if err != nil {
log.Fatal(err)
}
if len(os.Args) < 3 {
usage(dockerfiles)
}
taskArgs, taskOp, taskAllowTty, err := evaluateTask(os.Args[2:])
if err != nil {
log.Fatal(err)
}
var cmd *exec.Cmd
if os.Args[1] == "native" {
if taskArgs[0] == `/bin/bash` && runtime.GOOS == "windows" {
log.Fatal("This command can't be used in 'native' mode on Windows.")
}
cmd = exec.Command(taskArgs[0], taskArgs[1:]...) // n.b. [1:] may be an empty slice
} else {
dockerArgs, err := getDockerRunArgsForGlob(dockerfiles, os.Args[1], taskAllowTty && isatty())
if err != nil {
log.Fatal(err)
}
dockerArgs = append(dockerArgs, taskArgs...)
cmd = dockerCommand(dockerArgs...)
}
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
taskOp(cmd)
err = cmd.Run()
if err != nil {
log.Fatal(err)
}
}

77
cmd/miqt-docker/tasks.go Normal file
View File

@ -0,0 +1,77 @@
package main
import (
"bytes"
"embed"
"errors"
"fmt"
"os/exec"
)
//go:embed android-build.sh
var embedAndroidBuildSh []byte
var _ embed.FS // Workaround to allow import of package `embed`
// evaluateTask turns the supplied process arguments into real arguments to
// execute, handling quick command recipes as well as arbitrary execution
func evaluateTask(taskArgs []string) (retArgs []string, fixup func(*exec.Cmd), allowTty bool, err error) {
if len(taskArgs) == 0 {
return nil, nil, false, errors.New("No task specified")
}
if len(taskArgs[0]) == 0 {
return nil, nil, false, errors.New("Empty-string first command")
}
// Set up defaults
retArgs = []string{}
fixup = func(*exec.Cmd) {} // no-op
allowTty = true
//
stdinFrom := func(stdinBytes []byte) func(*exec.Cmd) {
return func(c *exec.Cmd) {
c.Stdin = bytes.NewReader(stdinBytes)
}
}
//
if taskArgs[0][0] != '-' {
// Task does not start with a hyphen = plain command
retArgs = taskArgs
return
}
switch taskArgs[0] {
case `-build`:
retArgs = []string{"go", "build", "-ldflags", "-s -w"}
retArgs = append(retArgs, taskArgs[1:]...)
return
case `-windows-build`:
retArgs = []string{"go", "build", "-ldflags", "-s -w -H windowsgui"}
retArgs = append(retArgs, taskArgs[1:]...)
return
case `-minify-build`:
// @ref https://github.com/mappu/miqt/issues/147#issuecomment-2800331135
retArgs = []string{`/bin/bash`, `-c`, "CGO_CFLAGS='-Os -ffunction-sections -fdata-sections -flto=auto' CGO_CXXFLAGS='-Os -ffunction-sections -fdata-sections -flto=auto' CGO_LDFLAGS='-Wl,--gc-sections -flto=auto -fwhole-program' go build -ldflags '-s -w'"}
retArgs = append(retArgs, taskArgs[1:]...)
return
case `-android-build`:
retArgs = []string{"/bin/bash", "-s"}
retArgs = append(retArgs, taskArgs[1:]...)
fixup = stdinFrom(embedAndroidBuildSh)
allowTty = false
return
default:
return nil, nil, false, fmt.Errorf("Unrecognized task %q", taskArgs[0])
}
}

View File

@ -10,9 +10,10 @@ type UiLayoutItem struct {
RowSpan *int `xml:"rowspan,attr"`
ColSpan *int `xml:"colspan,attr"`
// A layout item either has a widget, or a spacer
// A layout item either has a widget, or a spacer, or another layout
Widget *UiWidget `xml:"widget"`
Spacer *UiSpacer `xml:"spacer"`
Layout *UiLayout `xml:"layout"`
}
type UiLayout struct {
@ -61,6 +62,7 @@ type UiString struct {
type UiIcon struct {
ResourceFile string `xml:"resource,attr"`
Theme string `xml:"theme,attr"`
NormalOff *string `xml:"normaloff,omitempty"`
NormalOn *string `xml:"normalon,omitempty"`
@ -74,15 +76,23 @@ type UiIcon struct {
Base string `xml:",chardata"`
}
type UiSizePolicy struct {
HSizeType string `xml:"hsizetype,attr"`
VSizeType string `xml:"vsizetype,attr"`
HStretch int `xml:"horstretch"`
VStretch int `xml:"verstretch"`
}
type UiProperty struct {
Name string `xml:"name,attr"`
StringVal *UiString `xml:"string,omitempty"`
NumberVal *string `xml:"number,omitempty"` // Preserve as string literal
BoolVal *bool `xml:"bool,omitempty"` // "true" or "false"
EnumVal *string `xml:"enum,omitempty"`
RectVal *UiRect `xml:"rect,omitempty"`
IconVal *UiIcon `xml:"iconset,omitempty"`
SetVal *string `xml:"set,omitempty"`
Name string `xml:"name,attr"`
StringVal *UiString `xml:"string,omitempty"`
NumberVal *string `xml:"number,omitempty"` // Preserve as string literal
BoolVal *bool `xml:"bool,omitempty"` // "true" or "false"
EnumVal *string `xml:"enum,omitempty"`
RectVal *UiRect `xml:"rect,omitempty"`
IconVal *UiIcon `xml:"iconset,omitempty"`
SetVal *string `xml:"set,omitempty"`
SizePolicyVal *UiSizePolicy `xml:"sizepolicy,omitempty"`
}
type UiActionReference struct {

View File

@ -12,26 +12,46 @@ var (
DefaultGridMargin = 11
DefaultSpacing = 6
IconCounter = 0
trackWidgetClasses map[string]string
)
func collectClassNames_Layout(l *UiLayout) []string {
var ret []string
if l.Name != "" {
ret = append(ret, l.Name+" *qt."+l.Class)
trackWidgetClasses[l.Name] = l.Class
}
for _, li := range l.Items {
if li.Widget != nil {
ret = append(ret, collectClassNames_Widget(li.Widget)...)
}
if li.Spacer != nil {
ret = append(ret, li.Spacer.Name+" *qt.QSpacerItem")
}
if li.Layout != nil {
ret = append(ret, collectClassNames_Layout(li.Layout)...)
}
}
return ret
}
func collectClassNames_Widget(u *UiWidget) []string {
var ret []string
if u.Name != "" {
ret = append(ret, u.Name+" *qt."+u.Class)
trackWidgetClasses[u.Name] = u.Class
}
for _, w := range u.Widgets {
ret = append(ret, collectClassNames_Widget(&w)...)
}
if u.Layout != nil {
ret = append(ret, u.Layout.Name+" *qt."+u.Layout.Class)
for _, li := range u.Layout.Items {
if li.Widget != nil {
ret = append(ret, collectClassNames_Widget(li.Widget)...)
}
if li.Spacer != nil {
ret = append(ret, li.Spacer.Name+" *qt.QSpacerItem")
}
}
ret = append(ret, collectClassNames_Layout(u.Layout)...)
}
for _, a := range u.Actions {
ret = append(ret, a.Name+" *qt.QAction")
@ -70,13 +90,22 @@ func renderIcon(iconVal *UiIcon, ret *strings.Builder) string {
iconName := fmt.Sprintf("icon%d", IconCounter)
IconCounter++
ret.WriteString(iconName + " := qt.NewQIcon()\n")
if iconVal.Theme != "" {
ret.WriteString(iconName + ` := qt.QIcon_FromTheme(` + strconv.Quote(iconVal.Theme) + ")\n")
} else {
ret.WriteString(iconName + " := qt.NewQIcon()\n")
}
// A base entry is a synonym for NormalOff. Don't need them both
if iconVal.NormalOff != nil {
if iconVal.NormalOff != nil && *iconVal.NormalOff != "." {
ret.WriteString(iconName + ".AddFile4(" + strconv.Quote(*iconVal.NormalOff) + ", qt.NewQSize(), qt.QIcon__Normal, qt.QIcon__Off)\n")
} else {
ret.WriteString(iconName + ".AddFile(" + strconv.Quote(strings.TrimSpace(iconVal.Base)) + ")\n")
base := strings.TrimSpace(iconVal.Base)
if base == "" || base == "." {
// skip
} else {
ret.WriteString(iconName + ".AddFile(" + strconv.Quote(strings.TrimSpace(iconVal.Base)) + ")\n")
}
}
if iconVal.NormalOn != nil {
@ -182,6 +211,17 @@ func renderProperties(properties []UiProperty, ret *strings.Builder, targetName,
iconName := renderIcon(prop.IconVal, ret)
ret.WriteString(`ui.` + targetName + setterFunc + `(` + iconName + ")\n")
} else if prop.Name == "sizePolicy" {
spn := targetName + "__sizePolicy"
ret.WriteString(spn + " := qt.NewQSizePolicy()\n")
ret.WriteString(spn + ".SetHorizontalPolicy(" + normalizeEnumName("QSizePolicy::"+prop.SizePolicyVal.HSizeType) + ")\n")
ret.WriteString(spn + ".SetVerticalPolicy(" + normalizeEnumName("QSizePolicy::"+prop.SizePolicyVal.VSizeType) + ")\n")
ret.WriteString(spn + ".SetHorizontalStretch(" + strconv.Itoa(prop.SizePolicyVal.HStretch) + ")\n")
ret.WriteString(spn + ".SetVerticalStretch(" + strconv.Itoa(prop.SizePolicyVal.VStretch) + ")\n")
ret.WriteString(spn + ".SetHeightForWidth(ui." + targetName + ".SizePolicy().HasHeightForWidth())\n")
ret.WriteString("ui." + targetName + ".SetSizePolicy(*" + spn + ")\n")
ret.WriteString(spn + ".Delete() // setter copies values\n")
} else {
ret.WriteString("/* miqt-uic: no handler for " + targetName + " property '" + prop.Name + "' */\n")
}
@ -200,15 +240,170 @@ func renderProperties(properties []UiProperty, ret *strings.Builder, targetName,
return nil
}
func generateWidget(w UiWidget, parentName string, parentClass string) (string, error) {
func generateSetObjectName(target string, objectName string, useQt6 bool) string {
if useQt6 {
// return `ui.` + target + `.SetObjectName(*qt.NewQAnyStringView3(` + strconv.Quote(objectName) + "))\n"
spn := target + "__objectName"
ret := spn + `:= qt.NewQAnyStringView3(` + strconv.Quote(objectName) + ")\n"
ret += `ui.` + target + ".SetObjectName(*" + spn + ")\n"
ret += spn + ".Delete() // setter copied value\n"
return ret
} else {
return `ui.` + target + `.SetObjectName(` + strconv.Quote(objectName) + ")\n"
}
}
func assignWidgetToLayout(ret *strings.Builder, l *UiLayout, child *UiLayoutItem, noun string, widgetName string) {
switch l.Class {
case `QFormLayout`:
// Row and Column are always populated.
rowPos := fmt.Sprintf("%d", *child.Row)
var colPos string
if *child.Column == 0 {
colPos = `qt.QFormLayout__LabelRole`
} else if *child.Column == 1 {
colPos = `qt.QFormLayout__FieldRole`
} else {
ret.WriteString("/* miqt-uic: QFormLayout does not understand column index */\n")
return
}
// For QFormLayout it's SetWidget
ret.WriteString(`
ui.` + l.Name + `.Set` + noun + `(` + rowPos + `, ` + colPos + `, ` + widgetName + `)
`)
case `QGridLayout`:
if child.ColSpan != nil || child.RowSpan != nil {
// If either are present, use full four-value AddWidget3
rowSpan := 1
if child.RowSpan != nil {
rowSpan = *child.RowSpan
}
colSpan := 1
if child.ColSpan != nil {
colSpan = *child.ColSpan
}
if noun == "Widget" {
noun += "3"
} else if noun == "Layout" {
noun += "2"
}
ret.WriteString(`
ui.` + l.Name + `.Add` + noun + `(` + widgetName + `, ` + fmt.Sprintf("%d, %d, %d, %d", *child.Row, *child.Column, rowSpan, colSpan) + `)
`)
} else {
// Row and Column are always present in the .ui file
// For row/column it's AddWidget2
if noun == "Widget" {
noun += "2"
} else if noun == "Layout" {
// no suffix
}
ret.WriteString(`
ui.` + l.Name + `.Add` + noun + `(` + widgetName + `, ` + fmt.Sprintf("%d, %d", *child.Row, *child.Column) + `)
`)
}
case "QVBoxLayout", "QHBoxLayout":
// For box layout it's AddWidget
ret.WriteString(`
ui.` + l.Name + `.Add` + noun + `(` + widgetName + `)
`)
default:
ret.WriteString("/* miqt-uic: no handler for layout '" + l.Class + "' */\n")
}
}
func generateLayout(l *UiLayout, parentName string, parentClass string, useQt6 bool, isNestedLayout bool) (string, error) {
var ret strings.Builder
if isNestedLayout {
ctor := "New" + l.Class + "2"
ret.WriteString(`ui.` + l.Name + ` = qt.` + ctor + "()\n")
} else {
ctor := "New" + l.Class
ret.WriteString(`ui.` + l.Name + ` = qt.` + ctor + `(` + qwidgetName(parentName, parentClass) + ")\n")
}
ret.WriteString(generateSetObjectName(l.Name, l.Name, useQt6))
// Layout->Properties
err := renderProperties(l.Properties, &ret, l.Name, parentClass, true) // Always emit spacing/padding calls
if err != nil {
return "", err
}
// Layout->Items
for i, child := range l.Items {
// A layout item is either a widget, or a spacer, or another layout
if child.Spacer != nil {
ret.WriteString("/* miqt-uic: no handler for spacer */\n")
}
//
if child.Widget != nil {
// Layout items have the parent as the real QWidget parent and are
// separately assigned to the layout afterwards
nest, err := generateWidget(*child.Widget, parentName, parentClass, useQt6)
if err != nil {
return "", fmt.Errorf(l.Name+"/Layout/Item[%d]: %w", i, err)
}
ret.WriteString(nest)
// Assign to layout
assignWidgetToLayout(&ret, l, &child, "Widget", qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class))
}
//
if child.Layout != nil {
nest, err := generateLayout(child.Layout, parentName, parentClass, useQt6, true) // nested
if err != nil {
return "", fmt.Errorf(l.Name+"/Layout/Item[%d]: %w", i, err)
}
ret.WriteString(nest)
// Assign to layout
assignWidgetToLayout(&ret, l, &child, "Layout", `ui.`+child.Layout.Name+`.QLayout`)
}
//
}
return ret.String(), nil
}
func generateWidget(w UiWidget, parentName string, parentClass string, useQt6 bool) (string, error) {
ret := strings.Builder{}
ctor := "New" + w.Class
ret.WriteString(`
ui.` + w.Name + ` = qt.` + ctor + `(` + qwidgetName(parentName, parentClass) + `)
ui.` + w.Name + `.SetObjectName(` + strconv.Quote(w.Name) + `)
`)
ret.WriteString(`ui.` + w.Name + ` = qt.` + ctor + `(` + qwidgetName(parentName, parentClass) + ")\n")
ret.WriteString(generateSetObjectName(w.Name, w.Name, useQt6))
if RootWindowName == "" {
RootWindowName = `ui.` + w.Name
}
@ -244,109 +439,19 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
// Layout
if w.Layout != nil {
ctor := "New" + w.Layout.Class
ret.WriteString(`
ui.` + w.Layout.Name + ` = qt.` + ctor + `(` + qwidgetName("ui."+w.Name, w.Class) + `)
ui.` + w.Layout.Name + `.SetObjectName(` + strconv.Quote(w.Layout.Name) + `)
`)
// Layout->Properties
err := renderProperties(w.Layout.Properties, &ret, w.Layout.Name, parentClass, true) // Always emit spacing/padding calls
nest, err := generateLayout(w.Layout, `ui.`+w.Name, w.Class, useQt6, false)
if err != nil {
return "", err
}
// Layout->Items
for i, child := range w.Layout.Items {
// A layout item is either a widget, or a spacer
if child.Spacer != nil {
ret.WriteString("/* miqt-uic: no handler for spacer */\n")
}
if child.Widget != nil {
// Layout items have the parent as the real QWidget parent and are
// separately assigned to the layout afterwards
nest, err := generateWidget(*child.Widget, `ui.`+w.Name, w.Class)
if err != nil {
return "", fmt.Errorf(w.Name+"/Layout/Item[%d]: %w", i, err)
}
ret.WriteString(nest)
// Assign to layout
switch w.Layout.Class {
case `QFormLayout`:
// Row and Column are always populated.
rowPos := fmt.Sprintf("%d", *child.Row)
var colPos string
if *child.Column == 0 {
colPos = `qt.QFormLayout__LabelRole`
} else if *child.Column == 1 {
colPos = `qt.QFormLayout__FieldRole`
} else {
ret.WriteString("/* miqt-uic: QFormLayout does not understand column index */\n")
continue
}
// For QFormLayout it's SetWidget
ret.WriteString(`
ui.` + w.Layout.Name + `.SetWidget(` + rowPos + `, ` + colPos + `, ` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `)
`)
case `QGridLayout`:
if child.ColSpan != nil || child.RowSpan != nil {
// If either are present, use full four-value AddWidget3
rowSpan := 1
if child.RowSpan != nil {
rowSpan = *child.RowSpan
}
colSpan := 1
if child.ColSpan != nil {
colSpan = *child.ColSpan
}
ret.WriteString(`
ui.` + w.Layout.Name + `.AddWidget3(` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `, ` + fmt.Sprintf("%d, %d, %d, %d", *child.Row, *child.Column, rowSpan, colSpan) + `)
`)
} else {
// Row and Column are always present in the .ui file
// For row/column it's AddWidget2
ret.WriteString(`
ui.` + w.Layout.Name + `.AddWidget2(` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `, ` + fmt.Sprintf("%d, %d", *child.Row, *child.Column) + `)
`)
}
case "QVBoxLayout", "QHBoxLayout":
// For box layout it's AddWidget
ret.WriteString(`
ui.` + w.Layout.Name + `.AddWidget(` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `)
`)
default:
ret.WriteString("/* miqt-uic: no handler for layout '" + w.Layout.Class + "' */\n")
}
}
}
ret.WriteString(nest)
}
// Actions
for _, a := range w.Actions {
ret.WriteString(`
ui.` + a.Name + ` = qt.NewQAction(` + parentName + `)
ui.` + a.Name + `.SetObjectName(` + strconv.Quote(a.Name) + `)
`)
ret.WriteString(`ui.` + a.Name + ` = qt.NewQAction(` + parentName + ")\n")
ret.WriteString(generateSetObjectName(a.Name, a.Name, useQt6))
// QActions are translated in the parent window's context
if prop, ok := propertyByName(a.Properties, "text"); ok {
@ -403,7 +508,7 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
)
for i, child := range w.Widgets {
nest, err := generateWidget(child, `ui.`+w.Name, w.Class)
nest, err := generateWidget(child, `ui.`+w.Name, w.Class, useQt6)
if err != nil {
return "", fmt.Errorf(w.Name+"/Widgets[%d]: %w", i, err)
}
@ -471,10 +576,19 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
if w.Class == "QMenuBar" {
ret.WriteString("ui." + w.Name + ".AddMenu(ui." + a.Name + ")\n")
} else if w.Class == "QMenu" || w.Class == "QToolBar" {
// QMenu has its own .AddAction() implementation that takes plain string
// That's convenient, but it shadows the AddAction version that takes a QAction*
// We need to use the underlying QWidget.AddAction explicitly
ret.WriteString("ui." + w.Name + ".QWidget.AddAction(ui." + a.Name + ")\n")
// It's possible this is a nested menu, then we need to call AddMenu insted
// Resolve the class type of a.Name
if aClass, ok := trackWidgetClasses[a.Name]; ok && aClass == "QMenu" {
// Nested
ret.WriteString("ui." + w.Name + ".AddMenu(ui." + a.Name + ")\n")
} else {
// QMenu has its own .AddAction() implementation that takes plain string
// That's convenient, but it shadows the AddAction version that takes a QAction*
// We need to use the underlying QWidget.AddAction explicitly
ret.WriteString("ui." + w.Name + ".QWidget.AddAction(ui." + a.Name + ")\n")
}
} else {
ret.WriteString("ui." + w.Name + ".AddAction(ui." + a.Name + ")\n")
}
@ -492,6 +606,7 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
func generate(packageName string, goGenerateArgs string, u UiFile, useQt6 bool) ([]byte, error) {
trackWidgetClasses = make(map[string]string)
ret := strings.Builder{}
// Update globals for layoutdefault, if present
@ -532,7 +647,7 @@ func New` + u.Class + `Ui() *` + u.Class + `Ui {
ui := &` + u.Class + `Ui{}
`)
nest, err := generateWidget(u.Widget, "", "")
nest, err := generateWidget(u.Widget, "", "", useQt6)
if err != nil {
return nil, err
}

View File

@ -8,6 +8,7 @@ To specify the CFLAGS/CXXFLAGS and LDFLAGS for a specific library, make a `MyLib
```pkgconfig
Name: My Library
Requires: Qt6Widgets
Libs: -lfoo
Cflags: -I/path/
```
@ -16,6 +17,8 @@ Then run `PKG_CONFIG_PATH=/path/to/dir/ go build` so CGO will find your library.
The `PKG_CONFIG_PATH` environment variable is understood both by CGO and by genbindings.
When running genbindings in the docker/genbindings container, custom pkg-config files are created inline in the Dockerfile.
## Further reading
- [Guide to pkg-config](https://people.freedesktop.org/~dbn/pkg-config-guide.html)
@ -25,3 +28,23 @@ The `PKG_CONFIG_PATH` environment variable is understood both by CGO and by genb
$ pkg-config --variable pc_path pkg-config
/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
```
List all available packages known to pkg-config:
```bash
pkg-config --list-all
```
A full example for QScintilla (Qt 5) from the [genbindings.Dockerfile](../docker/genbindings.Dockerfile):
```pkg-config
includedir=/usr/include/x86_64-linux-gnu/qt5/Qsci/
Name: QScintilla
Description: Qt5 port of the Scintilla source code editing widget
URL: http://www.riverbankcomputing.co.uk/software/qscintilla
Version: 2.13.3
Requires: Qt5Widgets, Qt5PrintSupport
Libs: -lqscintilla2_qt5
Cflags: -I${includedir}
```

View File

@ -4,9 +4,6 @@ RUN wget 'https://go.dev/dl/go1.23.1.linux-amd64.tar.gz' && \
tar x -C /usr/local/ -f go1.23.1.linux-amd64.tar.gz && \
rm go1.23.1.linux-amd64.tar.gz
COPY cmd/android-stub-gen/android-stub-gen.sh /usr/local/bin/android-stub-gen.sh
COPY cmd/android-mktemplate/android-mktemplate.sh /usr/local/bin/android-mktemplate.sh
ENV PATH=/usr/local/go/bin:/opt/cmake/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/Qt-5.15.13/bin:/opt/android-sdk/cmdline-tools/tools/bin:/opt/android-sdk/tools:/opt/android-sdk/tools/bin:/opt/android-sdk/platform-tools
# The pkg-config definitions were all installed with platform-specific suffixes
@ -14,6 +11,10 @@ ENV PATH=/usr/local/go/bin:/opt/cmake/bin:/usr/local/sbin:/usr/local/bin:/usr/sb
# This container is targeting armv8-a, so set up simple symlinks
RUN /bin/bash -c 'cd /usr/local/Qt-5.15.13/lib/pkgconfig ; for f in *_arm64-v8a.pc ; do cp $f "$(basename -s _arm64-v8a.pc "$f").pc"; done'
# This is gross but (A) it's containerized and (B) allows --uid=1000 to perform builds
# Only needed for certain problematic versions of the Android SDK; a readonly SDK works in both older+newer SDKs
RUN /bin/bash -c 'find /opt/android-sdk/ -type d -exec chmod 777 {} \; && find /opt/android-sdk/ -perm 660 -exec chmod 666 {} \;'
ENV CC=/opt/android-sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang
ENV CXX=/opt/android-sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++
ENV CGO_ENABLED=1

View File

@ -9,9 +9,6 @@ RUN wget 'https://go.dev/dl/go1.23.6.linux-amd64.tar.gz' && \
tar x -C /usr/local/ -f go1.23.6.linux-amd64.tar.gz && \
rm go1.23.6.linux-amd64.tar.gz
COPY cmd/android-stub-gen/android-stub-gen.sh /usr/local/bin/android-stub-gen.sh
COPY cmd/android-mktemplate/android-mktemplate.sh /usr/local/bin/android-mktemplate.sh
# Fix up pkg-config definitions:
# 1. There are only pkg-config definitions included for gcc_64 (Linux native), not for the android_arm64_v8a target we actually want
# 2. It looks for `Libs: -L${libdir} -lQt6Widgets` but the file is named libQt6Widgets_arm64-v8a.so

16
docker/embed.go Normal file
View File

@ -0,0 +1,16 @@
// This Go file exports all the *.Dockerfile files for miqt-docker to use.
package docker
import (
"embed"
)
//go:embed *.Dockerfile
var Dockerfiles embed.FS
// ReadFile returns the content of one of the dockerfiles.
// That's because an embed.FS appears out-of-package as a []fs.DirEntry, which
// isn't directly readable.
func ReadFile(name string) ([]byte, error) {
return Dockerfiles.ReadFile(name)
}

View File

@ -5,6 +5,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
golang-go \
qtbase5-dev \
qtmultimedia5-dev \
qtpdf5-dev \
qtscript5-dev \
libqt5svg5-dev \
libqt5webkit5-dev \
@ -13,6 +14,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
qt6-charts-dev \
qt6-declarative-dev \
qt6-multimedia-dev \
qt6-pdf-dev \
qt6-svg-dev \
qt6-webengine-dev \
libqscintilla2-qt5-dev \
@ -37,10 +39,43 @@ RUN \
qmake && \
make
# Custom pkg-config definitions
RUN mkdir -p /usr/local/lib/pkgconfig
COPY pkg-config/QScintilla.pc.example /usr/local/lib/pkgconfig/QScintilla.pc
COPY pkg-config/QScintilla6.pc.example /usr/local/lib/pkgconfig/QScintilla6.pc
COPY pkg-config/ScintillaEdit.pc.example /usr/local/lib/pkgconfig/ScintillaEdit.pc
RUN echo 'includedir=/usr/include/x86_64-linux-gnu/qt5/Qsci/' \
'\n' \
'\nName: QScintilla' \
'\nDescription: Qt5 port of the Scintilla source code editing widget' \
'\nURL: http://www.riverbankcomputing.co.uk/software/qscintilla' \
'\nVersion: 2.13.3' \
'\nRequires: Qt5Widgets, Qt5PrintSupport' \
'\nLibs: -lqscintilla2_qt5' \
'\nCflags: -I${includedir}' \
> /usr/local/lib/pkgconfig/QScintilla.pc
RUN echo 'includedir=/usr/include/x86_64-linux-gnu/qt6/Qsci/' \
'\n' \
'\nName: QScintilla6' \
'\nDescription: Qt6 port of the Scintilla source code editing widget' \
'\nURL: http://www.riverbankcomputing.co.uk/software/qscintilla' \
'\nVersion: 2.13.3' \
'\nRequires: Qt6Widgets, Qt6PrintSupport' \
'\nLibs: -lqscintilla2_qt6' \
'\nCflags: -I${includedir}' \
> /usr/local/lib/pkgconfig/QScintilla6.pc
RUN echo 'srcdir=/usr/local/src/scintilla/' \
'\n' \
'\nName: ScintillaEdit' \
'\nDescription: Scintilla upstream Qt port' \
'\nURL: https://www.scintilla.org/' \
'\nVersion: 5.5.2' \
'\nRequires: Qt5Widgets' \
'\nLibs: -L${srcdir}/bin -lScintillaEdit' \
'\nCflags: -include stdint.h -I${srcdir}/qt/ScintillaEdit -I${srcdir}/qt/ScintillaEditBase -I${srcdir}/include -I${srcdir}/src' \
> /usr/local/lib/pkgconfig/ScintillaEdit.pc
#
ENV GOFLAGS=-buildvcs=false

View File

@ -1,29 +0,0 @@
package main
import (
"fmt"
"os"
"github.com/mappu/miqt/qt"
)
func myRealMainFunc() {
qt.NewQApplication(os.Args)
btn := qt.NewQPushButton3("Hello world!")
btn.SetFixedWidth(320)
var counter int = 0
btn.OnPressed(func() {
counter++
btn.SetText(fmt.Sprintf("You have clicked the button %d time(s)", counter))
})
btn.Show()
qt.QApplication_Exec()
fmt.Println("OK!")
}

View File

@ -1,14 +0,0 @@
// +build android
package main
import "C" // Required for export support
//export AndroidMain
func AndroidMain() {
myRealMainFunc()
}
func main() {
// Must be empty
}

View File

@ -1,7 +0,0 @@
// +build !android
package main
func main() {
myRealMainFunc()
}

View File

@ -1,29 +0,0 @@
package main
import (
"fmt"
"os"
qt "github.com/mappu/miqt/qt6"
)
func myRealMainFunc() {
qt.NewQApplication(os.Args)
btn := qt.NewQPushButton3("Hello world!")
btn.SetFixedWidth(320)
var counter int = 0
btn.OnPressed(func() {
counter++
btn.SetText(fmt.Sprintf("You have clicked the button %d time(s)", counter))
})
btn.Show()
qt.QApplication_Exec()
fmt.Println("OK!")
}

View File

@ -1,14 +0,0 @@
// +build android
package main
import "C" // Required for export support
//export AndroidMain
func AndroidMain() {
myRealMainFunc()
}
func main() {
// Must be empty
}

View File

@ -1,7 +0,0 @@
// +build !android
package main
func main() {
myRealMainFunc()
}

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,52 @@
package main
import (
"os"
"strings"
qt "github.com/mappu/miqt/qt6"
)
func main() {
qt.NewQApplication(os.Args)
widget := qt.NewQWidget2()
defer widget.Delete()
widget.SetWindowTitle("Qt 6 LCD Clock Example")
widget.Resize(360, 240)
hbox := qt.NewQHBoxLayout(widget)
lcd := qt.NewQLCDNumber(widget)
lcd.SetStyleSheet("background-color: #729fcf; color: white;")
time := qt.QTime_CurrentTime()
defer time.Delete()
text := time.ToStringWithFormat("hh:mm")
if (time.Second() % 2) == 0 {
text = strings.Replace(text, ":", " ", -1)
}
lcd.Display(text)
hbox.AddWidget(lcd.QFrame.QWidget)
timer := qt.NewQTimer2(widget.QObject)
timer.Start(1000)
timer.OnTimeout(func() {
time := qt.QTime_CurrentTime()
defer time.Delete()
text := time.ToStringWithFormat("hh:mm")
if (time.Second() % 2) == 0 {
text = strings.Replace(text, ":", " ", -1)
}
lcd.Display(text)
})
widget.Show()
qt.QApplication_Exec()
}

Binary file not shown.

View File

@ -0,0 +1,27 @@
package main
import (
"os"
"github.com/mappu/miqt/qt"
"github.com/mappu/miqt/qt/pdf"
)
func main() {
qt.NewQApplication(os.Args)
d := pdf.NewQPdfDocument()
d.Load("example.pdf")
p := pdf.NewQPdfView2()
p.SetWindowTitle("Qt 5 PDF Example")
p.SetMinimumSize2(650, 600)
p.SetPageMode(pdf.QPdfView__MultiPage)
p.SetZoomMode(pdf.QPdfView__FitInView)
p.SetDocument(d)
p.Show()
qt.QApplication_Exec()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

View File

@ -0,0 +1,27 @@
package main
import (
"os"
qt "github.com/mappu/miqt/qt6"
"github.com/mappu/miqt/qt6/pdf"
)
func main() {
qt.NewQApplication(os.Args)
d := pdf.NewQPdfDocument()
d.Load("example.pdf")
p := pdf.NewQPdfView2()
p.SetWindowTitle("Qt 6 PDF Example")
p.SetMinimumSize2(650, 600)
p.SetPageMode(pdf.QPdfView__MultiPage)
p.SetZoomMode(pdf.QPdfView__FitInView)
p.SetDocument(d)
p.Show()
qt.QApplication_Exec()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,9 +0,0 @@
includedir=/usr/include/x86_64-linux-gnu/qt5/Qsci/
Name: QScintilla
Description: Qt5 port of the Scintilla source code editing widget
URL: http://www.riverbankcomputing.co.uk/software/qscintilla
Version: 2.13.3
Requires: Qt5Widgets, Qt5PrintSupport
Libs: -lqscintilla2_qt5
Cflags: -I${includedir}

View File

@ -1,9 +0,0 @@
includedir=/usr/include/x86_64-linux-gnu/qt6/Qsci/
Name: QScintilla6
Description: Qt6 port of the Scintilla source code editing widget
URL: http://www.riverbankcomputing.co.uk/software/qscintilla
Version: 2.13.3
Requires: Qt6Widgets, Qt6PrintSupport
Libs: -lqscintilla2_qt6
Cflags: -I${includedir}

View File

@ -1,9 +0,0 @@
srcdir=/usr/local/src/scintilla/
Name: ScintillaEdit
Description: Scintilla's own upstream Qt port
URL: https://www.scintilla.org/
Version: 5.5.2
Requires: Qt5Widgets
Libs: -L${srcdir}/bin -lScintillaEdit
Cflags: -include stdint.h -I${srcdir}/qt/ScintillaEdit -I${srcdir}/qt/ScintillaEditBase -I${srcdir}/include -I${srcdir}/src

View File

@ -37,6 +37,20 @@ void miqt_exec_callback_QAbstractItemModel_layoutChangedWithParents(intptr_t, st
void miqt_exec_callback_QAbstractItemModel_layoutChanged2(intptr_t, struct miqt_array /* of QPersistentModelIndex* */ , int);
void miqt_exec_callback_QAbstractItemModel_layoutAboutToBeChangedWithParents(intptr_t, struct miqt_array /* of QPersistentModelIndex* */ );
void miqt_exec_callback_QAbstractItemModel_layoutAboutToBeChanged2(intptr_t, struct miqt_array /* of QPersistentModelIndex* */ , int);
void miqt_exec_callback_QAbstractItemModel_rowsAboutToBeInserted(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_rowsInserted(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_rowsAboutToBeRemoved(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_rowsRemoved(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_columnsAboutToBeInserted(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_columnsInserted(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_columnsAboutToBeRemoved(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_columnsRemoved(intptr_t, QModelIndex*, int, int);
void miqt_exec_callback_QAbstractItemModel_modelAboutToBeReset(intptr_t);
void miqt_exec_callback_QAbstractItemModel_modelReset(intptr_t);
void miqt_exec_callback_QAbstractItemModel_rowsAboutToBeMoved(intptr_t, QModelIndex*, int, int, QModelIndex*, int);
void miqt_exec_callback_QAbstractItemModel_rowsMoved(intptr_t, QModelIndex*, int, int, QModelIndex*, int);
void miqt_exec_callback_QAbstractItemModel_columnsAboutToBeMoved(intptr_t, QModelIndex*, int, int, QModelIndex*, int);
void miqt_exec_callback_QAbstractItemModel_columnsMoved(intptr_t, QModelIndex*, int, int, QModelIndex*, int);
QModelIndex* miqt_exec_callback_QAbstractItemModel_index(const QAbstractItemModel*, intptr_t, int, int, QModelIndex*);
QModelIndex* miqt_exec_callback_QAbstractItemModel_parent(const QAbstractItemModel*, intptr_t, QModelIndex*);
QModelIndex* miqt_exec_callback_QAbstractItemModel_sibling(const QAbstractItemModel*, intptr_t, int, int, QModelIndex*);
@ -2892,6 +2906,166 @@ bool QAbstractItemModel_protectedbase_isSignalConnected(bool* _dynamic_cast_ok,
}
void QAbstractItemModel_connect_rowsAboutToBeInserted(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsAboutToBeInserted, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_rowsAboutToBeInserted(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_rowsInserted(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsInserted, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_rowsInserted(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_rowsAboutToBeRemoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsAboutToBeRemoved, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_rowsAboutToBeRemoved(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_rowsRemoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsRemoved, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_rowsRemoved(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_columnsAboutToBeInserted(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsAboutToBeInserted, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_columnsAboutToBeInserted(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_columnsInserted(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsInserted, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_columnsInserted(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_columnsAboutToBeRemoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsAboutToBeRemoved, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_columnsAboutToBeRemoved(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_columnsRemoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsRemoved, self, [=](const QModelIndex& parent, int first, int last) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = first;
int sigval3 = last;
miqt_exec_callback_QAbstractItemModel_columnsRemoved(slot, sigval1, sigval2, sigval3);
});
}
void QAbstractItemModel_connect_modelAboutToBeReset(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::modelAboutToBeReset, self, [=]() {
miqt_exec_callback_QAbstractItemModel_modelAboutToBeReset(slot);
});
}
void QAbstractItemModel_connect_modelReset(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::modelReset, self, [=]() {
miqt_exec_callback_QAbstractItemModel_modelReset(slot);
});
}
void QAbstractItemModel_connect_rowsAboutToBeMoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsAboutToBeMoved, self, [=](const QModelIndex& sourceParent, int sourceStart, int sourceEnd, const QModelIndex& destinationParent, int destinationRow) {
const QModelIndex& sourceParent_ret = sourceParent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&sourceParent_ret);
int sigval2 = sourceStart;
int sigval3 = sourceEnd;
const QModelIndex& destinationParent_ret = destinationParent;
// Cast returned reference into pointer
QModelIndex* sigval4 = const_cast<QModelIndex*>(&destinationParent_ret);
int sigval5 = destinationRow;
miqt_exec_callback_QAbstractItemModel_rowsAboutToBeMoved(slot, sigval1, sigval2, sigval3, sigval4, sigval5);
});
}
void QAbstractItemModel_connect_rowsMoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::rowsMoved, self, [=](const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = start;
int sigval3 = end;
const QModelIndex& destination_ret = destination;
// Cast returned reference into pointer
QModelIndex* sigval4 = const_cast<QModelIndex*>(&destination_ret);
int sigval5 = row;
miqt_exec_callback_QAbstractItemModel_rowsMoved(slot, sigval1, sigval2, sigval3, sigval4, sigval5);
});
}
void QAbstractItemModel_connect_columnsAboutToBeMoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsAboutToBeMoved, self, [=](const QModelIndex& sourceParent, int sourceStart, int sourceEnd, const QModelIndex& destinationParent, int destinationColumn) {
const QModelIndex& sourceParent_ret = sourceParent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&sourceParent_ret);
int sigval2 = sourceStart;
int sigval3 = sourceEnd;
const QModelIndex& destinationParent_ret = destinationParent;
// Cast returned reference into pointer
QModelIndex* sigval4 = const_cast<QModelIndex*>(&destinationParent_ret);
int sigval5 = destinationColumn;
miqt_exec_callback_QAbstractItemModel_columnsAboutToBeMoved(slot, sigval1, sigval2, sigval3, sigval4, sigval5);
});
}
void QAbstractItemModel_connect_columnsMoved(QAbstractItemModel* self, intptr_t slot) {
MiqtVirtualQAbstractItemModel::connect(self, &QAbstractItemModel::columnsMoved, self, [=](const QModelIndex& parent, int start, int end, const QModelIndex& destination, int column) {
const QModelIndex& parent_ret = parent;
// Cast returned reference into pointer
QModelIndex* sigval1 = const_cast<QModelIndex*>(&parent_ret);
int sigval2 = start;
int sigval3 = end;
const QModelIndex& destination_ret = destination;
// Cast returned reference into pointer
QModelIndex* sigval4 = const_cast<QModelIndex*>(&destination_ret);
int sigval5 = column;
miqt_exec_callback_QAbstractItemModel_columnsMoved(slot, sigval1, sigval2, sigval3, sigval4, sigval5);
});
}
void QAbstractItemModel_delete(QAbstractItemModel* self) {
delete self;
}

View File

@ -2670,6 +2670,301 @@ func miqt_exec_callback_QAbstractItemModel_disconnectNotify(self *C.QAbstractIte
gofunc((&QAbstractItemModel{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QAbstractItemModel) OnRowsAboutToBeInserted(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_rowsAboutToBeInserted(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsAboutToBeInserted
func miqt_exec_callback_QAbstractItemModel_rowsAboutToBeInserted(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnRowsInserted(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_rowsInserted(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsInserted
func miqt_exec_callback_QAbstractItemModel_rowsInserted(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnRowsAboutToBeRemoved(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_rowsAboutToBeRemoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsAboutToBeRemoved
func miqt_exec_callback_QAbstractItemModel_rowsAboutToBeRemoved(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnRowsRemoved(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_rowsRemoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsRemoved
func miqt_exec_callback_QAbstractItemModel_rowsRemoved(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnColumnsAboutToBeInserted(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_columnsAboutToBeInserted(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsAboutToBeInserted
func miqt_exec_callback_QAbstractItemModel_columnsAboutToBeInserted(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnColumnsInserted(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_columnsInserted(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsInserted
func miqt_exec_callback_QAbstractItemModel_columnsInserted(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnColumnsAboutToBeRemoved(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_columnsAboutToBeRemoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsAboutToBeRemoved
func miqt_exec_callback_QAbstractItemModel_columnsAboutToBeRemoved(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnColumnsRemoved(slot func(parent *QModelIndex, first int, last int)) {
C.QAbstractItemModel_connect_columnsRemoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsRemoved
func miqt_exec_callback_QAbstractItemModel_columnsRemoved(cb C.intptr_t, parent *C.QModelIndex, first C.int, last C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, first int, last int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(first)
slotval3 := (int)(last)
gofunc(slotval1, slotval2, slotval3)
}
func (this *QAbstractItemModel) OnModelAboutToBeReset(slot func()) {
C.QAbstractItemModel_connect_modelAboutToBeReset(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_modelAboutToBeReset
func miqt_exec_callback_QAbstractItemModel_modelAboutToBeReset(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QAbstractItemModel) OnModelReset(slot func()) {
C.QAbstractItemModel_connect_modelReset(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_modelReset
func miqt_exec_callback_QAbstractItemModel_modelReset(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QAbstractItemModel) OnRowsAboutToBeMoved(slot func(sourceParent *QModelIndex, sourceStart int, sourceEnd int, destinationParent *QModelIndex, destinationRow int)) {
C.QAbstractItemModel_connect_rowsAboutToBeMoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsAboutToBeMoved
func miqt_exec_callback_QAbstractItemModel_rowsAboutToBeMoved(cb C.intptr_t, sourceParent *C.QModelIndex, sourceStart C.int, sourceEnd C.int, destinationParent *C.QModelIndex, destinationRow C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(sourceParent *QModelIndex, sourceStart int, sourceEnd int, destinationParent *QModelIndex, destinationRow int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(sourceParent)
slotval2 := (int)(sourceStart)
slotval3 := (int)(sourceEnd)
slotval4 := newQModelIndex(destinationParent)
slotval5 := (int)(destinationRow)
gofunc(slotval1, slotval2, slotval3, slotval4, slotval5)
}
func (this *QAbstractItemModel) OnRowsMoved(slot func(parent *QModelIndex, start int, end int, destination *QModelIndex, row int)) {
C.QAbstractItemModel_connect_rowsMoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_rowsMoved
func miqt_exec_callback_QAbstractItemModel_rowsMoved(cb C.intptr_t, parent *C.QModelIndex, start C.int, end C.int, destination *C.QModelIndex, row C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, start int, end int, destination *QModelIndex, row int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(start)
slotval3 := (int)(end)
slotval4 := newQModelIndex(destination)
slotval5 := (int)(row)
gofunc(slotval1, slotval2, slotval3, slotval4, slotval5)
}
func (this *QAbstractItemModel) OnColumnsAboutToBeMoved(slot func(sourceParent *QModelIndex, sourceStart int, sourceEnd int, destinationParent *QModelIndex, destinationColumn int)) {
C.QAbstractItemModel_connect_columnsAboutToBeMoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsAboutToBeMoved
func miqt_exec_callback_QAbstractItemModel_columnsAboutToBeMoved(cb C.intptr_t, sourceParent *C.QModelIndex, sourceStart C.int, sourceEnd C.int, destinationParent *C.QModelIndex, destinationColumn C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(sourceParent *QModelIndex, sourceStart int, sourceEnd int, destinationParent *QModelIndex, destinationColumn int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(sourceParent)
slotval2 := (int)(sourceStart)
slotval3 := (int)(sourceEnd)
slotval4 := newQModelIndex(destinationParent)
slotval5 := (int)(destinationColumn)
gofunc(slotval1, slotval2, slotval3, slotval4, slotval5)
}
func (this *QAbstractItemModel) OnColumnsMoved(slot func(parent *QModelIndex, start int, end int, destination *QModelIndex, column int)) {
C.QAbstractItemModel_connect_columnsMoved(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractItemModel_columnsMoved
func miqt_exec_callback_QAbstractItemModel_columnsMoved(cb C.intptr_t, parent *C.QModelIndex, start C.int, end C.int, destination *C.QModelIndex, column C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(parent *QModelIndex, start int, end int, destination *QModelIndex, column int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := newQModelIndex(parent)
slotval2 := (int)(start)
slotval3 := (int)(end)
slotval4 := newQModelIndex(destination)
slotval5 := (int)(column)
gofunc(slotval1, slotval2, slotval3, slotval4, slotval5)
}
// Delete this object from C++ memory.
func (this *QAbstractItemModel) Delete() {

View File

@ -281,6 +281,20 @@ QObject* QAbstractItemModel_protectedbase_sender(bool* _dynamic_cast_ok, const v
int QAbstractItemModel_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QAbstractItemModel_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QAbstractItemModel_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QAbstractItemModel_connect_rowsAboutToBeInserted(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_rowsInserted(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_rowsAboutToBeRemoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_rowsRemoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsAboutToBeInserted(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsInserted(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsAboutToBeRemoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsRemoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_modelAboutToBeReset(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_modelReset(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_rowsAboutToBeMoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_rowsMoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsAboutToBeMoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_connect_columnsMoved(QAbstractItemModel* self, intptr_t slot);
void QAbstractItemModel_delete(QAbstractItemModel* self);
QAbstractTableModel* QAbstractTableModel_new();

View File

@ -26,6 +26,7 @@
extern "C" {
#endif
void miqt_exec_callback_QAbstractProxyModel_sourceModelChanged(intptr_t);
void miqt_exec_callback_QAbstractProxyModel_setSourceModel(QAbstractProxyModel*, intptr_t, QAbstractItemModel*);
QModelIndex* miqt_exec_callback_QAbstractProxyModel_mapToSource(const QAbstractProxyModel*, intptr_t, QModelIndex*);
QModelIndex* miqt_exec_callback_QAbstractProxyModel_mapFromSource(const QAbstractProxyModel*, intptr_t, QModelIndex*);
@ -2468,6 +2469,12 @@ bool QAbstractProxyModel_protectedbase_isSignalConnected(bool* _dynamic_cast_ok,
}
void QAbstractProxyModel_connect_sourceModelChanged(QAbstractProxyModel* self, intptr_t slot) {
MiqtVirtualQAbstractProxyModel::connect(self, &QAbstractProxyModel::sourceModelChanged, self, [=]() {
miqt_exec_callback_QAbstractProxyModel_sourceModelChanged(slot);
});
}
void QAbstractProxyModel_delete(QAbstractProxyModel* self) {
delete self;
}

View File

@ -2108,6 +2108,19 @@ func miqt_exec_callback_QAbstractProxyModel_disconnectNotify(self *C.QAbstractPr
gofunc((&QAbstractProxyModel{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QAbstractProxyModel) OnSourceModelChanged(slot func()) {
C.QAbstractProxyModel_connect_sourceModelChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractProxyModel_sourceModelChanged
func miqt_exec_callback_QAbstractProxyModel_sourceModelChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QAbstractProxyModel) Delete() {

View File

@ -202,6 +202,7 @@ QObject* QAbstractProxyModel_protectedbase_sender(bool* _dynamic_cast_ok, const
int QAbstractProxyModel_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QAbstractProxyModel_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QAbstractProxyModel_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QAbstractProxyModel_connect_sourceModelChanged(QAbstractProxyModel* self, intptr_t slot);
void QAbstractProxyModel_delete(QAbstractProxyModel* self);
#ifdef __cplusplus

View File

@ -16,6 +16,8 @@ extern "C" {
#endif
void miqt_exec_callback_QAbstractState_activeChanged(intptr_t, bool);
void miqt_exec_callback_QAbstractState_entered(intptr_t);
void miqt_exec_callback_QAbstractState_exited(intptr_t);
#ifdef __cplusplus
} /* extern C */
#endif
@ -121,6 +123,18 @@ struct miqt_string QAbstractState_trUtf83(const char* s, const char* c, int n) {
return _ms;
}
void QAbstractState_connect_entered(QAbstractState* self, intptr_t slot) {
QAbstractState::connect(self, &QAbstractState::entered, self, [=]() {
miqt_exec_callback_QAbstractState_entered(slot);
});
}
void QAbstractState_connect_exited(QAbstractState* self, intptr_t slot) {
QAbstractState::connect(self, &QAbstractState::exited, self, [=]() {
miqt_exec_callback_QAbstractState_exited(slot);
});
}
void QAbstractState_delete(QAbstractState* self) {
delete self;
}

View File

@ -153,6 +153,33 @@ func QAbstractState_TrUtf83(s string, c string, n int) string {
C.free(unsafe.Pointer(_ms.data))
return _ret
}
func (this *QAbstractState) OnEntered(slot func()) {
C.QAbstractState_connect_entered(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractState_entered
func miqt_exec_callback_QAbstractState_entered(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QAbstractState) OnExited(slot func()) {
C.QAbstractState_connect_exited(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractState_exited
func miqt_exec_callback_QAbstractState_exited(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QAbstractState) Delete() {

View File

@ -49,6 +49,8 @@ struct miqt_string QAbstractState_tr2(const char* s, const char* c);
struct miqt_string QAbstractState_tr3(const char* s, const char* c, int n);
struct miqt_string QAbstractState_trUtf82(const char* s, const char* c);
struct miqt_string QAbstractState_trUtf83(const char* s, const char* c, int n);
void QAbstractState_connect_entered(QAbstractState* self, intptr_t slot);
void QAbstractState_connect_exited(QAbstractState* self, intptr_t slot);
void QAbstractState_delete(QAbstractState* self);
#ifdef __cplusplus

View File

@ -20,6 +20,9 @@
extern "C" {
#endif
void miqt_exec_callback_QAbstractTransition_triggered(intptr_t);
void miqt_exec_callback_QAbstractTransition_targetStateChanged(intptr_t);
void miqt_exec_callback_QAbstractTransition_targetStatesChanged(intptr_t);
bool miqt_exec_callback_QAbstractTransition_eventTest(QAbstractTransition*, intptr_t, QEvent*);
void miqt_exec_callback_QAbstractTransition_onTransition(QAbstractTransition*, intptr_t, QEvent*);
bool miqt_exec_callback_QAbstractTransition_event(QAbstractTransition*, intptr_t, QEvent*);
@ -555,6 +558,24 @@ bool QAbstractTransition_protectedbase_isSignalConnected(bool* _dynamic_cast_ok,
}
void QAbstractTransition_connect_triggered(QAbstractTransition* self, intptr_t slot) {
MiqtVirtualQAbstractTransition::connect(self, &QAbstractTransition::triggered, self, [=]() {
miqt_exec_callback_QAbstractTransition_triggered(slot);
});
}
void QAbstractTransition_connect_targetStateChanged(QAbstractTransition* self, intptr_t slot) {
MiqtVirtualQAbstractTransition::connect(self, &QAbstractTransition::targetStateChanged, self, [=]() {
miqt_exec_callback_QAbstractTransition_targetStateChanged(slot);
});
}
void QAbstractTransition_connect_targetStatesChanged(QAbstractTransition* self, intptr_t slot) {
MiqtVirtualQAbstractTransition::connect(self, &QAbstractTransition::targetStatesChanged, self, [=]() {
miqt_exec_callback_QAbstractTransition_targetStatesChanged(slot);
});
}
void QAbstractTransition_delete(QAbstractTransition* self) {
delete self;
}

View File

@ -490,6 +490,47 @@ func miqt_exec_callback_QAbstractTransition_disconnectNotify(self *C.QAbstractTr
gofunc((&QAbstractTransition{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QAbstractTransition) OnTriggered(slot func()) {
C.QAbstractTransition_connect_triggered(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractTransition_triggered
func miqt_exec_callback_QAbstractTransition_triggered(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QAbstractTransition) OnTargetStateChanged(slot func()) {
C.QAbstractTransition_connect_targetStateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractTransition_targetStateChanged
func miqt_exec_callback_QAbstractTransition_targetStateChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QAbstractTransition) OnTargetStatesChanged(slot func()) {
C.QAbstractTransition_connect_targetStatesChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QAbstractTransition_targetStatesChanged
func miqt_exec_callback_QAbstractTransition_targetStatesChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QAbstractTransition) Delete() {

View File

@ -87,6 +87,9 @@ QObject* QAbstractTransition_protectedbase_sender(bool* _dynamic_cast_ok, const
int QAbstractTransition_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QAbstractTransition_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QAbstractTransition_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QAbstractTransition_connect_triggered(QAbstractTransition* self, intptr_t slot);
void QAbstractTransition_connect_targetStateChanged(QAbstractTransition* self, intptr_t slot);
void QAbstractTransition_connect_targetStatesChanged(QAbstractTransition* self, intptr_t slot);
void QAbstractTransition_delete(QAbstractTransition* self);
#ifdef __cplusplus

View File

@ -23,6 +23,7 @@ void miqt_exec_callback_QCoreApplication_organizationNameChanged(intptr_t);
void miqt_exec_callback_QCoreApplication_organizationDomainChanged(intptr_t);
void miqt_exec_callback_QCoreApplication_applicationNameChanged(intptr_t);
void miqt_exec_callback_QCoreApplication_applicationVersionChanged(intptr_t);
void miqt_exec_callback_QCoreApplication_aboutToQuit(intptr_t);
bool miqt_exec_callback_QCoreApplication_notify(QCoreApplication*, intptr_t, QObject*, QEvent*);
bool miqt_exec_callback_QCoreApplication_event(QCoreApplication*, intptr_t, QEvent*);
bool miqt_exec_callback_QCoreApplication_eventFilter(QCoreApplication*, intptr_t, QObject*, QEvent*);
@ -832,6 +833,12 @@ bool QCoreApplication_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, co
}
void QCoreApplication_connect_aboutToQuit(QCoreApplication* self, intptr_t slot) {
MiqtVirtualQCoreApplication::connect(self, &QCoreApplication::aboutToQuit, self, [=]() {
miqt_exec_callback_QCoreApplication_aboutToQuit(slot);
});
}
void QCoreApplication_delete(QCoreApplication* self) {
delete self;
}

View File

@ -808,6 +808,19 @@ func miqt_exec_callback_QCoreApplication_disconnectNotify(self *C.QCoreApplicati
gofunc((&QCoreApplication{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QCoreApplication) OnAboutToQuit(slot func()) {
C.QCoreApplication_connect_aboutToQuit(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QCoreApplication_aboutToQuit
func miqt_exec_callback_QCoreApplication_aboutToQuit(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QCoreApplication) Delete() {

View File

@ -131,6 +131,7 @@ QObject* QCoreApplication_protectedbase_sender(bool* _dynamic_cast_ok, const voi
int QCoreApplication_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QCoreApplication_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QCoreApplication_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QCoreApplication_connect_aboutToQuit(QCoreApplication* self, intptr_t slot);
void QCoreApplication_delete(QCoreApplication* self);
#ifdef __cplusplus

View File

@ -16,6 +16,8 @@
extern "C" {
#endif
void miqt_exec_callback_QFileSystemWatcher_fileChanged(intptr_t, struct miqt_string);
void miqt_exec_callback_QFileSystemWatcher_directoryChanged(intptr_t, struct miqt_string);
bool miqt_exec_callback_QFileSystemWatcher_event(QFileSystemWatcher*, intptr_t, QEvent*);
bool miqt_exec_callback_QFileSystemWatcher_eventFilter(QFileSystemWatcher*, intptr_t, QObject*, QEvent*);
void miqt_exec_callback_QFileSystemWatcher_timerEvent(QFileSystemWatcher*, intptr_t, QTimerEvent*);
@ -556,6 +558,34 @@ bool QFileSystemWatcher_protectedbase_isSignalConnected(bool* _dynamic_cast_ok,
}
void QFileSystemWatcher_connect_fileChanged(QFileSystemWatcher* self, intptr_t slot) {
MiqtVirtualQFileSystemWatcher::connect(self, &QFileSystemWatcher::fileChanged, self, [=](const QString& path) {
const QString path_ret = path;
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
QByteArray path_b = path_ret.toUtf8();
struct miqt_string path_ms;
path_ms.len = path_b.length();
path_ms.data = static_cast<char*>(malloc(path_ms.len));
memcpy(path_ms.data, path_b.data(), path_ms.len);
struct miqt_string sigval1 = path_ms;
miqt_exec_callback_QFileSystemWatcher_fileChanged(slot, sigval1);
});
}
void QFileSystemWatcher_connect_directoryChanged(QFileSystemWatcher* self, intptr_t slot) {
MiqtVirtualQFileSystemWatcher::connect(self, &QFileSystemWatcher::directoryChanged, self, [=](const QString& path) {
const QString path_ret = path;
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
QByteArray path_b = path_ret.toUtf8();
struct miqt_string path_ms;
path_ms.len = path_b.length();
path_ms.data = static_cast<char*>(malloc(path_ms.len));
memcpy(path_ms.data, path_b.data(), path_ms.len);
struct miqt_string sigval1 = path_ms;
miqt_exec_callback_QFileSystemWatcher_directoryChanged(slot, sigval1);
});
}
void QFileSystemWatcher_delete(QFileSystemWatcher* self) {
delete self;
}

View File

@ -499,6 +499,45 @@ func miqt_exec_callback_QFileSystemWatcher_disconnectNotify(self *C.QFileSystemW
gofunc((&QFileSystemWatcher{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QFileSystemWatcher) OnFileChanged(slot func(path string)) {
C.QFileSystemWatcher_connect_fileChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QFileSystemWatcher_fileChanged
func miqt_exec_callback_QFileSystemWatcher_fileChanged(cb C.intptr_t, path C.struct_miqt_string) {
gofunc, ok := cgo.Handle(cb).Value().(func(path string))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
var path_ms C.struct_miqt_string = path
path_ret := C.GoStringN(path_ms.data, C.int(int64(path_ms.len)))
C.free(unsafe.Pointer(path_ms.data))
slotval1 := path_ret
gofunc(slotval1)
}
func (this *QFileSystemWatcher) OnDirectoryChanged(slot func(path string)) {
C.QFileSystemWatcher_connect_directoryChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QFileSystemWatcher_directoryChanged
func miqt_exec_callback_QFileSystemWatcher_directoryChanged(cb C.intptr_t, path C.struct_miqt_string) {
gofunc, ok := cgo.Handle(cb).Value().(func(path string))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
var path_ms C.struct_miqt_string = path
path_ret := C.GoStringN(path_ms.data, C.int(int64(path_ms.len)))
C.free(unsafe.Pointer(path_ms.data))
slotval1 := path_ret
gofunc(slotval1)
}
// Delete this object from C++ memory.
func (this *QFileSystemWatcher) Delete() {

View File

@ -69,6 +69,8 @@ QObject* QFileSystemWatcher_protectedbase_sender(bool* _dynamic_cast_ok, const v
int QFileSystemWatcher_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QFileSystemWatcher_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QFileSystemWatcher_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QFileSystemWatcher_connect_fileChanged(QFileSystemWatcher* self, intptr_t slot);
void QFileSystemWatcher_connect_directoryChanged(QFileSystemWatcher* self, intptr_t slot);
void QFileSystemWatcher_delete(QFileSystemWatcher* self);
#ifdef __cplusplus

View File

@ -18,6 +18,9 @@
extern "C" {
#endif
void miqt_exec_callback_QHistoryState_defaultTransitionChanged(intptr_t);
void miqt_exec_callback_QHistoryState_defaultStateChanged(intptr_t);
void miqt_exec_callback_QHistoryState_historyTypeChanged(intptr_t);
void miqt_exec_callback_QHistoryState_onEntry(QHistoryState*, intptr_t, QEvent*);
void miqt_exec_callback_QHistoryState_onExit(QHistoryState*, intptr_t, QEvent*);
bool miqt_exec_callback_QHistoryState_event(QHistoryState*, intptr_t, QEvent*);
@ -537,6 +540,24 @@ bool QHistoryState_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const
}
void QHistoryState_connect_defaultTransitionChanged(QHistoryState* self, intptr_t slot) {
MiqtVirtualQHistoryState::connect(self, &QHistoryState::defaultTransitionChanged, self, [=]() {
miqt_exec_callback_QHistoryState_defaultTransitionChanged(slot);
});
}
void QHistoryState_connect_defaultStateChanged(QHistoryState* self, intptr_t slot) {
MiqtVirtualQHistoryState::connect(self, &QHistoryState::defaultStateChanged, self, [=]() {
miqt_exec_callback_QHistoryState_defaultStateChanged(slot);
});
}
void QHistoryState_connect_historyTypeChanged(QHistoryState* self, intptr_t slot) {
MiqtVirtualQHistoryState::connect(self, &QHistoryState::historyTypeChanged, self, [=]() {
miqt_exec_callback_QHistoryState_historyTypeChanged(slot);
});
}
void QHistoryState_delete(QHistoryState* self) {
delete self;
}

View File

@ -474,6 +474,47 @@ func miqt_exec_callback_QHistoryState_disconnectNotify(self *C.QHistoryState, cb
gofunc((&QHistoryState{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QHistoryState) OnDefaultTransitionChanged(slot func()) {
C.QHistoryState_connect_defaultTransitionChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QHistoryState_defaultTransitionChanged
func miqt_exec_callback_QHistoryState_defaultTransitionChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QHistoryState) OnDefaultStateChanged(slot func()) {
C.QHistoryState_connect_defaultStateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QHistoryState_defaultStateChanged
func miqt_exec_callback_QHistoryState_defaultStateChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QHistoryState) OnHistoryTypeChanged(slot func()) {
C.QHistoryState_connect_historyTypeChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QHistoryState_historyTypeChanged
func miqt_exec_callback_QHistoryState_historyTypeChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QHistoryState) Delete() {

View File

@ -82,6 +82,9 @@ QObject* QHistoryState_protectedbase_sender(bool* _dynamic_cast_ok, const void*
int QHistoryState_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QHistoryState_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QHistoryState_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QHistoryState_connect_defaultTransitionChanged(QHistoryState* self, intptr_t slot);
void QHistoryState_connect_defaultStateChanged(QHistoryState* self, intptr_t slot);
void QHistoryState_connect_historyTypeChanged(QHistoryState* self, intptr_t slot);
void QHistoryState_delete(QHistoryState* self);
#ifdef __cplusplus

View File

@ -24,6 +24,7 @@ extern "C" {
void miqt_exec_callback_QObject_destroyed(intptr_t);
void miqt_exec_callback_QObject_destroyedWithQObject(intptr_t, QObject*);
void miqt_exec_callback_QObject_objectNameChanged(intptr_t, struct miqt_string);
bool miqt_exec_callback_QObject_event(QObject*, intptr_t, QEvent*);
bool miqt_exec_callback_QObject_eventFilter(QObject*, intptr_t, QObject*, QEvent*);
void miqt_exec_callback_QObject_timerEvent(QObject*, intptr_t, QTimerEvent*);
@ -637,6 +638,20 @@ bool QObject_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void*
}
void QObject_connect_objectNameChanged(QObject* self, intptr_t slot) {
MiqtVirtualQObject::connect(self, &QObject::objectNameChanged, self, [=](const QString& objectName) {
const QString objectName_ret = objectName;
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
QByteArray objectName_b = objectName_ret.toUtf8();
struct miqt_string objectName_ms;
objectName_ms.len = objectName_b.length();
objectName_ms.data = static_cast<char*>(malloc(objectName_ms.len));
memcpy(objectName_ms.data, objectName_b.data(), objectName_ms.len);
struct miqt_string sigval1 = objectName_ms;
miqt_exec_callback_QObject_objectNameChanged(slot, sigval1);
});
}
void QObject_delete(QObject* self) {
delete self;
}

View File

@ -658,6 +658,25 @@ func miqt_exec_callback_QObject_disconnectNotify(self *C.QObject, cb C.intptr_t,
gofunc((&QObject{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QObject) OnObjectNameChanged(slot func(objectName string)) {
C.QObject_connect_objectNameChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QObject_objectNameChanged
func miqt_exec_callback_QObject_objectNameChanged(cb C.intptr_t, objectName C.struct_miqt_string) {
gofunc, ok := cgo.Handle(cb).Value().(func(objectName string))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
var objectName_ms C.struct_miqt_string = objectName
objectName_ret := C.GoStringN(objectName_ms.data, C.int(int64(objectName_ms.len)))
C.free(unsafe.Pointer(objectName_ms.data))
slotval1 := objectName_ret
gofunc(slotval1)
}
// Delete this object from C++ memory.
func (this *QObject) Delete() {

View File

@ -122,6 +122,7 @@ QObject* QObject_protectedbase_sender(bool* _dynamic_cast_ok, const void* self);
int QObject_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QObject_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QObject_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QObject_connect_objectNameChanged(QObject* self, intptr_t slot);
void QObject_delete(QObject* self);
QObjectUserData* QObjectUserData_new();

View File

@ -23,6 +23,10 @@ void miqt_exec_callback_QProcess_finished(intptr_t, int);
void miqt_exec_callback_QProcess_finished2(intptr_t, int, int);
void miqt_exec_callback_QProcess_errorWithError(intptr_t, int);
void miqt_exec_callback_QProcess_errorOccurred(intptr_t, int);
void miqt_exec_callback_QProcess_started(intptr_t);
void miqt_exec_callback_QProcess_stateChanged(intptr_t, int);
void miqt_exec_callback_QProcess_readyReadStandardOutput(intptr_t);
void miqt_exec_callback_QProcess_readyReadStandardError(intptr_t);
bool miqt_exec_callback_QProcess_open(QProcess*, intptr_t, int);
bool miqt_exec_callback_QProcess_waitForReadyRead(QProcess*, intptr_t, int);
bool miqt_exec_callback_QProcess_waitForBytesWritten(QProcess*, intptr_t, int);
@ -1683,6 +1687,32 @@ bool QProcess_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void
}
void QProcess_connect_started(QProcess* self, intptr_t slot) {
MiqtVirtualQProcess::connect(self, &QProcess::started, self, [=]() {
miqt_exec_callback_QProcess_started(slot);
});
}
void QProcess_connect_stateChanged(QProcess* self, intptr_t slot) {
MiqtVirtualQProcess::connect(self, &QProcess::stateChanged, self, [=](QProcess::ProcessState state) {
QProcess::ProcessState state_ret = state;
int sigval1 = static_cast<int>(state_ret);
miqt_exec_callback_QProcess_stateChanged(slot, sigval1);
});
}
void QProcess_connect_readyReadStandardOutput(QProcess* self, intptr_t slot) {
MiqtVirtualQProcess::connect(self, &QProcess::readyReadStandardOutput, self, [=]() {
miqt_exec_callback_QProcess_readyReadStandardOutput(slot);
});
}
void QProcess_connect_readyReadStandardError(QProcess* self, intptr_t slot) {
MiqtVirtualQProcess::connect(self, &QProcess::readyReadStandardError, self, [=]() {
miqt_exec_callback_QProcess_readyReadStandardError(slot);
});
}
void QProcess_delete(QProcess* self) {
delete self;
}

View File

@ -1644,6 +1644,64 @@ func miqt_exec_callback_QProcess_disconnectNotify(self *C.QProcess, cb C.intptr_
gofunc((&QProcess{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QProcess) OnStarted(slot func()) {
C.QProcess_connect_started(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QProcess_started
func miqt_exec_callback_QProcess_started(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QProcess) OnStateChanged(slot func(state QProcess__ProcessState)) {
C.QProcess_connect_stateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QProcess_stateChanged
func miqt_exec_callback_QProcess_stateChanged(cb C.intptr_t, state C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(state QProcess__ProcessState))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := (QProcess__ProcessState)(state)
gofunc(slotval1)
}
func (this *QProcess) OnReadyReadStandardOutput(slot func()) {
C.QProcess_connect_readyReadStandardOutput(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QProcess_readyReadStandardOutput
func miqt_exec_callback_QProcess_readyReadStandardOutput(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QProcess) OnReadyReadStandardError(slot func()) {
C.QProcess_connect_readyReadStandardError(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QProcess_readyReadStandardError
func miqt_exec_callback_QProcess_readyReadStandardError(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QProcess) Delete() {

View File

@ -197,6 +197,10 @@ QObject* QProcess_protectedbase_sender(bool* _dynamic_cast_ok, const void* self)
int QProcess_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QProcess_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QProcess_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QProcess_connect_started(QProcess* self, intptr_t slot);
void QProcess_connect_stateChanged(QProcess* self, intptr_t slot);
void QProcess_connect_readyReadStandardOutput(QProcess* self, intptr_t slot);
void QProcess_connect_readyReadStandardError(QProcess* self, intptr_t slot);
void QProcess_delete(QProcess* self);
#ifdef __cplusplus

View File

@ -18,6 +18,8 @@
extern "C" {
#endif
void miqt_exec_callback_QSignalTransition_senderObjectChanged(intptr_t);
void miqt_exec_callback_QSignalTransition_signalChanged(intptr_t);
bool miqt_exec_callback_QSignalTransition_eventTest(QSignalTransition*, intptr_t, QEvent*);
void miqt_exec_callback_QSignalTransition_onTransition(QSignalTransition*, intptr_t, QEvent*);
bool miqt_exec_callback_QSignalTransition_event(QSignalTransition*, intptr_t, QEvent*);
@ -533,6 +535,18 @@ bool QSignalTransition_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, c
}
void QSignalTransition_connect_senderObjectChanged(QSignalTransition* self, intptr_t slot) {
MiqtVirtualQSignalTransition::connect(self, &QSignalTransition::senderObjectChanged, self, [=]() {
miqt_exec_callback_QSignalTransition_senderObjectChanged(slot);
});
}
void QSignalTransition_connect_signalChanged(QSignalTransition* self, intptr_t slot) {
MiqtVirtualQSignalTransition::connect(self, &QSignalTransition::signalChanged, self, [=]() {
miqt_exec_callback_QSignalTransition_signalChanged(slot);
});
}
void QSignalTransition_delete(QSignalTransition* self) {
delete self;
}

View File

@ -475,6 +475,33 @@ func miqt_exec_callback_QSignalTransition_disconnectNotify(self *C.QSignalTransi
gofunc((&QSignalTransition{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QSignalTransition) OnSenderObjectChanged(slot func()) {
C.QSignalTransition_connect_senderObjectChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QSignalTransition_senderObjectChanged
func miqt_exec_callback_QSignalTransition_senderObjectChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QSignalTransition) OnSignalChanged(slot func()) {
C.QSignalTransition_connect_signalChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QSignalTransition_signalChanged
func miqt_exec_callback_QSignalTransition_signalChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QSignalTransition) Delete() {

View File

@ -78,6 +78,8 @@ QObject* QSignalTransition_protectedbase_sender(bool* _dynamic_cast_ok, const vo
int QSignalTransition_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QSignalTransition_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QSignalTransition_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QSignalTransition_connect_senderObjectChanged(QSignalTransition* self, intptr_t slot);
void QSignalTransition_connect_signalChanged(QSignalTransition* self, intptr_t slot);
void QSignalTransition_delete(QSignalTransition* self);
#ifdef __cplusplus

View File

@ -16,6 +16,7 @@
extern "C" {
#endif
void miqt_exec_callback_QSocketNotifier_activated(intptr_t, QSocketDescriptor*, int);
bool miqt_exec_callback_QSocketNotifier_event(QSocketNotifier*, intptr_t, QEvent*);
bool miqt_exec_callback_QSocketNotifier_eventFilter(QSocketNotifier*, intptr_t, QObject*, QEvent*);
void miqt_exec_callback_QSocketNotifier_timerEvent(QSocketNotifier*, intptr_t, QTimerEvent*);
@ -446,6 +447,15 @@ bool QSocketNotifier_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, con
}
void QSocketNotifier_connect_activated(QSocketNotifier* self, intptr_t slot) {
MiqtVirtualQSocketNotifier::connect(self, &QSocketNotifier::activated, self, [=](QSocketDescriptor socket, QSocketNotifier::Type activationEvent) {
QSocketDescriptor* sigval1 = new QSocketDescriptor(socket);
QSocketNotifier::Type activationEvent_ret = activationEvent;
int sigval2 = static_cast<int>(activationEvent_ret);
miqt_exec_callback_QSocketNotifier_activated(slot, sigval1, sigval2);
});
}
void QSocketNotifier_delete(QSocketNotifier* self) {
delete self;
}

View File

@ -403,6 +403,26 @@ func miqt_exec_callback_QSocketNotifier_disconnectNotify(self *C.QSocketNotifier
gofunc((&QSocketNotifier{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QSocketNotifier) OnActivated(slot func(socket QSocketDescriptor, activationEvent QSocketNotifier__Type)) {
C.QSocketNotifier_connect_activated(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QSocketNotifier_activated
func miqt_exec_callback_QSocketNotifier_activated(cb C.intptr_t, socket *C.QSocketDescriptor, activationEvent C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(socket QSocketDescriptor, activationEvent QSocketNotifier__Type))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
socket_goptr := newQSocketDescriptor(socket)
socket_goptr.GoGC() // Qt uses pass-by-value semantics for this type. Mimic with finalizer
slotval1 := *socket_goptr
slotval2 := (QSocketNotifier__Type)(activationEvent)
gofunc(slotval1, slotval2)
}
// Delete this object from C++ memory.
func (this *QSocketNotifier) Delete() {

View File

@ -68,6 +68,7 @@ QObject* QSocketNotifier_protectedbase_sender(bool* _dynamic_cast_ok, const void
int QSocketNotifier_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QSocketNotifier_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QSocketNotifier_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QSocketNotifier_connect_activated(QSocketNotifier* self, intptr_t slot);
void QSocketNotifier_delete(QSocketNotifier* self);
QSocketDescriptor* QSocketDescriptor_new();

View File

@ -20,6 +20,11 @@
extern "C" {
#endif
void miqt_exec_callback_QState_finished(intptr_t);
void miqt_exec_callback_QState_propertiesAssigned(intptr_t);
void miqt_exec_callback_QState_childModeChanged(intptr_t);
void miqt_exec_callback_QState_initialStateChanged(intptr_t);
void miqt_exec_callback_QState_errorStateChanged(intptr_t);
void miqt_exec_callback_QState_onEntry(QState*, intptr_t, QEvent*);
void miqt_exec_callback_QState_onExit(QState*, intptr_t, QEvent*);
bool miqt_exec_callback_QState_event(QState*, intptr_t, QEvent*);
@ -572,6 +577,36 @@ bool QState_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void*
}
void QState_connect_finished(QState* self, intptr_t slot) {
MiqtVirtualQState::connect(self, &QState::finished, self, [=]() {
miqt_exec_callback_QState_finished(slot);
});
}
void QState_connect_propertiesAssigned(QState* self, intptr_t slot) {
MiqtVirtualQState::connect(self, &QState::propertiesAssigned, self, [=]() {
miqt_exec_callback_QState_propertiesAssigned(slot);
});
}
void QState_connect_childModeChanged(QState* self, intptr_t slot) {
MiqtVirtualQState::connect(self, &QState::childModeChanged, self, [=]() {
miqt_exec_callback_QState_childModeChanged(slot);
});
}
void QState_connect_initialStateChanged(QState* self, intptr_t slot) {
MiqtVirtualQState::connect(self, &QState::initialStateChanged, self, [=]() {
miqt_exec_callback_QState_initialStateChanged(slot);
});
}
void QState_connect_errorStateChanged(QState* self, intptr_t slot) {
MiqtVirtualQState::connect(self, &QState::errorStateChanged, self, [=]() {
miqt_exec_callback_QState_errorStateChanged(slot);
});
}
void QState_delete(QState* self) {
delete self;
}

View File

@ -515,6 +515,75 @@ func miqt_exec_callback_QState_disconnectNotify(self *C.QState, cb C.intptr_t, s
gofunc((&QState{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QState) OnFinished(slot func()) {
C.QState_connect_finished(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QState_finished
func miqt_exec_callback_QState_finished(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QState) OnPropertiesAssigned(slot func()) {
C.QState_connect_propertiesAssigned(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QState_propertiesAssigned
func miqt_exec_callback_QState_propertiesAssigned(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QState) OnChildModeChanged(slot func()) {
C.QState_connect_childModeChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QState_childModeChanged
func miqt_exec_callback_QState_childModeChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QState) OnInitialStateChanged(slot func()) {
C.QState_connect_initialStateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QState_initialStateChanged
func miqt_exec_callback_QState_initialStateChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QState) OnErrorStateChanged(slot func()) {
C.QState_connect_errorStateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QState_errorStateChanged
func miqt_exec_callback_QState_errorStateChanged(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QState) Delete() {

View File

@ -90,6 +90,11 @@ QObject* QState_protectedbase_sender(bool* _dynamic_cast_ok, const void* self);
int QState_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QState_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QState_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QState_connect_finished(QState* self, intptr_t slot);
void QState_connect_propertiesAssigned(QState* self, intptr_t slot);
void QState_connect_childModeChanged(QState* self, intptr_t slot);
void QState_connect_initialStateChanged(QState* self, intptr_t slot);
void QState_connect_errorStateChanged(QState* self, intptr_t slot);
void QState_delete(QState* self);
#ifdef __cplusplus

View File

@ -24,6 +24,8 @@ extern "C" {
#endif
void miqt_exec_callback_QStateMachine_runningChanged(intptr_t, bool);
void miqt_exec_callback_QStateMachine_started(intptr_t);
void miqt_exec_callback_QStateMachine_stopped(intptr_t);
bool miqt_exec_callback_QStateMachine_eventFilter(QStateMachine*, intptr_t, QObject*, QEvent*);
void miqt_exec_callback_QStateMachine_onEntry(QStateMachine*, intptr_t, QEvent*);
void miqt_exec_callback_QStateMachine_onExit(QStateMachine*, intptr_t, QEvent*);
@ -790,6 +792,18 @@ bool QStateMachine_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const
}
void QStateMachine_connect_started(QStateMachine* self, intptr_t slot) {
MiqtVirtualQStateMachine::connect(self, &QStateMachine::started, self, [=]() {
miqt_exec_callback_QStateMachine_started(slot);
});
}
void QStateMachine_connect_stopped(QStateMachine* self, intptr_t slot) {
MiqtVirtualQStateMachine::connect(self, &QStateMachine::stopped, self, [=]() {
miqt_exec_callback_QStateMachine_stopped(slot);
});
}
void QStateMachine_delete(QStateMachine* self) {
delete self;
}

View File

@ -689,6 +689,33 @@ func miqt_exec_callback_QStateMachine_disconnectNotify(self *C.QStateMachine, cb
gofunc((&QStateMachine{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QStateMachine) OnStarted(slot func()) {
C.QStateMachine_connect_started(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QStateMachine_started
func miqt_exec_callback_QStateMachine_started(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QStateMachine) OnStopped(slot func()) {
C.QStateMachine_connect_stopped(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QStateMachine_stopped
func miqt_exec_callback_QStateMachine_stopped(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QStateMachine) Delete() {

View File

@ -126,6 +126,8 @@ QObject* QStateMachine_protectedbase_sender(bool* _dynamic_cast_ok, const void*
int QStateMachine_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QStateMachine_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QStateMachine_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QStateMachine_connect_started(QStateMachine* self, intptr_t slot);
void QStateMachine_connect_stopped(QStateMachine* self, intptr_t slot);
void QStateMachine_delete(QStateMachine* self);
QStateMachine__SignalEvent* QStateMachine__SignalEvent_new(QObject* sender, int signalIndex, struct miqt_array /* of QVariant* */ arguments);

View File

@ -17,6 +17,8 @@
extern "C" {
#endif
void miqt_exec_callback_QThread_started(intptr_t);
void miqt_exec_callback_QThread_finished(intptr_t);
bool miqt_exec_callback_QThread_event(QThread*, intptr_t, QEvent*);
void miqt_exec_callback_QThread_run(QThread*, intptr_t);
bool miqt_exec_callback_QThread_eventFilter(QThread*, intptr_t, QObject*, QEvent*);
@ -593,6 +595,18 @@ bool QThread_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void*
}
void QThread_connect_started(QThread* self, intptr_t slot) {
MiqtVirtualQThread::connect(self, &QThread::started, self, [=]() {
miqt_exec_callback_QThread_started(slot);
});
}
void QThread_connect_finished(QThread* self, intptr_t slot) {
MiqtVirtualQThread::connect(self, &QThread::finished, self, [=]() {
miqt_exec_callback_QThread_finished(slot);
});
}
void QThread_delete(QThread* self) {
delete self;
}

View File

@ -541,6 +541,33 @@ func miqt_exec_callback_QThread_disconnectNotify(self *C.QThread, cb C.intptr_t,
gofunc((&QThread{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QThread) OnStarted(slot func()) {
C.QThread_connect_started(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QThread_started
func miqt_exec_callback_QThread_started(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
func (this *QThread) OnFinished(slot func()) {
C.QThread_connect_finished(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QThread_finished
func miqt_exec_callback_QThread_finished(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QThread) Delete() {

View File

@ -97,6 +97,8 @@ QObject* QThread_protectedbase_sender(bool* _dynamic_cast_ok, const void* self);
int QThread_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QThread_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QThread_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QThread_connect_started(QThread* self, intptr_t slot);
void QThread_connect_finished(QThread* self, intptr_t slot);
void QThread_delete(QThread* self);
#ifdef __cplusplus

View File

@ -16,6 +16,10 @@
extern "C" {
#endif
void miqt_exec_callback_QTimeLine_valueChanged(intptr_t, double);
void miqt_exec_callback_QTimeLine_frameChanged(intptr_t, int);
void miqt_exec_callback_QTimeLine_stateChanged(intptr_t, int);
void miqt_exec_callback_QTimeLine_finished(intptr_t);
double miqt_exec_callback_QTimeLine_valueForTime(const QTimeLine*, intptr_t, int);
void miqt_exec_callback_QTimeLine_timerEvent(QTimeLine*, intptr_t, QTimerEvent*);
bool miqt_exec_callback_QTimeLine_event(QTimeLine*, intptr_t, QEvent*);
@ -590,6 +594,34 @@ bool QTimeLine_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const voi
}
void QTimeLine_connect_valueChanged(QTimeLine* self, intptr_t slot) {
MiqtVirtualQTimeLine::connect(self, &QTimeLine::valueChanged, self, [=](qreal x) {
double sigval1 = x;
miqt_exec_callback_QTimeLine_valueChanged(slot, sigval1);
});
}
void QTimeLine_connect_frameChanged(QTimeLine* self, intptr_t slot) {
MiqtVirtualQTimeLine::connect(self, &QTimeLine::frameChanged, self, [=](int param1) {
int sigval1 = param1;
miqt_exec_callback_QTimeLine_frameChanged(slot, sigval1);
});
}
void QTimeLine_connect_stateChanged(QTimeLine* self, intptr_t slot) {
MiqtVirtualQTimeLine::connect(self, &QTimeLine::stateChanged, self, [=](QTimeLine::State newState) {
QTimeLine::State newState_ret = newState;
int sigval1 = static_cast<int>(newState_ret);
miqt_exec_callback_QTimeLine_stateChanged(slot, sigval1);
});
}
void QTimeLine_connect_finished(QTimeLine* self, intptr_t slot) {
MiqtVirtualQTimeLine::connect(self, &QTimeLine::finished, self, [=]() {
miqt_exec_callback_QTimeLine_finished(slot);
});
}
void QTimeLine_delete(QTimeLine* self) {
delete self;
}

View File

@ -557,6 +557,70 @@ func miqt_exec_callback_QTimeLine_disconnectNotify(self *C.QTimeLine, cb C.intpt
gofunc((&QTimeLine{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QTimeLine) OnValueChanged(slot func(x float64)) {
C.QTimeLine_connect_valueChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QTimeLine_valueChanged
func miqt_exec_callback_QTimeLine_valueChanged(cb C.intptr_t, x C.double) {
gofunc, ok := cgo.Handle(cb).Value().(func(x float64))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := (float64)(x)
gofunc(slotval1)
}
func (this *QTimeLine) OnFrameChanged(slot func(param1 int)) {
C.QTimeLine_connect_frameChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QTimeLine_frameChanged
func miqt_exec_callback_QTimeLine_frameChanged(cb C.intptr_t, param1 C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(param1 int))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := (int)(param1)
gofunc(slotval1)
}
func (this *QTimeLine) OnStateChanged(slot func(newState QTimeLine__State)) {
C.QTimeLine_connect_stateChanged(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QTimeLine_stateChanged
func miqt_exec_callback_QTimeLine_stateChanged(cb C.intptr_t, newState C.int) {
gofunc, ok := cgo.Handle(cb).Value().(func(newState QTimeLine__State))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
// Convert all CABI parameters to Go parameters
slotval1 := (QTimeLine__State)(newState)
gofunc(slotval1)
}
func (this *QTimeLine) OnFinished(slot func()) {
C.QTimeLine_connect_finished(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QTimeLine_finished
func miqt_exec_callback_QTimeLine_finished(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QTimeLine) Delete() {

View File

@ -96,6 +96,10 @@ QObject* QTimeLine_protectedbase_sender(bool* _dynamic_cast_ok, const void* self
int QTimeLine_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QTimeLine_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QTimeLine_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QTimeLine_connect_valueChanged(QTimeLine* self, intptr_t slot);
void QTimeLine_connect_frameChanged(QTimeLine* self, intptr_t slot);
void QTimeLine_connect_stateChanged(QTimeLine* self, intptr_t slot);
void QTimeLine_connect_finished(QTimeLine* self, intptr_t slot);
void QTimeLine_delete(QTimeLine* self);
#ifdef __cplusplus

View File

@ -15,6 +15,7 @@
extern "C" {
#endif
void miqt_exec_callback_QTimer_timeout(intptr_t);
void miqt_exec_callback_QTimer_timerEvent(QTimer*, intptr_t, QTimerEvent*);
bool miqt_exec_callback_QTimer_event(QTimer*, intptr_t, QEvent*);
bool miqt_exec_callback_QTimer_eventFilter(QTimer*, intptr_t, QObject*, QEvent*);
@ -476,6 +477,12 @@ bool QTimer_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void*
}
void QTimer_connect_timeout(QTimer* self, intptr_t slot) {
MiqtVirtualQTimer::connect(self, &QTimer::timeout, self, [=]() {
miqt_exec_callback_QTimer_timeout(slot);
});
}
void QTimer_delete(QTimer* self) {
delete self;
}

View File

@ -427,6 +427,19 @@ func miqt_exec_callback_QTimer_disconnectNotify(self *C.QTimer, cb C.intptr_t, s
gofunc((&QTimer{h: self}).callVirtualBase_DisconnectNotify, slotval1)
}
func (this *QTimer) OnTimeout(slot func()) {
C.QTimer_connect_timeout(this.h, C.intptr_t(cgo.NewHandle(slot)))
}
//export miqt_exec_callback_QTimer_timeout
func miqt_exec_callback_QTimer_timeout(cb C.intptr_t) {
gofunc, ok := cgo.Handle(cb).Value().(func())
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
gofunc()
}
// Delete this object from C++ memory.
func (this *QTimer) Delete() {

View File

@ -74,6 +74,7 @@ QObject* QTimer_protectedbase_sender(bool* _dynamic_cast_ok, const void* self);
int QTimer_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QTimer_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QTimer_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QTimer_connect_timeout(QTimer* self, intptr_t slot);
void QTimer_delete(QTimer* self);
#ifdef __cplusplus

7
qt/pdf/cflags.go Normal file
View File

@ -0,0 +1,7 @@
package pdf
/*
#cgo pkg-config: Qt5PdfWidgets
*/
import "C"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,187 @@
#pragma once
#ifndef MIQT_QT_PDF_GEN_QPDFBOOKMARKMODEL_H
#define MIQT_QT_PDF_GEN_QPDFBOOKMARKMODEL_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include "../../libmiqt/libmiqt.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
class QAbstractItemModel;
class QChildEvent;
class QDataStream;
class QEvent;
class QMetaMethod;
class QMetaObject;
class QMimeData;
class QModelIndex;
class QObject;
class QPdfBookmarkModel;
class QPdfDocument;
class QSize;
class QTimerEvent;
class QVariant;
#else
typedef struct QAbstractItemModel QAbstractItemModel;
typedef struct QChildEvent QChildEvent;
typedef struct QDataStream QDataStream;
typedef struct QEvent QEvent;
typedef struct QMetaMethod QMetaMethod;
typedef struct QMetaObject QMetaObject;
typedef struct QMimeData QMimeData;
typedef struct QModelIndex QModelIndex;
typedef struct QObject QObject;
typedef struct QPdfBookmarkModel QPdfBookmarkModel;
typedef struct QPdfDocument QPdfDocument;
typedef struct QSize QSize;
typedef struct QTimerEvent QTimerEvent;
typedef struct QVariant QVariant;
#endif
QPdfBookmarkModel* QPdfBookmarkModel_new();
QPdfBookmarkModel* QPdfBookmarkModel_new2(QObject* parent);
void QPdfBookmarkModel_virtbase(QPdfBookmarkModel* src, QAbstractItemModel** outptr_QAbstractItemModel);
QMetaObject* QPdfBookmarkModel_metaObject(const QPdfBookmarkModel* self);
void* QPdfBookmarkModel_metacast(QPdfBookmarkModel* self, const char* param1);
struct miqt_string QPdfBookmarkModel_tr(const char* s);
struct miqt_string QPdfBookmarkModel_trUtf8(const char* s);
QPdfDocument* QPdfBookmarkModel_document(const QPdfBookmarkModel* self);
void QPdfBookmarkModel_setDocument(QPdfBookmarkModel* self, QPdfDocument* document);
int QPdfBookmarkModel_structureMode(const QPdfBookmarkModel* self);
void QPdfBookmarkModel_setStructureMode(QPdfBookmarkModel* self, int mode);
QVariant* QPdfBookmarkModel_data(const QPdfBookmarkModel* self, QModelIndex* index, int role);
QModelIndex* QPdfBookmarkModel_index(const QPdfBookmarkModel* self, int row, int column, QModelIndex* parent);
QModelIndex* QPdfBookmarkModel_parent(const QPdfBookmarkModel* self, QModelIndex* index);
int QPdfBookmarkModel_rowCount(const QPdfBookmarkModel* self, QModelIndex* parent);
int QPdfBookmarkModel_columnCount(const QPdfBookmarkModel* self, QModelIndex* parent);
struct miqt_map /* of int to struct miqt_string */ QPdfBookmarkModel_roleNames(const QPdfBookmarkModel* self);
void QPdfBookmarkModel_documentChanged(QPdfBookmarkModel* self, QPdfDocument* document);
void QPdfBookmarkModel_connect_documentChanged(QPdfBookmarkModel* self, intptr_t slot);
void QPdfBookmarkModel_structureModeChanged(QPdfBookmarkModel* self, int structureMode);
void QPdfBookmarkModel_connect_structureModeChanged(QPdfBookmarkModel* self, intptr_t slot);
struct miqt_string QPdfBookmarkModel_tr2(const char* s, const char* c);
struct miqt_string QPdfBookmarkModel_tr3(const char* s, const char* c, int n);
struct miqt_string QPdfBookmarkModel_trUtf82(const char* s, const char* c);
struct miqt_string QPdfBookmarkModel_trUtf83(const char* s, const char* c, int n);
bool QPdfBookmarkModel_override_virtual_data(void* self, intptr_t slot);
QVariant* QPdfBookmarkModel_virtualbase_data(const void* self, QModelIndex* index, int role);
bool QPdfBookmarkModel_override_virtual_index(void* self, intptr_t slot);
QModelIndex* QPdfBookmarkModel_virtualbase_index(const void* self, int row, int column, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_parent(void* self, intptr_t slot);
QModelIndex* QPdfBookmarkModel_virtualbase_parent(const void* self, QModelIndex* index);
bool QPdfBookmarkModel_override_virtual_rowCount(void* self, intptr_t slot);
int QPdfBookmarkModel_virtualbase_rowCount(const void* self, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_columnCount(void* self, intptr_t slot);
int QPdfBookmarkModel_virtualbase_columnCount(const void* self, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_roleNames(void* self, intptr_t slot);
struct miqt_map /* of int to struct miqt_string */ QPdfBookmarkModel_virtualbase_roleNames(const void* self);
bool QPdfBookmarkModel_override_virtual_sibling(void* self, intptr_t slot);
QModelIndex* QPdfBookmarkModel_virtualbase_sibling(const void* self, int row, int column, QModelIndex* idx);
bool QPdfBookmarkModel_override_virtual_hasChildren(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_hasChildren(const void* self, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_setData(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_setData(void* self, QModelIndex* index, QVariant* value, int role);
bool QPdfBookmarkModel_override_virtual_headerData(void* self, intptr_t slot);
QVariant* QPdfBookmarkModel_virtualbase_headerData(const void* self, int section, int orientation, int role);
bool QPdfBookmarkModel_override_virtual_setHeaderData(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_setHeaderData(void* self, int section, int orientation, QVariant* value, int role);
bool QPdfBookmarkModel_override_virtual_itemData(void* self, intptr_t slot);
struct miqt_map /* of int to QVariant* */ QPdfBookmarkModel_virtualbase_itemData(const void* self, QModelIndex* index);
bool QPdfBookmarkModel_override_virtual_setItemData(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_setItemData(void* self, QModelIndex* index, struct miqt_map /* of int to QVariant* */ roles);
bool QPdfBookmarkModel_override_virtual_mimeTypes(void* self, intptr_t slot);
struct miqt_array /* of struct miqt_string */ QPdfBookmarkModel_virtualbase_mimeTypes(const void* self);
bool QPdfBookmarkModel_override_virtual_mimeData(void* self, intptr_t slot);
QMimeData* QPdfBookmarkModel_virtualbase_mimeData(const void* self, struct miqt_array /* of QModelIndex* */ indexes);
bool QPdfBookmarkModel_override_virtual_canDropMimeData(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_canDropMimeData(const void* self, QMimeData* data, int action, int row, int column, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_dropMimeData(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_dropMimeData(void* self, QMimeData* data, int action, int row, int column, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_supportedDropActions(void* self, intptr_t slot);
int QPdfBookmarkModel_virtualbase_supportedDropActions(const void* self);
bool QPdfBookmarkModel_override_virtual_supportedDragActions(void* self, intptr_t slot);
int QPdfBookmarkModel_virtualbase_supportedDragActions(const void* self);
bool QPdfBookmarkModel_override_virtual_insertRows(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_insertRows(void* self, int row, int count, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_insertColumns(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_insertColumns(void* self, int column, int count, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_removeRows(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_removeRows(void* self, int row, int count, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_removeColumns(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_removeColumns(void* self, int column, int count, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_moveRows(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_moveRows(void* self, QModelIndex* sourceParent, int sourceRow, int count, QModelIndex* destinationParent, int destinationChild);
bool QPdfBookmarkModel_override_virtual_moveColumns(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_moveColumns(void* self, QModelIndex* sourceParent, int sourceColumn, int count, QModelIndex* destinationParent, int destinationChild);
bool QPdfBookmarkModel_override_virtual_fetchMore(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_fetchMore(void* self, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_canFetchMore(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_canFetchMore(const void* self, QModelIndex* parent);
bool QPdfBookmarkModel_override_virtual_flags(void* self, intptr_t slot);
int QPdfBookmarkModel_virtualbase_flags(const void* self, QModelIndex* index);
bool QPdfBookmarkModel_override_virtual_sort(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_sort(void* self, int column, int order);
bool QPdfBookmarkModel_override_virtual_buddy(void* self, intptr_t slot);
QModelIndex* QPdfBookmarkModel_virtualbase_buddy(const void* self, QModelIndex* index);
bool QPdfBookmarkModel_override_virtual_match(void* self, intptr_t slot);
struct miqt_array /* of QModelIndex* */ QPdfBookmarkModel_virtualbase_match(const void* self, QModelIndex* start, int role, QVariant* value, int hits, int flags);
bool QPdfBookmarkModel_override_virtual_span(void* self, intptr_t slot);
QSize* QPdfBookmarkModel_virtualbase_span(const void* self, QModelIndex* index);
bool QPdfBookmarkModel_override_virtual_submit(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_submit(void* self);
bool QPdfBookmarkModel_override_virtual_revert(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_revert(void* self);
bool QPdfBookmarkModel_override_virtual_event(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_event(void* self, QEvent* event);
bool QPdfBookmarkModel_override_virtual_eventFilter(void* self, intptr_t slot);
bool QPdfBookmarkModel_virtualbase_eventFilter(void* self, QObject* watched, QEvent* event);
bool QPdfBookmarkModel_override_virtual_timerEvent(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_timerEvent(void* self, QTimerEvent* event);
bool QPdfBookmarkModel_override_virtual_childEvent(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_childEvent(void* self, QChildEvent* event);
bool QPdfBookmarkModel_override_virtual_customEvent(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_customEvent(void* self, QEvent* event);
bool QPdfBookmarkModel_override_virtual_connectNotify(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_connectNotify(void* self, QMetaMethod* signal);
bool QPdfBookmarkModel_override_virtual_disconnectNotify(void* self, intptr_t slot);
void QPdfBookmarkModel_virtualbase_disconnectNotify(void* self, QMetaMethod* signal);
void QPdfBookmarkModel_protectedbase_resetInternalData(bool* _dynamic_cast_ok, void* self);
QModelIndex* QPdfBookmarkModel_protectedbase_createIndex(bool* _dynamic_cast_ok, const void* self, int row, int column);
void QPdfBookmarkModel_protectedbase_encodeData(bool* _dynamic_cast_ok, const void* self, struct miqt_array /* of QModelIndex* */ indexes, QDataStream* stream);
bool QPdfBookmarkModel_protectedbase_decodeData(bool* _dynamic_cast_ok, void* self, int row, int column, QModelIndex* parent, QDataStream* stream);
void QPdfBookmarkModel_protectedbase_beginInsertRows(bool* _dynamic_cast_ok, void* self, QModelIndex* parent, int first, int last);
void QPdfBookmarkModel_protectedbase_endInsertRows(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_beginRemoveRows(bool* _dynamic_cast_ok, void* self, QModelIndex* parent, int first, int last);
void QPdfBookmarkModel_protectedbase_endRemoveRows(bool* _dynamic_cast_ok, void* self);
bool QPdfBookmarkModel_protectedbase_beginMoveRows(bool* _dynamic_cast_ok, void* self, QModelIndex* sourceParent, int sourceFirst, int sourceLast, QModelIndex* destinationParent, int destinationRow);
void QPdfBookmarkModel_protectedbase_endMoveRows(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_beginInsertColumns(bool* _dynamic_cast_ok, void* self, QModelIndex* parent, int first, int last);
void QPdfBookmarkModel_protectedbase_endInsertColumns(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_beginRemoveColumns(bool* _dynamic_cast_ok, void* self, QModelIndex* parent, int first, int last);
void QPdfBookmarkModel_protectedbase_endRemoveColumns(bool* _dynamic_cast_ok, void* self);
bool QPdfBookmarkModel_protectedbase_beginMoveColumns(bool* _dynamic_cast_ok, void* self, QModelIndex* sourceParent, int sourceFirst, int sourceLast, QModelIndex* destinationParent, int destinationColumn);
void QPdfBookmarkModel_protectedbase_endMoveColumns(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_beginResetModel(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_endResetModel(bool* _dynamic_cast_ok, void* self);
void QPdfBookmarkModel_protectedbase_changePersistentIndex(bool* _dynamic_cast_ok, void* self, QModelIndex* from, QModelIndex* to);
void QPdfBookmarkModel_protectedbase_changePersistentIndexList(bool* _dynamic_cast_ok, void* self, struct miqt_array /* of QModelIndex* */ from, struct miqt_array /* of QModelIndex* */ to);
struct miqt_array /* of QModelIndex* */ QPdfBookmarkModel_protectedbase_persistentIndexList(bool* _dynamic_cast_ok, const void* self);
QObject* QPdfBookmarkModel_protectedbase_sender(bool* _dynamic_cast_ok, const void* self);
int QPdfBookmarkModel_protectedbase_senderSignalIndex(bool* _dynamic_cast_ok, const void* self);
int QPdfBookmarkModel_protectedbase_receivers(bool* _dynamic_cast_ok, const void* self, const char* signal);
bool QPdfBookmarkModel_protectedbase_isSignalConnected(bool* _dynamic_cast_ok, const void* self, QMetaMethod* signal);
void QPdfBookmarkModel_delete(QPdfBookmarkModel* self);
#ifdef __cplusplus
} /* extern C */
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More