提交 5d78d333 编写于 作者: P peterq

init: 搭建qt5 开发框架

上级
*.pro.user
.idea
pc/vendor
moc*
*.autosave
rcc*
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
## pan-light, 百度网盘不限速客户端
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
)
func main() {
flag.Usage = func() {
println("用法: pan-light [cmd] [sub cmd]\n")
println("参数:\n")
flag.PrintDefaults()
println()
println("命令:\n")
for _, m := range []struct{ name, desc string }{
{"pc start", "启动pc客户端"},
{"pc moc", "生成moc"},
} {
fmt.Printf(" %v%v%v\n", m.name, strings.Repeat(" ", 12-len(m.name)), m.desc)
}
println()
os.Exit(0)
}
flag.Parse()
cmd := "pc"
cmd = flag.Arg(0)
switch cmd {
case "pc":
pcCmd()
default:
flag.Usage()
}
}
func pcCmd() {
cmd := flag.Arg(1)
switch cmd {
case "start":
pcStart()
case "moc":
pcMoc()
default:
flag.Usage()
}
}
func qtBin(name string) string {
v, ok1 := os.LookupEnv("QT_VERSION")
d, ok2 := os.LookupEnv("QT_DIR")
if !ok1 || !ok2 {
panic("请先配置qt环境变量")
}
return d + "/" + v + "/gcc_64/bin/" + name
}
func pcStart() {
// 打包qml
log.Println("打包qml...")
c := cmd("go", "run", "../qt/cmd/qtrcc/main.go", "desktop", "gui/qml")
c.Dir, _ = filepath.Abs("./pc")
c.Run()
// 启动
log.Println("启动pc客户端")
c = cmd("go", "run", "pan-light-pc.go")
c.Dir = "./pc"
c.Run()
}
// 清除svg的style font节点, 减小尺寸
func iconSimplify() {
dir := "./pc/gui/qml/assets/images/icons"
ls, err := ioutil.ReadDir(dir)
if err != nil {
panic(err)
}
reg := regexp.MustCompile(`\<defs\>(.|\n)*\</defs\>`)
for _, f := range ls {
if strings.Index(f.Name(), ".svg") == len(f.Name())-4 {
filename := dir + "/" + f.Name()
bin, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
content := string(bin)
target := reg.ReplaceAllString(content, "")
if target != content {
err = ioutil.WriteFile(filename, []byte(target), os.ModePerm)
if err != nil {
panic(err)
}
}
}
}
}
func pcMoc() {
log.Println("moc...")
c := cmd("go", "run", "../qt/cmd/qtmoc/main.go", "desktop", "gui/comp")
c.Dir, _ = filepath.Abs("./pc")
e := c.Run()
if e != nil {
log.Println(e)
}
}
func cmd(name string, arg ...string) *exec.Cmd {
cmd := exec.Command(name, arg...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd
}
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES +=
RESOURCES += pc/gui/qml/qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS +=
module github.com/peterq/pan-light/pc
require (
github.com/peterq/pan-light/qt v0.0.0
github.com/peterq/pan-light/qt/bindings v0.0.0
)
replace github.com/peterq/pan-light/qt/bindings => ../qt/bindings
replace github.com/peterq/pan-light/qt => ../qt
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shurcooL/go v0.0.0-20181215222900-0143a8f55f04/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/therecipe/env_darwin_amd64_512 v0.0.0-20190102210040-529084f510b3/go.mod h1:4O+Hy+lamRLGBSpC6us4ri+GigPeYdeG9wQRZFH3Rkc=
github.com/therecipe/env_linux_amd64_512 v0.0.0-20190102180622-9b3faedb5806/go.mod h1:rUlYPwVtCiv2SKco9iedVR3TouC3WvEzagEWtL2Mim8=
github.com/therecipe/env_windows_amd64_512 v0.0.0-20190121195954-78ba6026af9b/go.mod h1:hcI7eNXyJoOLCMhct/6aNYySZ4s8pXEejlkSF0tdlww=
github.com/therecipe/env_windows_amd64_512/Tools v0.0.0-20190121195954-78ba6026af9b/go.mod h1:uo9CZHpTlY/tCnFZXyhV/weqZGYWsbYmPOU8UANqU2E=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190319232107-3f1ed9edd1b4 h1:4oAPsdy/MJIeaCzEMEhYwYBU/gHkXH52Xa4M+0GBHfA=
golang.org/x/tools v0.0.0-20190319232107-3f1ed9edd1b4/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
package bridge
import (
"time"
)
var callSyncMap = map[string]func(map[string]interface{}) interface{}{
// 通知异步任务
"asyncTaskMsg": func(p map[string]interface{}) interface{} {
AsyncTaskChanMapLock.RLock()
ch, ok := AsyncTaskChanMap[p["asyncCallId"].(string)]
AsyncTaskChanMapLock.RUnlock()
if !ok {
return false
}
ch <- p["msg"]
return true
},
// 获取当前时间
"time": func(p map[string]interface{}) interface{} {
return time.Now().UnixNano()
},
}
var callAsyncMap = map[string]func(map[string]interface{},
func(interface{}), func(interface{}), func(interface{}), chan interface{}){
"wait": func(p map[string]interface{}, resolve func(interface{}), reject func(interface{}), progress func(interface{}), qmlMsg chan interface{}) {
for i := 0; i < int(p["time"].(float64)); i++ {
time.Sleep(time.Second)
progress("current time is " + time.Now().String())
}
resolve("wait complete")
},
}
package bridge
import (
"context"
"fmt"
"github.com/peterq/pan-light/pc/gui/qt-rpc"
"log"
"runtime/debug"
"sync"
"time"
)
// 业务逻辑侧衔接ui
var sendDataToQml func(string)
var OnClose func(func())
var UiContext = context.WithValue(context.Background(), "start_time", time.Now())
type tJson map[string]interface{}
func NotifyQml(event string, data map[string]interface{}) {
qt_rpc.NotifyQml(event, (*qt_rpc.Gson)(&data))
}
var AsyncTaskChanMap = make(map[string]chan interface{})
var AsyncTaskChanMapLock = new(sync.RWMutex)
func init() {
qt_rpc.CallGoAsync = callGoAsync
qt_rpc.CallGoSync = callGoSync
}
func callGoAsync(data *qt_rpc.Gson) {
var err error
p := *data
action := p["action"].(string)
if fn, ok := callAsyncMap[action]; ok {
go func() {
finish := func() {}
defer func() {
if e := recover(); e != nil {
err = e.(error)
log.Println("调用go api函数出错"+action, e)
log.Printf("stack %s", debug.Stack())
NotifyQml("call.ret", map[string]interface{}{
"type": "reject",
"callId": p["callId"],
"reject": err.Error(),
})
finish()
}
}()
var qmlMsg chan interface{}
if withCh, ok := p["chan"]; ok && withCh.(bool) {
qmlMsg = make(chan interface{})
AsyncTaskChanMapLock.Lock()
AsyncTaskChanMap[p["callId"].(string)] = qmlMsg
AsyncTaskChanMapLock.Unlock()
finish = func() {
AsyncTaskChanMapLock.Lock()
defer AsyncTaskChanMapLock.Unlock()
close(qmlMsg)
delete(AsyncTaskChanMap, p["callId"].(string))
}
}
fn(p["param"].(map[string]interface{}), func(i interface{}) {
NotifyQml("call.ret", map[string]interface{}{
"type": "resolve",
"callId": p["callId"],
"resolve": i,
})
finish()
}, func(i interface{}) {
NotifyQml("call.ret", map[string]interface{}{
"type": "reject",
"callId": p["callId"],
"reject": i,
})
finish()
}, func(i interface{}) {
NotifyQml("call.ret", map[string]interface{}{
"type": "progress",
"callId": p["callId"],
"progress": i,
})
}, qmlMsg)
}()
} else {
NotifyQml("call.ret", map[string]interface{}{
"type": "reject",
"callId": p["callId"],
"reject": fmt.Sprintf("api [%s] not exist", action),
})
}
}
func callGoSync(data *qt_rpc.Gson) (retPointer *qt_rpc.Gson) {
ret := qt_rpc.Gson{}
defer func() { retPointer = &ret }()
p := *data
var err error
action := p["action"].(string)
if fn, ok := callSyncMap[action]; ok {
defer func() {
if e := recover(); e != nil {
err = e.(error)
log.Println("调用go api函数出错"+action, e)
log.Printf("stack %s", debug.Stack())
ret["error"] = "call go panic"
return
}
}()
result := fn(p["param"].(map[string]interface{}))
ret["result"] = result
return
} else {
ret["error"] = "api not exist"
return
}
}
package comp
import (
"encoding/json"
"github.com/peterq/pan-light/pc/gui/qt-rpc"
"github.com/peterq/pan-light/qt/bindings/core"
"github.com/peterq/pan-light/qt/bindings/quick"
"github.com/peterq/pan-light/qt/bindings/widgets"
"log"
)
func init() {
BridgeComp_QmlRegisterType2("PanLight", 1, 0, "BridgeComp")
}
// 用来和qml通信的组件
type BridgeComp struct {
quick.QQuickItem
_ string `property:"someString"`
_ func() `constructor:"init"`
_ func(w *quick.QQuickItem, attr core.Qt__WidgetAttribute, b bool) `signal:"changeAttribute,auto"`
_ func(msg string) `signal:"logMsg,auto"`
_ func(data interface{}) `signal:"test,auto"`
_ func(data string) string `slot:"callSync,auto"`
_ func(data string) `signal:"callAsync,auto"`
_ func(data string) `signal:"goMessage"`
//...
}
var Bridge *BridgeComp
func (t *BridgeComp) init() {
Bridge = t
qt_rpc.NotifyQml = func(event string, data *qt_rpc.Gson) {
(*data)["event"] = event
bin, _ := json.Marshal(*data)
t.GoMessage(string(bin))
}
}
func (t *BridgeComp) changeAttribute(w *quick.QQuickItem, attr core.Qt__WidgetAttribute, b bool) {
widgets.NewQWidgetFromPointer(w.Pointer()).SetAttribute(attr, b)
}
func (t *BridgeComp) logMsg(msg string) {
log.Println("bridge log:", msg)
}
func (t *BridgeComp) test(data interface{}) {
//core.QVariant{}
//log.Println(fmt.Sprintf("%#v", data))
}
// 同步调用go
func (t *BridgeComp) callSync(data string) string {
var gson qt_rpc.Gson
json.Unmarshal([]byte(data), &gson)
result := qt_rpc.CallGoSync(&gson)
bin, _ := json.Marshal(*result)
return string(bin)
}
// 异步调用go
func (t *BridgeComp) callAsync(data string) {
var gson qt_rpc.Gson
json.Unmarshal([]byte(data), &gson)
qt_rpc.CallGoAsync(&gson)
}
import QtQuick 2.0
import PanLight 1.0
BridgeComp {
id: root
width: 250
height: 450
visible: false
someString: "ItemTemplateString"
Component.onCompleted: {
root.logMsg('bridge ready')
root.test(function () {})
}
}
import QtQuick 2.0
Timer {
id: timer
property alias interval: timer.interval
property var cb
running: true
onTriggered: {
cb()
timer.destroy()
}
}
.pragma library
// 此文件存放全局变量和 Polly fill, 不要依赖其他js, 否则会造成依赖循环
// global
var g = {}
// qml 根组件
var root
function init(r) {
root = r
}
var setTimeout = (function () {
var timer = Qt.createComponent("../comps/timer.qml")
return function (cb, time) {
cb = cb || function () {
}
time = time || 0
timer.createObject(null, {
interval: time,
cb: cb
})
return function cancel() {
if (timer) {
timer.destroy()
}
}
}
})()
// 实现了一个待progress回调的Promise
.pragma library
.import "global.js" as G
var setTimeout = G.setTimeout
var Promise = (function () {
'use strict';
/**
* @this {Promise}
*/
function finallyConstructor(callback) {
var constructor = this.constructor;
return this.then(
function (value) {
return constructor.resolve(callback()).then(function () {
return value;
});
},
function (reason) {
return constructor.resolve(callback()).then(function () {
return constructor.reject(reason);
});
}
);
}
// Store setTimeout reference so promise-polyfill will be unaffected by
// other code modifying setTimeout (like sinon.useFakeTimers())
var setTimeoutFunc = setTimeout;
function noop() {
}
// Polyfill for Function.prototype.bind
function bind(fn, thisArg) {
return function () {
fn.apply(thisArg, arguments);
};
}
/**
* @constructor
* @param {Function} fn
*/
function Promise(fn) {
if (!(this instanceof Promise))
throw new TypeError('Promises must be constructed via new');
if (typeof fn !== 'function') throw new TypeError('not a function');
/** @type {!number} */
this._state = 0;
/** @type {!boolean} */
this._handled = false;
/** @type {Promise|undefined} */
this._value = undefined;
/** @type {!Array<!Function>} */
this._deferreds = [];
doResolve(fn, this);
}
function handle(self, deferred) {
while (self._state === 3) {
self = self._value;
}
if (self._state === 0) {
self._deferreds.push(deferred);
return;
}
self._handled = true;
Promise._immediateFn(function () {
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
if (cb === null) {
(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
return;
}
var ret;
try {
ret = cb(self._value);
} catch (e) {
reject(deferred.promise, e);
return;
}
resolve(deferred.promise, ret);
});
}
function resolve(self, newValue) {
try {
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self)
throw new TypeError('A promise cannot be resolved with itself.');
if (
newValue &&
(typeof newValue === 'object' || typeof newValue === 'function')
) {
var then = newValue.then;
if (newValue instanceof Promise) {
self._state = 3;
self._value = newValue;
finale(self);
return;
} else if (typeof then === 'function') {
doResolve(bind(then, newValue), self);
return;
}
}
self._state = 1;
self._value = newValue;
finale(self);
} catch (e) {
reject(self, e);
}
}
function progress(self, newValue) {
try {
for (var i = 0, len = self._deferreds.length; i < len; i++) {
var deferred = self._deferreds[i]
var cb = deferred.onProgress
if (!cb) {
progress(deferred.promise, newValue);
continue
}
var ret
try {
ret = cb(newValue);
} catch (e) {
reject(deferred.promise, e);
return;
}
progress(deferred.promise, ret);
}
} catch (e) {
reject(self, e);
}
}
function reject(self, newValue) {
self._state = 2;
self._value = newValue;
finale(self);
}
function finale(self) {
if (self._state === 2 && self._deferreds.length === 0) {
Promise._immediateFn(function () {
if (!self._handled) {
Promise._unhandledRejectionFn(self._value);
}
});
}
for (var i = 0, len = self._deferreds.length; i < len; i++) {
handle(self, self._deferreds[i]);
}
self._deferreds = null;
}
/**
* @constructor
*/
function Handler(onFulfilled, onRejected, onProgress, promise) {
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
this.onProgress = typeof onProgress === 'function' ? onProgress : null;
this.promise = promise;
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, self) {
var done = false;
try {
fn(
function (value) {
if (done) return;
done = true;
resolve(self, value);
},
function (reason) {
if (done) return;
done = true;
reject(self, reason);
},
function (p) {
if (done) return;
progress(self, p)
}
);
} catch (ex) {
if (done) return;
done = true;
reject(self, ex);
}
}
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype['progress'] = function (onProgeress) {
return this.then(null, null, onProgeress);
};
Promise.prototype.then = function (onFulfilled, onRejected, onProgress) {
// @ts-ignore
var prom = new this.constructor(noop);
prom.parent = this
handle(this, new Handler(onFulfilled, onRejected, onProgress, prom));
return prom;
};
Promise.prototype['finally'] = finallyConstructor;
Promise.all = function (arr) {
return new Promise(function (resolve, reject) {
if (!arr || typeof arr.length === 'undefined')
throw new TypeError('Promise.all accepts an array');
var args = Array.prototype.slice.call(arr);
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(
val,
function (val) {
res(i, val);
},
reject
);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};
Promise.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
};
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
for (var i = 0, len = values.length; i < len; i++) {
values[i].then(resolve, reject);
}
});
};
// Use polyfill for setImmediate for performance gains
Promise._immediateFn =
(typeof setImmediate === 'function' &&
function (fn) {
setImmediate(fn);
}) ||
function (fn) {
setTimeoutFunc(fn, 0);
};
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
if (typeof console !== 'undefined' && console) {
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
}
};
return Promise
})()
.pragma library
.import QtQuick 2.0 as Q
.import "global.js" as G
.import "promise.js" as P
var event = {}
;(function () {
var map = {}
event.fire = function (evt, data) {
if (!map[evt]) return
map[evt].forEach(function (fn, idx) {
try {
fn(data)
if (fn.once) {
map[evt].splice(idx, 1)
}
} catch (e) {
console.error(evt, fn, e)
}
})
}
event.on = function (evt, fn) {
map[evt] = map[evt] || []
map[evt].push(fn)
return function () {
var idx = map[evt].findIndex(function (v) {
return v === fn
})
if (idx >= 0) {
map[evt].splice(idx, 1)
}
}
}
event.once = function (evt, fn) {
fn.once = 1
return event.on(evt, fn)
}
})()
var bridge = (function () {
var comp = loadComponent(function () {
}, "../comps/bridge.qml")
var ins = comp.createObject(G.root)
ins.goMessage.connect(function (data) {
var obj = JSON.parse(data)
event.fire('go.' + obj.event, obj)
})
event.on('go.fuck', function (data) {
console.log('fuck you from golang, ', data.name)
})
return ins
})()
function loadComponent(cb, url) {
var comp = Qt.createComponent(url)
function finishCreation() {
if (comp.status === Q.Component.Ready) {
cb(comp)
} else if (comp.status === Q.Component.Error) {
// Error Handling
console.log("Error loading component:", comp.errorString())
}
}
if (comp.status === Q.Component.Ready) {
cb(comp)
} else {
finishCreation()
comp.statusChanged.connect(finishCreation)
}
return comp
}
var callGoAsync
var callGoSync
;(function () {
var promiseMap = {}
callGoAsync = function (action, param, chan) {
param = param || {}
var callId = action + (+new Date) + ~~(Math.random() * 1e5)
var promise = new P.Promise(function (resolve, reject, progress) {
var handler = {
callId: callId,
resolve: resolve,
reject: reject,
progress: progress
}
promiseMap[callId] = handler
bridge.callAsync(JSON.stringify({chan: !!chan, action: action, param: param, callId: callId}))
})
promise.callId = callId
return promise
}
event.on('go.call.ret', function (data) {
var callId = data.callId
var handler = promiseMap[callId]
if (!handler) {
console.error('can not find handler for call id: ', callId)
return
}
handler[data.type](data[data.type])
if (data.type !== 'progress') {
delete promiseMap[callId]
}
})
callGoSync = function (action, param) {
param = param || {}
var str = bridge.callSync(JSON.stringify({action: action, param: param}))
return JSON.parse(str).result
}
})()
import QtQuick 2.1
import QtQuick.Window 2.0
import "js/util.js" as Util
Window {
visible: true
width: 360
height: 360
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit()
}
}
Text {
id: text
text: "hello pan-light"
anchors.centerIn: parent
}
Component.onCompleted: {
// 初始化js工具
Util.callGoAsync('wait', {
"time": 3
}).then(function (s) {
text.text = s + Util.callGoSync('time')
}, null, function (s) {
text.text = s
})
}
}
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>comps/bridge.qml</file>
<file>js/util.js</file>
<file>js/promise.js</file>
<file>js/global.js</file>
<file>comps/timer.qml</file>
</qresource>
</RCC>
package qt_rpc
import (
"log"
"time"
)
type Gson map[string]interface{}
var CallGoSync = func(gson *Gson) *Gson {
return &Gson{
"error": "go rpc service not initialized",
}
}
var CallGoAsync = func(gson *Gson) {
go func() {
result := &Gson{
"type": "reject",
"callId": (*gson)["callId"],
"reject": "go rpc service not initialized",
}
NotifyQml("call.ret", result)
}()
}
var NotifyQml = func(event string, data *Gson) {
log.Println("qml msg handler not initialized")
}
func init() {
go func() {
time.Sleep(1 * time.Second)
NotifyQml("fuck", &Gson{"name": "trump"})
}()
}
package main
import (
_ "github.com/peterq/pan-light/pc/gui/bridge"
_ "github.com/peterq/pan-light/pc/gui/comp"
_ "github.com/peterq/pan-light/pc/gui/qml"
"github.com/peterq/pan-light/qt/bindings/core"
"github.com/peterq/pan-light/qt/bindings/gui"
"github.com/peterq/pan-light/qt/bindings/qml"
"github.com/peterq/pan-light/qt/bindings/quick"
"os"
)
var dev = true
func main() {
if dev {
devSetup()
}
// 开启高清
core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
quick.QQuickWindow_SetDefaultAlphaBuffer(true) // 悬浮窗需要此设置
app := gui.NewQGuiApplication(len(os.Args), os.Args)
engine := qml.NewQQmlApplicationEngine(nil)
engine.Load(core.NewQUrl3("qrc:/main.qml", 0))
app.Exec()
}
func devSetup() {
}
*.jsc
*.log
*.pro
*.pro.user
*.qmake.stash
*.qmlc
*.so
*.trace
*.vagrant
.DS_Store
Mfile*
*/*-minimal.*
*/*.o
*/*_string.go
*/cgo_*
*/minimal_*
bindings/
/internal/binding/dump/*
/internal/cmd/moc/test/**/moc*
/internal/examples/**/deploy
/internal/examples/**/moc*
/internal/examples/**/rcc*
\ No newline at end of file
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
> 本模块基于 [therecipe/qt](https://github.com/therecipe/qt) 修改, 详细文档请访问原项目
---
Introduction
------------
[Qt](https://en.wikipedia.org/wiki/Qt_(software)) is a cross-platform application framework that is used for developing application software that can be run on various software and hardware platforms with little or no change in the underlying codebase.
[Go](https://en.wikipedia.org/wiki/Go_(programming_language)) (often referred to as golang) is a programming language created at Google.
This package allows you to write Qt applications entirely in Go and makes deploying them later very easy.
[Gallery](https://github.com/therecipe/qt/wiki/Gallery) of example applications making use of this package.
[WebAssembly Demo](https://therecipe.github.io/widgets_playground) | *[repo](https://github.com/therecipe/widgets_playground)*
Status
------
Almost all Qt functions and classes are accessible from Go and you should be able to find everything you need to build fully featured applications.
(A special exception are the WebEngine/WebView packages, these aren't available for Windows yet.)
Installation
------------
##### Windows [(more info)](https://github.com/therecipe/qt/wiki/Installation-on-Windows)
```powershell
go get -u -v github.com/therecipe/qt/cmd/... && for /f %v in ('go env GOPATH') do %v\bin\qtsetup test && %v\bin\qtsetup
```
##### macOS [(more info)](https://github.com/therecipe/qt/wiki/Installation-on-macOS)
```bash
xcode-select --install; go get -u -v github.com/therecipe/qt/cmd/... && $(go env GOPATH)/bin/qtsetup test && $(go env GOPATH)/bin/qtsetup
```
##### Linux [(more info)](https://github.com/therecipe/qt/wiki/Installation-on-Linux)
```bash
go get -u -v github.com/therecipe/qt/cmd/... && $(go env GOPATH)/bin/qtsetup test && $(go env GOPATH)/bin/qtsetup
```
Resources
---------
- [General Installation](https://github.com/therecipe/qt/wiki/Installation)
- [Getting Started](https://github.com/therecipe/qt/wiki/Getting-Started)
- [Wiki](https://github.com/therecipe/qt/wiki)
- [Qt Documentation](https://doc.qt.io/qt-5/classes.html)
- [FAQ](https://github.com/therecipe/qt/wiki/FAQ)
- [#qt-binding](https://gophers.slack.com/messages/qt-binding/details) Slack channel ([invite](https://invite.slack.golangbridge.org)\)
Deployment Targets
------------------
| Target | Arch | Linkage | Docker Deployment | Host OS |
|:------------------------:|:--------:|:----------------:|:-----------------:|:-------:|
| Windows | 32 / 64 | dynamic / static | Yes | Any |
| Linux | 64 | dynamic / system | Yes | Any |
| Android (+Wear) | arm | dynamic | Yes | Any |
| Android-Emulator (+Wear) | 32 | dynamic | Yes | Any |
| Raspberry Pi (1/2/3) | arm | dynamic / system | Yes | Any |
| SailfishOS | arm | system | Yes | Any |
| SailfishOS-Emulator | 32 | system | Yes | Any |
| Ubuntu Touch | arm / 64 | system | Yes | Any |
| JavaScript | 32 | static | Yes | Any |
| WebAssembly | 32 | static | Yes | Any |
| macOS | 64 | dynamic | No | macOS |
| iOS | arm64 | static | No | macOS |
| iOS-Simulator | 64 | static | No | macOS |
| AsteroidOS | arm | system | No | Linux |
License
-------
This package is released under [LGPLv3](https://opensource.org/licenses/LGPL-3.0)
Qt is available under multiple [licenses](https://www.qt.io/licensing)
// +build !no_env,darwin,amd64
package env
import _ "github.com/therecipe/env_darwin_amd64_512"
// +build !no_env,linux,amd64
package env
import _ "github.com/therecipe/env_linux_amd64_512"
// +build !no_env,windows,amd64
package env
import _ "github.com/therecipe/env_windows_amd64_512"
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/cmd"
"github.com/peterq/pan-light/qt/tool-chain/cmd/deploy"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func main() {
flag.Usage = func() {
println("Usage: qtdeploy [-docker] [mode] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
println()
println("Modes:\n")
for _, m := range []struct{ name, desc string }{
{"build", "compile and bundle"},
{"run", "run the binary"},
{"test", "build and run"},
{"help", "print help"},
} {
fmt.Printf(" %v%v%v\n", m.name, strings.Repeat(" ", 12-len(m.name)), m.desc)
}
println()
println("Targets:\n")
//TODO:
println()
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var vagrant bool
flag.BoolVar(&vagrant, "vagrant", false, "run command inside vagrant vm")
var ldFlags string
flag.StringVar(&ldFlags, "ldflags", "", "arguments to pass on each go tool link invocation")
var fast bool
flag.BoolVar(&fast, "fast", false, "use cached moc, minimal and dependencies (works for: windows, darwin, linux)")
var tags string
flag.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build")
var device string
flag.StringVar(&device, "device", "", "a device UUID to be used by the iOS simulator")
var comply bool
flag.BoolVar(&comply, "comply", false, "dump object code to make it easier to comply with LGPL obligations for proprietary developments")
if cmd.ParseFlags() {
flag.Usage()
}
mode := "test"
target := runtime.GOOS
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
mode = flag.Arg(0)
case 2:
mode = flag.Arg(0)
target = flag.Arg(1)
case 3:
mode = flag.Arg(0)
target = flag.Arg(1)
path = flag.Arg(2)
default:
flag.Usage()
}
if mode == "help" {
flag.Usage()
}
var vagrant_system string
if target_splitted := strings.Split(target, "/"); vagrant && len(target_splitted) == 2 {
vagrant_system = target_splitted[0]
target = target_splitted[1]
}
if target == "desktop" {
target = runtime.GOOS
}
utils.CheckBuildTarget(target)
cmd.InitEnv(target)
if !filepath.IsAbs(path) {
oPath := path
path, err = filepath.Abs(path)
if err != nil || !utils.ExistsDir(path) {
utils.Log.WithError(err).WithField("path", path).Debug("can't resolve absolute path")
dirFunc := func() (string, error) {
out, err := utils.RunCmdOptionalError(utils.GoList("{{.Dir}}", oPath), "get pkg dir")
return strings.TrimSpace(out), err
}
if dir, err := dirFunc(); err != nil {
utils.RunCmd(exec.Command("go", "get", "-d", "-v", oPath), "go get pkg")
path, _ = dirFunc()
} else {
path = dir
}
}
}
if !(target == runtime.GOOS || target == "js" || target == "wasm") {
fast = false
}
if (docker || vagrant) && !(target == "js" || target == "wasm") {
fast = false
}
if target == "js" || target == "wasm" { //TODO: remove for module support + resolve dependencies
os.Setenv("GOCACHE", "off")
}
deploy.Deploy(mode, target, path, docker, ldFlags, tags, fast, device, vagrant, vagrant_system, comply)
}
package main
import (
"flag"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/cmd"
"github.com/peterq/pan-light/qt/tool-chain/cmd/minimal"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func main() {
flag.Usage = func() {
println("Usage: qtminimal [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
println()
println("Targets:\n")
//TODO:
println()
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var vagrant bool
flag.BoolVar(&vagrant, "vagrant", false, "run command inside vagrant vm")
var tags string
flag.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build")
if cmd.ParseFlags() {
flag.Usage()
}
target := runtime.GOOS
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
var vagrant_system string
if target_splitted := strings.Split(target, "/"); vagrant && len(target_splitted) == 2 {
vagrant_system = target_splitted[0]
target = target_splitted[1]
}
if target == "desktop" {
target = runtime.GOOS
}
utils.CheckBuildTarget(target)
cmd.InitEnv(target)
if !filepath.IsAbs(path) {
oPath := path
path, err = filepath.Abs(path)
if err != nil || !utils.ExistsDir(path) {
utils.Log.WithError(err).WithField("path", path).Debug("can't resolve absolute path")
dirFunc := func() (string, error) {
out, err := utils.RunCmdOptionalError(utils.GoList("{{.Dir}}", oPath), "get pkg dir")
return strings.TrimSpace(out), err
}
if dir, err := dirFunc(); err != nil {
utils.RunCmd(exec.Command("go", "get", "-d", "-v", oPath), "go get pkg")
path, _ = dirFunc()
} else {
path = dir
}
}
}
if target == "js" || target == "wasm" { //TODO: remove for module support + resolve dependencies
os.Setenv("GOCACHE", "off")
}
switch {
case docker:
cmd.Docker([]string{"qtminimal", "-debug", "-tags=" + tags}, target, path, false)
case vagrant:
cmd.Vagrant([]string{"qtminimal", "-debug", "-tags=" + tags}, target, path, false, vagrant_system)
default:
minimal.Minimal(path, target, tags)
}
}
package main
import (
"flag"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/cmd"
"github.com/peterq/pan-light/qt/tool-chain/cmd/moc"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func main() {
flag.Usage = func() {
println("Usage: qtmoc [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
println()
println("Targets:\n")
//TODO:
println()
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var vagrant bool
flag.BoolVar(&vagrant, "vagrant", false, "run command inside vagrant vm")
var fast bool
flag.BoolVar(&fast, "fast", false, "don't run qtmoc for dependencies")
var tags string
flag.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build")
var slow bool
flag.BoolVar(&slow, "slow", false, "reduce qtmoc's resource usage")
if cmd.ParseFlags() {
flag.Usage()
}
target := runtime.GOOS
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
var vagrant_system string
if target_splitted := strings.Split(target, "/"); vagrant && len(target_splitted) == 2 {
vagrant_system = target_splitted[0]
target = target_splitted[1]
}
if target == "desktop" {
target = runtime.GOOS
}
utils.CheckBuildTarget(target)
cmd.InitEnv(target)
if !filepath.IsAbs(path) {
oPath := path
path, err = filepath.Abs(path)
if err != nil || !utils.ExistsDir(path) {
utils.Log.WithError(err).WithField("path", path).Debug("can't resolve absolute path")
dirFunc := func() (string, error) {
out, err := utils.RunCmdOptionalError(utils.GoList("{{.Dir}}", oPath), "get pkg dir")
return strings.TrimSpace(out), err
}
if dir, err := dirFunc(); err != nil {
utils.RunCmd(exec.Command("go", "get", "-d", "-v", oPath), "go get pkg")
path, _ = dirFunc()
} else {
path = dir
}
}
}
if target == "js" || target == "wasm" { //TODO: remove for module support + resolve dependencies
os.Setenv("GOCACHE", "off")
}
switch {
case docker:
cmd.Docker([]string{"qtmoc", "-debug", "-tags=" + tags}, target, path, false)
case vagrant:
cmd.Vagrant([]string{"qtmoc", "-debug", "-tags=" + tags}, target, path, false, vagrant_system)
default:
moc.Moc(path, target, tags, fast, slow)
}
}
package main
import (
"flag"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/cmd"
"github.com/peterq/pan-light/qt/tool-chain/cmd/rcc"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func main() {
flag.Usage = func() {
println("Usage: qtrcc [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
println()
println("Targets:\n")
//TODO:
println()
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var vagrant bool
flag.BoolVar(&vagrant, "vagrant", false, "run command inside vagrant vm")
var output string
flag.StringVar(&output, "o", os.Getenv("QTRCC_OUTPUT_DIR"), "specify an alternative output dir")
var tags string
flag.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build")
if cmd.ParseFlags() {
flag.Usage()
}
target := runtime.GOOS
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
var vagrant_system string
if target_splitted := strings.Split(target, "/"); vagrant && len(target_splitted) == 2 {
vagrant_system = target_splitted[0]
target = target_splitted[1]
}
if target == "desktop" {
target = runtime.GOOS
}
utils.CheckBuildTarget(target)
cmd.InitEnv(target)
if !filepath.IsAbs(path) {
oPath := path
path, err = filepath.Abs(path)
if err != nil || !utils.ExistsDir(path) {
utils.Log.WithError(err).WithField("path", path).Debug("can't resolve absolute path")
dirFunc := func() (string, error) {
out, err := utils.RunCmdOptionalError(utils.GoList("{{.Dir}}", oPath), "get pkg dir")
return strings.TrimSpace(out), err
}
if dir, err := dirFunc(); err != nil {
utils.RunCmd(exec.Command("go", "get", "-d", "-v", oPath), "go get pkg")
path, _ = dirFunc()
} else {
path = dir
}
}
}
if output != "" && !filepath.IsAbs(output) {
output, err = filepath.Abs(output)
if err != nil {
utils.Log.WithError(err).WithField("output", output).Fatal("can't resolve absolute path")
}
}
if target == "js" || target == "wasm" { //TODO: remove for module support + resolve dependencies
os.Setenv("GOCACHE", "off")
}
switch {
case docker:
cmd.Docker([]string{"qtrcc", "-debug"}, target, path, false)
case vagrant:
cmd.Vagrant([]string{"qtrcc", "-debug"}, target, path, false, vagrant_system)
default:
rcc.Rcc(path, target, tags, output)
}
}
package main
import (
"flag"
"fmt"
"os"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/cmd"
"github.com/peterq/pan-light/qt/tool-chain/cmd/setup"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func main() {
flag.Usage = func() {
println("Usage: qtsetup [-debug] [mode] [target]\n")
println("Flags:\n")
flag.PrintDefaults()
println()
println("Modes:\n")
for _, m := range []struct{ name, desc string }{
{"prep", "symlink tooling into the PATH"},
{"check", "perform some basic env checks"},
{"generate", "generate code for all packages"},
{"install", "go install all packages"},
{"test", "build and test some examples"},
{"full", "run all of the above"},
{"help", "print help"},
{"update", "update 'cmd' and 'tool-chain/cmd'"},
{"upgrade", "update everything"},
} {
fmt.Printf(" %v%v%v\n", m.name, strings.Repeat(" ", 12-len(m.name)), m.desc)
}
println()
println("Targets:\n")
//TODO:
println()
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var vagrant bool
flag.BoolVar(&vagrant, "vagrant", false, "run command inside vagrant vm")
var dynamic bool
if runtime.GOOS != "windows" {
flag.BoolVar(&dynamic, "dynamic", false, "create and use semi-dynamic libraries during the generation and installation process (experimental; no real replacement for dynamic linking)")
}
if cmd.ParseFlags() {
flag.Usage()
}
mode := "full"
target := runtime.GOOS
switch flag.NArg() {
case 0:
case 1:
mode = flag.Arg(0)
case 2:
mode = flag.Arg(0)
target = flag.Arg(1)
default:
flag.Usage()
}
var vagrant_system string
if target_splitted := strings.Split(target, "/"); vagrant && len(target_splitted) == 2 {
vagrant_system = target_splitted[0]
target = target_splitted[1]
}
if target == "desktop" {
target = runtime.GOOS
}
utils.CheckBuildTarget(target)
cmd.InitEnv(target)
if dynamic && (target == runtime.GOOS || target == "js" || target == "wasm") {
os.Setenv("QT_DYNAMIC_SETUP", "true")
}
if target == "js" || target == "wasm" { //TODO: remove for module support + resolve dependencies
os.Setenv("GOCACHE", "off")
}
switch mode {
case "prep":
setup.Prep()
case "check":
setup.Check(target, docker, vagrant)
case "generate":
setup.Generate(target, docker, vagrant)
case "install":
setup.Install(target, docker, vagrant)
case "test":
setup.Test(target, docker, vagrant, vagrant_system)
case "full":
setup.Prep()
setup.Check(target, docker, vagrant)
setup.Generate(target, docker, vagrant)
setup.Install(target, docker, vagrant)
setup.Test(target, docker, vagrant, vagrant_system)
case "update":
setup.Update()
case "upgrade":
setup.Upgrade()
default:
flag.Usage()
}
}
module github.com/peterq/pan-light/qt
require (
github.com/fsnotify/fsnotify v1.4.7 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kisielk/gotool v1.0.0 // indirect
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 // indirect
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab // indirect
github.com/shurcooL/go v0.0.0-20181215222900-0143a8f55f04 // indirect
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect
github.com/sirupsen/logrus v1.4.0
github.com/spf13/cobra v0.0.3 // indirect
github.com/spf13/pflag v1.0.3 // indirect
github.com/stretchr/testify v1.2.2
github.com/therecipe/env_darwin_amd64_512 v0.0.0-20190102210040-529084f510b3
github.com/therecipe/env_linux_amd64_512 v0.0.0-20190102180622-9b3faedb5806
github.com/therecipe/env_windows_amd64_512 v0.0.0-20190121195954-78ba6026af9b
github.com/therecipe/env_windows_amd64_512/Tools v0.0.0-20190121195954-78ba6026af9b // indirect
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/tools v0.0.0-20190319232107-3f1ed9edd1b4
)
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shurcooL/go v0.0.0-20181215222900-0143a8f55f04/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/therecipe/env_darwin_amd64_512 v0.0.0-20190102210040-529084f510b3 h1:PA8Ye1gIvi075ue+vrnrxO+FwzLlqPdtXAYaOoFawgQ=
github.com/therecipe/env_darwin_amd64_512 v0.0.0-20190102210040-529084f510b3/go.mod h1:4O+Hy+lamRLGBSpC6us4ri+GigPeYdeG9wQRZFH3Rkc=
github.com/therecipe/env_linux_amd64_512 v0.0.0-20190102180622-9b3faedb5806 h1:jDlD5+hUuk3Jqv/p3pXWg6XnSHg+vP2C+TawC4PAwZY=
github.com/therecipe/env_linux_amd64_512 v0.0.0-20190102180622-9b3faedb5806/go.mod h1:rUlYPwVtCiv2SKco9iedVR3TouC3WvEzagEWtL2Mim8=
github.com/therecipe/env_windows_amd64_512 v0.0.0-20190121195954-78ba6026af9b h1:6ZI+KleTgN9qERNFwcraUQglw7jWf8fGwaUgYWH+C6k=
github.com/therecipe/env_windows_amd64_512 v0.0.0-20190121195954-78ba6026af9b/go.mod h1:hcI7eNXyJoOLCMhct/6aNYySZ4s8pXEejlkSF0tdlww=
github.com/therecipe/env_windows_amd64_512/Tools v0.0.0-20190121195954-78ba6026af9b h1:gqAAI91SAWaZGnrtYbfrJ688I5WKiiL1hILRF5WtXZ8=
github.com/therecipe/env_windows_amd64_512/Tools v0.0.0-20190121195954-78ba6026af9b/go.mod h1:uo9CZHpTlY/tCnFZXyhV/weqZGYWsbYmPOU8UANqU2E=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6 h1:MXtOG7w2ND9qNCUZSDBGll/SpVIq7ftozR9I8/JGBHY=
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e h1:XEcLGV2fKy3FrsoJVCkX+lMhqc9Suj7J5L/wldA1wu4=
golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190319232107-3f1ed9edd1b4 h1:4oAPsdy/MJIeaCzEMEhYwYBU/gHkXH52Xa4M+0GBHfA=
golang.org/x/tools v0.0.0-20190319232107-3f1ed9edd1b4/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
package qt
import (
"log"
"os"
"runtime"
"strings"
"sync"
"unsafe"
)
var (
Logger = log.New(os.Stderr, "", log.Ltime)
signals = make(map[unsafe.Pointer]map[string]interface{})
signalsJNI = make(map[string]map[string]interface{})
signalsMutex = new(sync.Mutex)
objects = make(map[unsafe.Pointer]interface{})
objectsMutex = new(sync.Mutex)
objectsTemp = make(map[unsafe.Pointer]interface{})
objectsTempMutex = new(sync.Mutex)
)
func init() { runtime.LockOSThread() }
func ExistsSignal(cPtr unsafe.Pointer, signal string) (exists bool) {
signalsMutex.Lock()
_, exists = signals[cPtr][signal]
signalsMutex.Unlock()
return
}
func LendSignal(cPtr unsafe.Pointer, signal string) (s interface{}) {
signalsMutex.Lock()
s = signals[cPtr][signal]
signalsMutex.Unlock()
return
}
func lendSignalJNI(cPtr, signal string) (s interface{}) {
signalsMutex.Lock()
s = signalsJNI[cPtr][signal]
signalsMutex.Unlock()
return
}
func GetSignal(cPtr interface{}, signal string) interface{} {
if dcPtr, ok := cPtr.(unsafe.Pointer); ok {
if signal == "destroyed" || strings.HasPrefix(signal, "~") {
defer DisconnectAllSignals(dcPtr, signal)
}
return LendSignal(dcPtr, signal)
}
return lendSignalJNI(cPtr.(string), signal)
}
func ConnectSignal(cPtr interface{}, signal string, function interface{}) {
if dcPtr, ok := cPtr.(unsafe.Pointer); ok {
signalsMutex.Lock()
if s, exists := signals[dcPtr]; !exists {
signals[dcPtr] = map[string]interface{}{signal: function}
} else {
s[signal] = function
}
signalsMutex.Unlock()
} else {
connectSignalJNI(cPtr.(string), signal, function)
}
}
func connectSignalJNI(cPtr, signal string, function interface{}) {
signalsMutex.Lock()
if s, exists := signalsJNI[cPtr]; !exists {
signalsJNI[cPtr] = map[string]interface{}{signal: function}
} else {
s[signal] = function
}
signalsMutex.Unlock()
}
func DisconnectSignal(cPtr interface{}, signal string) {
if dcPtr, ok := cPtr.(unsafe.Pointer); ok {
signalsMutex.Lock()
delete(signals[dcPtr], signal)
signalsMutex.Unlock()
} else {
disconnectSignalJNI(cPtr.(string), signal)
}
}
func disconnectSignalJNI(cPtr, signal string) {
signalsMutex.Lock()
delete(signalsJNI[cPtr], signal)
signalsMutex.Unlock()
}
func DisconnectAllSignals(cPtr unsafe.Pointer, signal string) {
signalsMutex.Lock()
if s, exists := signals[cPtr]["destroyed"]; signal != "destroyed" && exists {
signals[cPtr] = map[string]interface{}{"destroyed": s}
} else {
delete(signals, cPtr)
}
signalsMutex.Unlock()
if signal == "destroyed" {
Unregister(cPtr)
}
}
func DumpSignals() {
Debug("##############################\tSIGNALSTABLE_START\t##############################")
signalsMutex.Lock()
for cPtr, entry := range signals {
Debug(cPtr, entry)
}
signalsMutex.Unlock()
Debug("##############################\tSIGNALSTABLE_END\t##############################")
}
func CountSignals() (c int) {
signalsMutex.Lock()
c = len(signals)
signalsMutex.Unlock()
return
}
func GoBoolToInt(b bool) int8 {
if b {
return 1
}
return 0
}
func Recover(fn string) {
if recover() != nil {
Debug("RECOVERED:", fn)
}
}
func Debug(fn ...interface{}) {
if strings.ToLower(os.Getenv("QT_DEBUG")) == "true" || runtime.GOARCH == "js" || runtime.GOARCH == "wasm" {
Logger.Println(fn...)
}
}
func ClearSignals() {
signalsMutex.Lock()
signals = make(map[unsafe.Pointer]map[string]interface{})
signalsMutex.Unlock()
}
func Register(cPtr unsafe.Pointer, gPtr interface{}) {
objectsMutex.Lock()
objects[cPtr] = gPtr
objectsMutex.Unlock()
}
func Receive(cPtr unsafe.Pointer) (o interface{}, ok bool) {
objectsMutex.Lock()
o, ok = objects[cPtr]
objectsMutex.Unlock()
return
}
func Unregister(cPtr unsafe.Pointer) {
objectsMutex.Lock()
delete(objects, cPtr)
objectsMutex.Unlock()
}
func RegisterTemp(cPtr unsafe.Pointer, gPtr interface{}) {
objectsTempMutex.Lock()
objectsTemp[cPtr] = gPtr
objectsTempMutex.Unlock()
}
func ReceiveTemp(cPtr unsafe.Pointer) (o interface{}, ok bool) {
objectsTempMutex.Lock()
o, ok = objectsTemp[cPtr]
objectsTempMutex.Unlock()
return
}
func UnregisterTemp(cPtr unsafe.Pointer) {
objectsTempMutex.Lock()
delete(objectsTemp, cPtr)
objectsTempMutex.Unlock()
}
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package qt
/*
To view the log output run:
adb logcat GoLog:I *:S
*/
// Android redirects stdout and stderr to /dev/null.
// As these are common debugging utilities in Go,
// we redirect them to logcat.
//
// Unfortunately, logcat is line oriented, so we must buffer.
/*
#cgo LDFLAGS: -landroid -llog
#include <android/log.h>
#include <stdlib.h>
#include <string.h>
*/
import "C"
import (
"bufio"
"log"
"os"
"syscall"
"unsafe"
)
var (
ctag = C.CString("GoLog")
// Store the writer end of the redirected stderr and stdout
// so that they are not garbage collected and closed.
stderr, stdout *os.File
)
type infoWriter struct{}
func (infoWriter) Write(p []byte) (n int, err error) {
cstr := C.CString(string(p))
C.__android_log_write(C.ANDROID_LOG_INFO, ctag, cstr)
C.free(unsafe.Pointer(cstr))
return len(p), nil
}
func lineLog(f *os.File, priority C.int) {
const logSize = 1024 // matches android/log.h.
r := bufio.NewReaderSize(f, logSize)
for {
line, _, err := r.ReadLine()
str := string(line)
if err != nil {
str += " " + err.Error()
}
cstr := C.CString(str)
C.__android_log_write(priority, ctag, cstr)
C.free(unsafe.Pointer(cstr))
if err != nil {
break
}
}
}
func init() {
log.SetOutput(infoWriter{})
// android logcat includes all of log.LstdFlags
log.SetFlags(log.Flags() &^ log.LstdFlags)
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
stderr = w
if err := syscall.Dup3(int(w.Fd()), int(os.Stderr.Fd()), 0); err != nil {
panic(err)
}
go lineLog(r, C.ANDROID_LOG_ERROR)
r, w, err = os.Pipe()
if err != nil {
panic(err)
}
stdout = w
if err := syscall.Dup3(int(w.Fd()), int(os.Stdout.Fd()), 0); err != nil {
panic(err)
}
go lineLog(r, C.ANDROID_LOG_INFO)
}
// +build js,!wasm
package qt
import "github.com/gopherjs/gopherjs/js"
var Global = js.Global
var Module = Global.Call("eval", "Module")
func MakeWrapper(i interface{}) *js.Object {
o := js.InternalObject(i)
methods := o.Get("constructor").Get("methods")
for i := 0; i < methods.Length(); i++ {
m := methods.Index(i)
if m.Get("pkg").String() != "" { // not exported
continue
}
if o.Get(m.Get("name").String()) == js.Undefined {
o.Set(m.Get("name").String(), func(args ...*js.Object) *js.Object {
return js.Global.Call("$externalizeFunction", o.Get(m.Get("prop").String()), m.Get("typ"), true).Call("apply", o, args)
})
}
}
return o
}
//
var WASM = Module //TODO: remove
// +build !js
package qt
type jsValue interface {
Call(...string) jsValue
Int() int
}
var Global jsValue
var Module jsValue
// +build js,wasm
package qt
import (
"syscall/js"
"unsafe"
)
func init() {
WASM.Set("_callbackReleaseTypedArray", js.NewCallback(func(_ js.Value, args []js.Value) interface{} {
(*js.TypedArray)(unsafe.Pointer(uintptr(args[0].Int()))).Release()
return nil
}))
}
var Global = js.Global()
var Module = Global.Call("eval", "Module")
//TODO: func MakeWrapper(i interface{}) *js.Value
//
var WASM = Module //TODO: remove
package converter
import (
"crypto/sha1"
"encoding/hex"
"fmt"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func CppInputParameters(function *parser.Function) string {
var input = make([]string, len(function.Parameters))
for i, parameter := range function.Parameters {
input[i] = CppInput(parameter.Name, parameter.Value, function)
}
if function.Fullname == "QWebEnginePage::print" {
input = append(input, "[](bool){}")
}
return strings.Join(input, ", ")
}
func CppInputParametersForSlotInvoke(function *parser.Function) string {
if len(function.Parameters) == 0 {
return ""
}
input := make([]string, len(function.Parameters))
for i, parameter := range function.Parameters {
input[i] = fmt.Sprintf("Q_ARG(%v, %v)", CppInputParametersForSlotArguments(function, parameter), CppInput(parameter.Name, parameter.Value, function))
if c, _ := function.Class(); c.Module == parser.MOC && parser.IsPackedMap(parameter.Value) && function.IsMocFunction {
var tHash = sha1.New()
tHash.Write([]byte(parameter.Value))
input[i] = strings.Replace(input[i], parser.CleanValue(parameter.Value), fmt.Sprintf("type%v", hex.EncodeToString(tHash.Sum(nil)[:3])), -1)
}
}
return fmt.Sprintf(", %v", strings.Join(input, ", "))
}
func CppInputParametersForSlotArguments(function *parser.Function, parameter *parser.Parameter) string {
var con string
if strings.Contains(parameter.Value, "const ") {
con = "const "
}
switch {
case strings.Contains(parameter.Value, "*"):
if parser.IsPackedList(parameter.Value) || parser.IsPackedMap(parameter.Value) {
return fmt.Sprintf("%v%v", con, parser.CleanValue(parameter.Value))
}
return fmt.Sprintf("%v%v*", con, parser.CleanValue(parameter.Value))
case isEnum(function.ClassName(), parameter.Value):
if function.Meta == parser.SLOT && function.SignalMode == "" && parser.CleanValue(parameter.Value) == "Qt::Alignment" {
return parser.CleanValue(parameter.Value)
}
return fmt.Sprintf("%v%v", con, cppEnum(function, parameter.Value, true))
default:
return fmt.Sprintf("%v%v", con, parser.CleanValue(parameter.Value))
}
}
func CppInputParametersForSignalConnect(function *parser.Function) string {
var input = make([]string, len(function.Parameters))
for i, parameter := range function.Parameters {
if isEnum(function.ClassName(), parameter.Value) {
input[i] = cppEnum(function, parameter.Value, true)
} else {
input[i] = parameter.Value
}
}
return strings.Join(input, ", ")
}
func CppInputParametersForCallbackHeader(function *parser.Function) string {
var input = make([]string, len(function.Parameters))
for i, parameter := range function.Parameters {
if isEnum(function.ClassName(), parameter.Value) {
input[i] = fmt.Sprintf("%v %v", cppEnum(function, parameter.Value, true), parser.CleanName(parameter.Name, parameter.Value))
} else {
var c, _ = function.Class()
if parser.IsPackedMap(parameter.Value) && c.Module == parser.MOC && function.IsMocFunction {
var tHash = sha1.New()
tHash.Write([]byte(parameter.Value))
input[i] = fmt.Sprintf("%v %v", fmt.Sprintf("type%v", hex.EncodeToString(tHash.Sum(nil)[:3])), parser.CleanName(parameter.Name, parameter.Value))
} else {
if parser.IsPackedList(parameter.Value) || parser.IsPackedMap(parameter.Value) {
input[i] = fmt.Sprintf("%v %v", function.OgParameters[i].Value, parser.CleanName(parameter.Name, parameter.Value))
} else {
input[i] = fmt.Sprintf("%v %v", parameter.Value, parser.CleanName(parameter.Name, parameter.Value))
}
}
}
}
return strings.Join(input, ", ")
}
func CppInputParametersForCallbackBody(function *parser.Function) string {
var input = make([]string, len(function.Parameters)+1)
if parser.UseJs() {
if strings.Contains(strings.Split(function.Signature, ")")[1], "const") {
input[0] = fmt.Sprintf("reinterpret_cast<uintptr_t>(const_cast<void*>(static_cast<const void*>(this)))")
} else {
input[0] = "reinterpret_cast<uintptr_t>(this)"
}
} else {
if strings.Contains(strings.Split(function.Signature, ")")[1], "const") {
input[0] = fmt.Sprintf("const_cast<void*>(static_cast<const void*>(this))")
} else {
input[0] = "this"
}
}
for i, parameter := range function.Parameters {
input[i+1] = cppOutputPacked(parameter.Name, parameter.Value, function)
}
return strings.Join(input, ", ")
}
func CppInputParametersForCallbackBodyPrePack(function *parser.Function) string {
var input = make([]string, 0)
for _, parameter := range function.Parameters {
if packed := cppOutputPack(parameter.Name, parameter.Value, function); packed != "" {
input = append(input, packed)
}
}
return strings.Join(input, "")
}
func CppRegisterMetaType(function *parser.Function) string {
var out = make([]string, 0)
for _, p := range function.Parameters {
if isEnum(function.ClassName(), p.Value) {
out = append(out, cppEnum(function, p.Value, true))
}
}
if isEnum(function.ClassName(), function.Output) {
out = append(out, cppEnum(function, function.Output, true))
}
//TODO: these should ideally be registered with Q_DECLARE_METATYPE instead; also relocate use into registerTypes function
for i := len(out) - 1; i >= 0; i-- {
switch out[i] {
case "QAbstractAnimation::DeletionPolicy", "QTimeLine::State", "QClipboard::Mode",
"QImageReader::ImageReaderError", "QLocalSocket::LocalSocketError", "QSslSocket::SslMode", "QNearFieldShareManager::ShareModes",
"QAccelerometer::AccelerationMode", "QSensor::AxesOrientationMode", "QGeoAreaMonitorSource::Error", "QGeoPositionInfoSource::Error",
"QGeoSatelliteInfoSource::Error", "QSystemTrayIcon::MessageIcon", "QLocalSocket::LocalSocketState", "QGraphicsScene::SceneLayers",
"QSystemTrayIcon::ActivationReason", "QGraphicsBlurEffect::BlurHints", "QAbstractItemDelegate::EndEditHint", "QDockWidget::DockWidgetFeatures",
"QAbstract3DSeries::Mesh", "QAbstract3DInputHandler::InputView", "QAbstract3DGraph::ShadowQuality",
"QAbstract3DGraph::SelectionFlags", "QWebSocketProtocol::CloseCode", "QSqlDriver::NotificationSource", "QCamera::LockTypes",
"QGeoRouteReply::Error", "QWebEnginePage::Feature", "QWebEnginePage::RenderProcessTerminationStatus", "QSerialPort::Directions",
"QPrinter::Orientation", "QPrintPreviewWidget::ViewMode", "QPrintPreviewWidget::ZoomMode", "QInAppProduct::ProductType",
"Q3DCamera::CameraPreset", "Q3DTheme::ColorStyle", "Q3DTheme::Theme", "QAbstract3DAxis::AxisOrientation", "QAbstract3DGraph::OptimizationHints",
"QAbstract3DGraph::ElementType", "QImage::Format", "QItemModelBarDataProxy::MultiMatchBehavior", "QSurface3DSeries::DrawFlags",
"QAbstractBarSeries::LabelsPosition", "QScatterSeries::MarkerShape", "QWebPage::MessageSource", "QWebPage::MessageLevel",
"QWebPage::Feature", "QItemModelSurfaceDataProxy::MultiMatchBehavior", "QCategoryAxis::AxisLabelsPosition",
"QLegend::MarkerShape", "QDesignerFormWindowInterface::Feature", "QValidator::State", "QBluetoothDeviceInfo::Fields", "QValueAxis::TickType":
out = append(out[:i], out[i+1:]...)
default:
if utils.QT_VERSION_NUM() <= 5063 {
switch out[i] {
case "QNetworkAccessManager::NetworkAccessibility":
out = append(out[:i], out[i+1:]...)
}
} else if utils.QT_VERSION_NUM() <= 5042 {
switch out[i] {
case "QAbstractAnimation::Direction", "QAbstractAnimation::State", "QAbstractItemModel::LayoutChangeHint", "QItemSelectionModel::SelectionFlags",
"QInputMethod::Action", "QMovie::MovieState", "QOpenGLDebugLogger::LoggingMode", "QWindow::Visibility", "QDnsLookup::Type", "QNetworkAccessManager::NetworkAccessibility",
"QAbstractItemView::ScrollHint", "QScroller::State", "QQmlComponent::CompilationMode", "QQuickWidget::Status", "QQuickWindow::SceneGraphError", "QQuickView::Status",
"Qt::Orientation", "Qt::DropAction", "Qt::ApplicationState", "Qt::LayoutDirection", "Qt::InputMethodQueries", "Qt::ScreenOrientation", "Qt::WindowModality", "Qt::WindowState",
"Qt::DockWidgetAreas", "Qt::DockWidgetArea", "Qt::FocusReason", "Qt::SortOrder", "Qt::ToolButtonStyle", "Qt::WindowStates", "Qt::Alignment", "Qt::ToolBarAreas":
out = append(out[:i], out[i+1:]...)
}
}
}
}
for i := range out {
out[i] = fmt.Sprintf("\tqRegisterMetaType<%v>();", out[i])
}
return strings.Join(out, "\n")
}
func CppRegisterMetaTypeProp(p *parser.Variable) string {
if isClass(parser.CleanValue(p.Output)) {
pc, _ := p.Class()
if pc.Module != parser.State.ClassMap[parser.CleanValue(p.Output)].Module {
return p.Output
}
}
if isEnum(p.ClassName(), parser.CleanValue(p.Output)) {
return cppEnum(&parser.Function{Fullname: p.Fullname}, parser.CleanValue(p.Output), true)
}
return ""
}
package converter
import (
"fmt"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
)
func GoInputParametersForC(function *parser.Function) string {
var input = make([]string, 0)
if !(function.Static || function.Meta == parser.CONSTRUCTOR) {
input = append(input, "ptr.Pointer()")
}
if function.SignalMode == "" {
for _, parameter := range function.Parameters {
if parameter.PureGoType != "" && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
input = append(input, GoInput(fmt.Sprintf("uintptr(unsafe.Pointer(%v%v))",
func() string {
if !strings.HasPrefix(parameter.PureGoType, "*") {
return "&"
}
return ""
}(), parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
} else {
var alloc = GoInput(parameter.Name, parameter.Value, function, parameter.PureGoType)
if strings.Contains(alloc, "C.CString") || strings.Contains(alloc, "qt.GoBoolToInt(*") || strings.Contains(alloc, "*C.char") {
if parser.CleanValue(parameter.Value) == "QString" || parser.CleanValue(parameter.Value) == "QStringList" {
input = append(input, fmt.Sprintf("C.struct_%v_PackedString{data: %vC, len: %v}", strings.Title(parser.State.ClassMap[function.ClassName()].Module), parser.CleanName(parameter.Name, parameter.Value),
func() string {
if parser.IsBlackListedPureGoType(parameter.PureGoType) {
return "C.longlong(-1)"
}
if parser.CleanValue(parameter.Value) == "QStringList" {
return fmt.Sprintf("C.longlong(len(strings.Join(%v, \"|\")))", parser.CleanName(parameter.Name, parameter.Value))
}
return fmt.Sprintf("C.longlong(len(%v))", parser.CleanName(parameter.Name, parameter.Value))
}()))
} else {
if strings.Contains(alloc, "qt.GoBoolToInt(*") {
input = append(input, fmt.Sprintf("&%vC", parser.CleanName(parameter.Name, parameter.Value)))
} else {
input = append(input, fmt.Sprintf("%vC", parser.CleanName(parameter.Name, parameter.Value)))
}
}
} else {
input = append(input, alloc)
}
}
}
}
return strings.Join(input, ", ")
}
func GoInputParametersForJS(function *parser.Function) string {
input := make([]string, 0)
if !(function.Static || function.Meta == parser.CONSTRUCTOR) {
input = append(input, "uintptr(ptr.Pointer())")
}
if function.SignalMode == "" {
for _, parameter := range function.Parameters {
if parameter.PureGoType != "" && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
input = append(input, GoInputJS(fmt.Sprintf("%vTID", parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
} else {
alloc := GoInputJS(parameter.Name, parameter.Value, function, parameter.PureGoType)
if (parser.UseWasm() && strings.Contains(alloc, "js.TypedArrayOf(")) || GoType(function, parameter.Value, parameter.PureGoType) == "*bool" {
input = append(input, fmt.Sprintf("%vC", parser.CleanName(parameter.Name, parameter.Value)))
} else {
input = append(input, alloc)
}
}
}
}
return strings.Join(input, ", ")
}
func GoInputParametersForJSAlloc(function *parser.Function) []string {
input := make([]string, 0)
if function.SignalMode == "" {
for _, parameter := range function.Parameters {
var (
alloc = GoInputJS(parameter.Name, parameter.Value, function, parameter.PureGoType)
name = fmt.Sprintf("%vC", parser.CleanName(parameter.Name, parameter.Value))
)
switch goType(function, parameter.Value, parameter.PureGoType) {
case "string":
{
if !parser.UseWasm() {
continue
}
//TODO: make it possible to pass nil strings; fix this on C side instead
input = append(input, fmt.Sprintf("var %v js.Value\nif %v != \"\" || true {\n%v = %v\ndefer (*js.TypedArray)(unsafe.Pointer(uintptr(%v.Get(\"data_ptr\").Int()))).Release()\n}\n", name, parser.CleanName(parameter.Name, parameter.Value), name, alloc, name))
}
case "*string", "[]string", "error":
{
if !parser.UseWasm() {
continue
}
input = append(input, fmt.Sprintf("%v := %v\ndefer (*js.TypedArray)(unsafe.Pointer(uintptr(%v.Get(\"data_ptr\").Int()))).Release()\n", name, alloc, name))
}
case "*bool":
{
input = append(input, fmt.Sprintf("%v := qt.WASM.Call(\"_malloc\", 1)\nqt.WASM.Call(\"setValue\", %v, qt.GoBoolToInt(*%v), \"i8\")\ndefer func(){*%v = int8(qt.WASM.Call(\"getValue\", %v, \"i8\").Int()) != 0\nqt.WASM.Call(\"_free\", %v)\n}()\n", name, name, parser.CleanName(parameter.Name, parameter.Value), parser.CleanName(parameter.Name, parameter.Value), name, name))
}
}
}
}
return input
}
func GoInputParametersForCAlloc(function *parser.Function) []string {
input := make([]string, 0)
if function.SignalMode == "" {
for _, parameter := range function.Parameters {
var (
alloc = GoInput(parameter.Name, parameter.Value, function, parameter.PureGoType)
name = fmt.Sprintf("%vC", parser.CleanName(parameter.Name, parameter.Value))
)
switch goType(function, parameter.Value, parameter.PureGoType) {
case "string":
{
input = append(input, fmt.Sprintf("var %v *C.char\nif %v != \"\" {\n%v = %v\ndefer C.free(unsafe.Pointer(%v))\n}\n", name, parser.CleanName(parameter.Name, parameter.Value), name, alloc, name))
}
case "[]byte":
{
input = append(input, fmt.Sprintf("var %v *C.char\nif len(%v) != 0 {\n%v = %v\n}\n", name, parser.CleanName(parameter.Name, parameter.Value), name, alloc))
}
case "*string", "[]string", "error":
{
input = append(input, fmt.Sprintf("%v := %v\ndefer C.free(unsafe.Pointer(%v))\n", name, alloc, name))
}
case "*bool":
{
input = append(input, fmt.Sprintf("%v := %v\ndefer func(){*%v = %v}()\n", name, alloc, parser.CleanName(parameter.Name, parameter.Value), goOutput(name, parameter.Value, function, parameter.PureGoType)))
}
}
}
}
return input
}
func GoInputParametersForCallback(function *parser.Function) string {
input := make([]string, len(function.Parameters))
for i, parameter := range function.Parameters {
if parameter.PureGoType != "" && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
input[i] = fmt.Sprintf("%vD", parser.CleanName(parameter.Name, parameter.Value))
} else {
if function.Name == "readData" && strings.HasPrefix(cgoOutput(parameter.Name, parameter.Value, function, parameter.PureGoType), "cGoUnpack") {
input[i] = "&retS"
} else if strings.Contains(goType(function, parameter.Value, parameter.PureGoType), "*bool") {
if function.SignalMode != parser.CALLBACK {
input[i] = "nil" //TODO: make *bool usable from pure js
} else {
input[i] = fmt.Sprintf("&%vR", parser.CleanName(parameter.Name, parameter.Value))
}
} else {
input[i] = cgoOutput(parameter.Name, parameter.Value, function, parameter.PureGoType)
}
}
}
return strings.Join(input, ", ")
}
package converter
import (
"fmt"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
)
func CppOutputParameters(function *parser.Function, name string) string {
if function.Meta == parser.CONSTRUCTOR {
return CppOutput(name, function.Name, function)
}
return CppOutput(name, function.Output, function)
}
func CppOutputParametersFailed(function *parser.Function) string {
var output = GoOutputParametersFromCFailed(function)
if output == "nil" {
output = "NULL"
}
return output
}
func CppOutputParametersDeducedFromGeneric(function *parser.Function) string {
if function.TemplateModeGo != "" {
return fmt.Sprintf("<%v>", function.TemplateModeGo)
}
switch function.TemplateModeJNI {
case "Int":
{
return "<jint>"
}
case "Boolean":
{
return "<jboolean>"
}
case "Void":
{
return "<void>"
}
case "Object", "String":
{
if function.Name == "callObjectMethod" || function.Name == "callStaticObjectMethod" {
if function.OverloadNumber == "2" || function.OverloadNumber == "4" {
return ""
}
}
return "<jobject>"
}
}
return ""
}
func CppOutputParametersJNIGenericModes(function *parser.Function) []string {
switch function.Name {
case "callMethod", "callStaticMethod":
{
return []string{"Int", "Boolean", "Void"} //TODO: more primitives
}
case "getField", "setField", "getStaticField", "setStaticField":
{
return []string{"Int", "Boolean"} //TODO: more primitives
}
case "getObjectField", "getStaticObjectField", "callObjectMethod", "callStaticObjectMethod":
{
return []string{"Object", "String"} //TODO: add []string, []int, []object, ...
}
}
return make([]string, 0)
}
func CppOutputTemplateJS(function *parser.Function) string {
out := parser.CleanValue(function.Output)
switch out {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
return "emscripten::val"
case "longlong", "long long", "qlonglong", "qint64":
if function.BoundByEmscripten || function.SignalMode == parser.CALLBACK {
return "long"
}
case "ulonglong", "unsigned long long", "qulonglong", "quint64":
if function.BoundByEmscripten || function.SignalMode == parser.CALLBACK {
return "unsigned long"
}
}
switch {
case len(out) == 0:
return "void"
case isClass(out) || parser.IsPackedList(out) || parser.IsPackedMap(out) || cppType(function, function.Output) == "void*" || cppType(function, function.Output) == "uintptr_t":
return "uintptr_t"
case isEnum(function.ClassName(), out) && (function.BoundByEmscripten || function.SignalMode == parser.CALLBACK):
return "long"
default:
return out
}
}
package converter
import "github.com/peterq/pan-light/qt/tool-chain/binding/parser"
func GoOutputParametersFromC(function *parser.Function, name string) string {
if function.Meta == parser.CONSTRUCTOR {
return goOutput(name, function.Name, function, function.PureGoOutput)
}
return goOutput(name, function.Output, function, function.PureGoOutput)
}
func GoJSOutputParametersFromC(function *parser.Function, name string) string {
if function.Meta == parser.CONSTRUCTOR {
return goOutputJS(name, function.Name, function, function.PureGoOutput)
}
return goOutputJS(name, function.Output, function, function.PureGoOutput)
}
func GoOutputParametersFromCFailed(function *parser.Function) string {
if function.Meta == parser.CONSTRUCTOR {
return goOutputFailed(function.Name, function, function.PureGoOutput)
}
return goOutputFailed(function.Output, function, function.PureGoOutput)
}
package converter
import (
"fmt"
"strconv"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
)
func EnumNeedsCppGlue(value string) bool {
return strings.ContainsAny(value, "()<>~+") || value == "" || value == "0x1FFFFFFFU"
}
func GoEnum(n string, v string, e *parser.Enum) string {
var _, err = strconv.Atoi(v)
switch {
case EnumNeedsCppGlue(v):
{
e.NoConst = true
if parser.UseJs() {
if parser.UseWasm() {
return fmt.Sprintf("int64(qt.WASM.Call(\"_%v_%v_Type\").Int())", strings.Split(e.Fullname, "::")[0], n)
}
return fmt.Sprintf("qt.WASM.Call(\"_%v_%v_Type\").Int64()", strings.Split(e.Fullname, "::")[0], n)
}
return fmt.Sprintf("C.%v_%v_Type()", strings.Split(e.Fullname, "::")[0], n)
}
case strings.Contains(v, "0x"):
{
return v
}
case err != nil:
{
if c, ok := parser.State.ClassMap[class(goEnum(e, v))]; ok && module(c.Module) != module(e) && module(c.Module) != "" {
return fmt.Sprintf("%v.%v", module(c.Module), goEnum(e, v))
}
return goEnum(e, v)
}
}
return v
}
package converter
import (
"bytes"
"fmt"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
)
func GoHeaderName(f *parser.Function) string {
if f.SignalMode == parser.CALLBACK {
return fmt.Sprintf("callback%v_%v%v", f.ClassName(), strings.Replace(strings.Title(f.Name), parser.TILDE, "Destroy", -1), f.OverloadNumber)
}
var bb = new(bytes.Buffer)
defer bb.Reset()
if f.Static {
fmt.Fprintf(bb, "%v_", strings.Split(f.Fullname, "::")[0])
}
fmt.Fprint(bb, f.SignalMode)
switch {
case f.Meta == parser.CONSTRUCTOR:
{
fmt.Fprint(bb, "New")
}
case f.Meta == parser.DESTRUCTOR, strings.HasPrefix(f.Name, parser.TILDE):
{
fmt.Fprint(bb, "Destroy")
}
}
switch f.TemplateModeJNI {
case "String", "Object":
{
if strings.Contains(f.Name, "Object") {
if f.TemplateModeJNI == "String" {
fmt.Fprintf(bb, "%v%v", strings.Replace(strings.Title(f.Name), "Object", "", -1), f.TemplateModeJNI)
} else {
fmt.Fprint(bb, strings.Title(f.Name))
}
}
}
default:
{
fmt.Fprintf(bb, "%v%v",
func() string {
if strings.HasSuffix(f.Name, "_atList") || strings.HasSuffix(f.Name, "_setList") ||
strings.HasSuffix(f.Name, "_newList") || strings.HasSuffix(f.Name, "_keyList") {
return f.Name
}
return strings.Title(f.Name)
}(),
f.TemplateModeJNI,
)
}
}
if f.Overload {
fmt.Fprint(bb, f.OverloadNumber)
}
if f.Default {
fmt.Fprint(bb, "Default")
}
if f.Exception {
fmt.Fprint(bb, "Caught")
}
if strings.ContainsAny(bb.String(), "&<>=/!()[]{}^|*+-") || strings.Contains(bb.String(), "Operator") {
f.Access = "unsupported_GoHeaderName"
return f.Access
}
return strings.Replace(bb.String(), parser.TILDE, "", -1)
}
func CppHeaderName(f *parser.Function) string {
return fmt.Sprintf("%v_%v", f.ClassName(), GoHeaderName(f))
}
func GoHeaderOutput(f *parser.Function) string {
switch f.SignalMode {
case parser.CALLBACK:
{
if parser.UseJs() {
if parser.UseWasm() {
return "interface{}"
}
cv := parser.CleanValue(f.Output)
switch cv {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
return "*js.Object"
}
if isClass(cv) || parser.IsPackedList(cv) || parser.IsPackedMap(cv) || goType(f, f.Output, f.PureGoOutput) == "unsafe.Pointer" {
return "uintptr"
}
return goType(f, f.Output, f.PureGoOutput)
}
return cgoTypeOutput(f, f.Output)
}
case parser.CONNECT, parser.DISCONNECT:
{
return ""
}
}
if f.PureGoOutput != "" && !parser.IsBlackListedPureGoType(f.PureGoOutput) {
return f.PureGoOutput
}
var value = f.Output
if f.Meta == parser.CONSTRUCTOR && f.Output == "" {
value = f.Name
}
var o = goType(f, value, f.PureGoOutput)
if isClass(o) {
if !strings.HasPrefix(o, "[]") && !strings.HasPrefix(o, "map[") {
o = fmt.Sprintf("*%v", o)
}
}
if f.Exception {
if o != "" {
o += ", "
}
o += "error"
o = fmt.Sprintf("(%v)", o)
}
return o
}
func CppHeaderOutput(f *parser.Function) string {
var value = f.Output
if f.Meta == parser.CONSTRUCTOR && f.Output == "" {
value = f.Name
}
return cppType(f, value)
}
func GoHeaderInput(f *parser.Function) string {
var bb = new(bytes.Buffer)
defer bb.Reset()
if f.SignalMode == parser.DISCONNECT {
return bb.String()
}
if f.SignalMode == parser.CALLBACK {
if parser.UseJs() {
if parser.UseWasm() {
return "_ js.Value, args []js.Value"
}
fmt.Fprint(bb, "ptr uintptr")
} else {
fmt.Fprint(bb, "ptr unsafe.Pointer")
}
for _, p := range f.Parameters {
if parser.UseJs() { //TODO: move into goType ?
if v := goType(f, p.Value, p.PureGoType); v != "" {
cv := parser.CleanValue(p.Value)
if isEnum(f.ClassName(), cv) {
fmt.Fprintf(bb, ", %v int64", parser.CleanName(p.Name, p.Value))
} else if isClass(cv) {
if cv == "QString" || cv == "QStringList" {
if f.FakeForJSCallback {
fmt.Fprintf(bb, ", %v string", parser.CleanName(p.Name, p.Value))
} else {
fmt.Fprintf(bb, ", %vP *js.Object", parser.CleanName(p.Name, p.Value))
}
} else {
if f.FakeForJSCallback {
fmt.Fprintf(bb, ", %v *js.Object", parser.CleanName(p.Name, p.Value))
} else {
fmt.Fprintf(bb, ", %v uintptr", parser.CleanName(p.Name, p.Value))
}
}
} else {
if parser.IsPackedList(cv) || parser.IsPackedMap(cv) {
if parser.UseWasm() {
fmt.Fprintf(bb, ", %v js.Value", parser.CleanName(p.Name, p.Value))
} else {
fmt.Fprintf(bb, ", %v *js.Object", parser.CleanName(p.Name, p.Value))
}
} else {
if v == "string" {
if f.FakeForJSCallback {
fmt.Fprintf(bb, ", %v string", parser.CleanName(p.Name, p.Value))
} else {
fmt.Fprintf(bb, ", %vP *js.Object", parser.CleanName(p.Name, p.Value))
}
} else {
if v == "*bool" {
fmt.Fprintf(bb, ", %v uintptr", parser.CleanName(p.Name, p.Value))
} else {
fmt.Fprintf(bb, ", %v %v", parser.CleanName(p.Name, p.Value), v)
}
}
}
}
}
} else {
if v := cgoType(f, p.Value); v != "" {
fmt.Fprintf(bb, ", %v %v", parser.CleanName(p.Name, p.Value), v)
}
}
}
return bb.String()
}
if f.SignalMode == parser.CONNECT {
fmt.Fprint(bb, "f func (")
}
if (f.Meta == parser.SIGNAL || strings.Contains(f.Virtual, parser.IMPURE)) && f.SignalMode != parser.CONNECT {
if strings.Contains(f.Virtual, parser.IMPURE) && f.SignalMode == "" {
} else {
return bb.String()
}
}
var tmp = make([]string, 0)
for _, p := range f.Parameters {
if p.PureGoType != "" && !parser.IsBlackListedPureGoType(p.PureGoType) {
tmp = append(tmp, fmt.Sprintf("%v %v", parser.CleanName(p.Name, p.Value), p.PureGoType))
} else {
if v := goType(f, p.Value, p.PureGoType); v != "" {
if isClass(v) && !parser.IsPackedList(parser.CleanValue(p.Value)) && !parser.IsPackedMap(parser.CleanValue(p.Value)) {
if f.SignalMode == parser.CONNECT {
tmp = append(tmp, fmt.Sprintf("%v *%v", parser.CleanName(p.Name, p.Value), v))
} else {
tmp = append(tmp, fmt.Sprintf("%v %v_ITF", parser.CleanName(p.Name, p.Value), v))
}
} else {
tmp = append(tmp, fmt.Sprintf("%v %v", parser.CleanName(p.Name, p.Value), v))
}
} else {
f.Access = "unsupported_GoHeaderInput"
return f.Access
}
}
}
fmt.Fprint(bb, strings.Join(tmp, ", "))
if f.SignalMode == parser.CONNECT {
fmt.Fprint(bb, ")")
if f.PureGoOutput != "" && !parser.IsBlackListedPureGoType(f.PureGoOutput) {
fmt.Fprintf(bb, " %v", f.PureGoOutput)
} else {
if isClass(goType(f, f.Output, f.PureGoOutput)) && !parser.IsPackedList(parser.CleanValue(f.Output)) && !parser.IsPackedMap(parser.CleanValue(f.Output)) {
fmt.Fprintf(bb, " *%v", goType(f, f.Output, f.PureGoOutput))
} else {
fmt.Fprintf(bb, " %v", goType(f, f.Output, f.PureGoOutput))
}
}
}
return bb.String()
}
//TODO: combine with above
func GoHeaderInputSignalFunction(f *parser.Function) string {
var bb = new(bytes.Buffer)
defer bb.Reset()
fmt.Fprint(bb, "func (")
var tmp = make([]string, 0)
for _, p := range f.Parameters {
if p.PureGoType != "" && !parser.IsBlackListedPureGoType(p.PureGoType) {
tmp = append(tmp, fmt.Sprintf("%v", p.PureGoType))
} else {
if v := goType(f, p.Value, p.PureGoType); v != "" {
if isClass(v) && !parser.IsPackedList(parser.CleanValue(p.Value)) && !parser.IsPackedMap(parser.CleanValue(p.Value)) {
tmp = append(tmp, fmt.Sprintf("*%v", v))
} else {
tmp = append(tmp, v)
}
} else {
f.Access = "unsupported_GoHeaderInputSignalFunction"
return f.Access
}
}
}
fmt.Fprint(bb, strings.Join(tmp, ", "))
fmt.Fprint(bb, ")")
if f.SignalMode == parser.CALLBACK {
if f.PureGoOutput != "" && !parser.IsBlackListedPureGoType(f.PureGoOutput) {
fmt.Fprintf(bb, " %v", f.PureGoOutput)
} else {
if isClass(goType(f, f.Output, f.PureGoOutput)) && !parser.IsPackedList(parser.CleanValue(f.Output)) && !parser.IsPackedMap(parser.CleanValue(f.Output)) {
fmt.Fprintf(bb, " *%v", goType(f, f.Output, f.PureGoOutput))
} else {
fmt.Fprintf(bb, " %v", goType(f, f.Output, f.PureGoOutput))
}
}
}
return bb.String()
}
func GoGoInput(f *parser.Function) string {
var tmp = make([]string, 0)
for _, p := range f.Parameters {
tmp = append(tmp, parser.CleanName(p.Name, p.Value))
}
return strings.Join(tmp, ", ")
}
func CppHeaderInput(f *parser.Function) string {
var tmp = make([]string, 0)
if !(f.Static || f.Meta == parser.CONSTRUCTOR) {
tmp = append(tmp, "void* ptr")
}
if f.Meta == parser.SIGNAL {
return strings.Join(tmp, ", ")
}
for _, p := range f.Parameters {
if v := cppTypeInput(f, p.Value); v != "" {
tmp = append(tmp, fmt.Sprintf("%v %v", v, parser.CleanName(p.Name, p.Value)))
} else {
f.Access = "unsupported_CppHeaderInput"
return f.Access
}
}
return strings.Join(tmp, ", ")
}
package converter
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
"github.com/peterq/pan-light/qt/tool-chain/utils"
)
func module(input interface{}) string {
switch input.(type) {
case *parser.Enum, *parser.Function:
{
return module(parser.State.ClassMap[class(input)].Module)
}
case string:
{
return strings.ToLower(strings.TrimPrefix(input.(string), "Qt"))
}
}
return ""
}
func class(input interface{}) string {
switch input.(type) {
case *parser.Function:
{
return class(input.(*parser.Function).Fullname)
}
case *parser.Enum:
{
return class(input.(*parser.Enum).Fullname)
}
case string:
{
if strings.Contains(input.(string), "::") {
return strings.Split(input.(string), "::")[0]
}
if strings.Contains(input.(string), "__") {
return strings.Split(input.(string), "__")[0]
}
}
}
return ""
}
func isClass(value string) bool {
_, ok := parser.IsClass(value)
return ok
}
func isEnum(class, value string) bool {
outE, _ := findEnum(class, value, false)
return outE != ""
}
func findEnum(className, value string, byValue bool) (string, string) {
//look in given class
if c, ok := parser.State.ClassMap[class(value)]; ok {
for _, e := range c.Enums {
if outE, outT := findEnumH(e, value, byValue); outE != "" {
return outE, outT
}
}
}
//look in same class
if c, ok := parser.State.ClassMap[className]; ok {
for _, e := range c.Enums {
if outE, outT := findEnumH(e, value, byValue); outE != "" {
return outE, outT
}
}
}
//look in super classes
if c, ok := parser.State.ClassMap[className]; ok {
for _, s := range c.GetAllBases() {
if sc, ok := parser.State.ClassMap[s]; ok {
for _, e := range sc.Enums {
if outE, outT := findEnumH(e, value, byValue); outE != "" {
return outE, outT
}
}
}
}
}
return "", ""
}
func findEnumH(e *parser.Enum, value string, byValue bool) (string, string) {
if byValue {
for _, v := range e.Values {
if outE, _ := findEnumHelper(value, fmt.Sprintf("%v::%v", class(e), v.Name), ""); outE != "" {
return outE, ""
}
}
} else {
if outE, outT := findEnumHelper(value, e.Fullname, e.Typedef); outE != "" {
return outE, outT
}
}
return "", ""
}
func findEnumHelper(value, name, typedef string) (string, string) {
var fullName = name
if strings.Contains(value, "::") {
value = strings.Split(value, "::")[1]
}
if strings.Contains(name, "::") {
name = strings.Split(name, "::")[1]
}
if strings.Contains(typedef, "::") {
typedef = strings.Split(typedef, "::")[1]
}
switch value {
case name, typedef:
{
return fullName, typedef
}
}
return "", ""
}
func goEnum(inter interface{}, value string) string {
var findByValue bool
switch inter.(type) {
case *parser.Enum:
{
findByValue = true
}
}
if outE, _ := findEnum(class(inter), value, findByValue); outE != "" {
return strings.Replace(outE, ":", "_", -1)
}
switch deduced := inter.(type) {
case *parser.Function:
{
deduced.Access = "unsupported_goEnum"
}
case *parser.Enum:
{
deduced.Access = "unsupported_goEnum"
}
}
return "unsupported_goEnum"
}
func cppEnum(f *parser.Function, value string, exact bool) string {
if outE, outT := findEnum(class(f), value, false); outE != "" {
if exact {
if outT == "" {
return outE
}
if !strings.Contains(outT, "::") {
outT = fmt.Sprintf("%v::%v", class(outE), outT)
}
return cppEnumExact(value, outE, outT)
}
return outE
}
f.Access = fmt.Sprintf("unsupported_cppEnum(%v)", value)
return f.Access
}
func cppEnumExact(value, outE, outT string) string {
var trimedValue = value
if strings.Contains(value, "::") {
trimedValue = strings.Split(value, "::")[1]
}
if trimedValue == strings.Split(outT, "::")[1] {
return outT
}
return outE
}
func IsPrivateSignal(f *parser.Function) bool {
var fc, ok = f.Class()
if !ok {
return false
}
if fc.Module == "QtCore" {
var (
fData string
fPath = strings.Replace(filepath.Base(f.Filepath), ".cpp", ".h", -1)
)
fPath = strings.Replace(fPath, ".mm", ".h", -1)
if strings.HasSuffix(fPath, "_win.h") {
fPath = strings.Replace(fPath, "_win.h", ".h", -1)
}
switch runtime.GOOS {
case "darwin":
{
if utils.QT_HOMEBREW() || utils.QT_MACPORTS() {
fData = utils.LoadOptional(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath))
} else if utils.QT_NIX() {
for _, qmakepath := range strings.Split(os.Getenv("QMAKEPATH"), string(filepath.ListSeparator)) {
if strings.Contains(qmakepath, "qtbase") {
fData = utils.Load(filepath.Join(qmakepath, "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
break
}
}
} else {
fData = utils.LoadOptional(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath))
if len(fData) == 0 {
fData = utils.LoadOptional(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Headers", fPath))
}
}
}
case "windows":
{
if utils.QT_MSYS2() {
if utils.QT_MSYS2_STATIC() {
fData = utils.LoadOptional(filepath.Join(utils.QT_MSYS2_DIR(), "qt5-static", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
} else {
fData = utils.LoadOptional(filepath.Join(utils.QT_MSYS2_DIR(), "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
}
} else {
path := filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "mingw73_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)
if !utils.ExistsDir(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR())) {
path = filepath.Join(utils.QT_DIR(), utils.QT_VERSION(), "mingw73_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)
}
if !utils.ExistsFile(path) {
path = strings.Replace(path, "mingw73_64", "mingw53_32", -1)
}
if !utils.ExistsFile(path) {
path = strings.Replace(path, "mingw53_32", "mingw49_32", -1)
}
fData = utils.Load(path)
}
}
case "linux":
{
switch {
case utils.QT_PKG_CONFIG():
fData = utils.LoadOptional(filepath.Join(strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=includedir", "Qt5Core"), "convert.IsPrivateSignal_includeDir")), strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
case utils.QT_SAILFISH():
fData = utils.LoadOptional(filepath.Join("/srv/mer/targets/SailfishOS-"+utils.QT_SAILFISH_VERSION()+"-i486/usr/include/qt5", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
default:
path := filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "gcc_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)
if !utils.ExistsDir(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR())) {
path = filepath.Join(utils.QT_DIR(), utils.QT_VERSION(), "gcc_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)
}
fData = utils.Load(path)
}
}
}
if fData != "" {
if strings.Contains(fData, fmt.Sprintf("%v(", f.Name)) {
return strings.Contains(strings.Split(strings.Split(fData, fmt.Sprintf("%v(", f.Name))[1], ");")[0], "QPrivateSignal")
}
if strings.Contains(fData, fmt.Sprintf("%v (", f.Name)) {
return strings.Contains(strings.Split(strings.Split(fData, fmt.Sprintf("%v (", f.Name))[1], ");")[0], "QPrivateSignal")
}
}
utils.Log.Debugln("converter.IsPrivateSignal", f.ClassName())
}
return false
}
此差异已折叠。
此差异已折叠。
package converter
//TODO: GLchar, GLbyte
import (
"fmt"
"strings"
"github.com/peterq/pan-light/qt/tool-chain/binding/parser"
)
func GoType(f *parser.Function, value string, p string) string { return goType(f, value, p) }
func goType(f *parser.Function, value string, p string) string {
var vOld = value
value = parser.CleanValue(value)
switch value {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
{
if strings.Contains(vOld, "**") || value == "QStringList" {
return "[]string"
}
if strings.Contains(p, "error") {
return "error"
}
if value == "char" && strings.Count(vOld, "*") == 1 && f.Name == "readData" {
return "*string"
}
if !parser.UseJs() { //TODO: support []byte in js as well
switch value {
case "char", "qint8", "uchar", "quint8", "GLubyte":
if len(f.Parameters) <= 4 &&
(strings.Contains(strings.ToLower(f.Name), "read") ||
strings.Contains(strings.ToLower(f.Name), "write") ||
strings.Contains(strings.ToLower(f.Name), "data")) {
for _, p := range f.Parameters {
if strings.Contains(p.Value, "int") && f.Parameters[0].Value == vOld {
return "[]byte"
}
}
}
}
}
return "string"
}
case "void", "GLvoid", "":
{
if strings.Contains(vOld, "*") {
return "unsafe.Pointer"
}
return ""
}
case "bool", "GLboolean":
{
if strings.Contains(vOld, "*") {
return "*bool"
}
return "bool"
}
case "short", "qint16", "GLshort":
{
return "int16"
}
case "ushort", "unsigned short", "quint16", "GLushort":
{
return "uint16"
}
case "int", "qint32", "GLint", "GLsizei", "GLintptrARB", "GLsizeiptrARB", "GLfixed", "GLclampx":
{
return "int"
}
case "uint", "unsigned int", "quint32", "GLenum", "GLbitfield", "GLuint", "QRgb":
{
return "uint"
}
case "long":
{
return "int"
}
case "ulong", "unsigned long":
{
return "uint"
}
case "longlong", "long long", "qlonglong", "qint64":
{
return "int64"
}
case "ulonglong", "unsigned long long", "qulonglong", "quint64":
{
return "uint64"
}
case "float", "GLfloat", "GLclampf":
{
return "float32"
}
case "double", "qreal":
{
return "float64"
}
case "uintptr_t", "uintptr", "quintptr", "WId":
{
return "uintptr"
}
//non std types
case "T":
{
switch f.TemplateModeJNI {
case "Boolean":
{
return "bool"
}
case "Int":
{
return "int"
}
case "Void":
{
return ""
}
}
if module(f) == "androidextras" && f.Name != "object" {
return fmt.Sprintf("interface{}")
}
return "unsafe.Pointer"
}
case "JavaVM", "jclass", "jobject":
{
return "unsafe.Pointer"
}
case "...":
{
if parser.State.ClassMap[f.ClassName()].Module == "QtAndroidExtras" {
return "...interface{}"
}
}
}
switch {
case isEnum(f.ClassName(), value):
{
if c, ok := parser.State.ClassMap[class(cppEnum(f, value, false))]; ok && module(c.Module) != module(f) && module(c.Module) != "" {
if _, ok := parser.State.ClassMap[f.ClassName()].WeakLink[c.Module]; ok {
return "int64"
}
return fmt.Sprintf("%v.%v", module(c.Module), goEnum(f, value))
}
return goEnum(f, value)
}
case isClass(value):
{
if strings.Contains(value, ".") {
value = strings.Split(value, ".")[1]
}
if m := module(parser.State.ClassMap[value].Module); m != module(f) {
if _, ok := parser.State.ClassMap[f.ClassName()].WeakLink[parser.State.ClassMap[value].Module]; ok {
return "unsafe.Pointer"
}
return fmt.Sprintf("%v.%v", m, value)
}
if f.TemplateModeJNI == "String" {
return "string"
}
return value
}
case parser.IsPackedList(value):
{
return fmt.Sprintf("[]%v%v", func() string {
if isClass(parser.UnpackedList(value)) && parser.UnpackedList(value) != "QString" && parser.UnpackedList(value) != "QStringList" {
return "*"
}
return ""
}(), goType(f, parser.UnpackedListDirty(value), p))
}
case parser.IsPackedMap(value):
{
var key, value = parser.UnpackedMapDirty(value)
return fmt.Sprintf("map[%v%v]%v%v",
func() string {
if isClass(parser.CleanValue(key)) && parser.CleanValue(key) != "QString" && parser.CleanValue(key) != "QStringList" {
return "*"
}
return ""
}(), goType(f, key, parser.UnpackedGoMapDirty(p)[0]),
func() string {
if isClass(parser.CleanValue(value)) && parser.CleanValue(value) != "QString" && parser.CleanValue(value) != "QStringList" {
return "*"
}
return ""
}(), goType(f, value, parser.UnpackedGoMapDirty(p)[1]))
}
}
f.Access = fmt.Sprintf("unsupported_goType(%v)", value)
return f.Access
}
func cgoTypeOutput(f *parser.Function, value string) string {
switch parser.CleanValue(value) {
case "char", "qint8", "uchar", "quint8", "GLubyte":
{
return "*C.char"
}
default:
{
if parser.IsPackedList(parser.CleanValue(value)) || parser.IsPackedMap(parser.CleanValue(value)) {
return "unsafe.Pointer"
}
return cgoType(f, value)
}
}
}
func cgoType(f *parser.Function, value string) string {
var vOld = value
value = parser.CleanValue(value)
switch value {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
{
return fmt.Sprintf("C.struct_%v_PackedString", strings.Title(parser.State.ClassMap[f.ClassName()].Module))
}
case "void", "GLvoid", "":
{
if strings.Contains(vOld, "*") {
return "unsafe.Pointer"
}
return ""
}
case "bool", "GLboolean":
{
if strings.Contains(vOld, "*") {
return "*C.char"
}
return "C.char"
}
case "short", "qint16", "GLshort":
{
return "C.short"
}
case "ushort", "unsigned short", "quint16", "GLushort":
{
return "C.ushort"
}
case "int", "qint32", "GLint", "GLsizei", "GLintptrARB", "GLsizeiptrARB", "GLfixed", "GLclampx":
{
return "C.int"
}
case "uint", "unsigned int", "quint32", "GLenum", "GLbitfield", "GLuint", "QRgb":
{
return "C.uint"
}
case "long":
{
return "C.long"
}
case "ulong", "unsigned long":
{
return "C.ulong"
}
case "longlong", "long long", "qlonglong", "qint64":
{
return "C.longlong"
}
case "ulonglong", "unsigned long long", "qulonglong", "quint64":
{
return "C.ulonglong"
}
case "float", "GLfloat", "GLclampf":
{
return "C.float"
}
case "double", "qreal":
{
if value == "qreal" && strings.HasPrefix(parser.State.Target, "sailfish") {
return "C.float"
}
return "C.double"
}
case "uintptr_t", "uintptr", "quintptr", "WId":
{
return "C.uintptr_t"
}
}
switch {
case isEnum(f.ClassName(), value):
{
return "C.longlong"
}
case isClass(value):
{
return "unsafe.Pointer"
}
case parser.IsPackedList(value) || parser.IsPackedMap(value):
{
return fmt.Sprintf("C.struct_%v_PackedList", strings.Title(parser.State.ClassMap[f.ClassName()].Module))
}
}
f.Access = fmt.Sprintf("unsupported_cgoType(%v)", value)
return f.Access
}
func cppTypeInput(f *parser.Function, value string) string {
switch parser.CleanValue(value) {
case "char", "qint8", "uchar", "quint8", "GLubyte":
{
if parser.UseJs() {
return "emscripten::val"
}
return "char*"
}
default:
{
if parser.IsPackedList(parser.CleanValue(value)) || parser.IsPackedMap(parser.CleanValue(value)) {
return "void*"
}
return cppType(f, value)
}
}
}
func cppType(f *parser.Function, value string) string {
var vOld = value
value = parser.CleanValue(value)
switch value {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
{
if parser.UseJs() {
return "emscripten::val"
}
return fmt.Sprintf("struct %v_PackedString", strings.Title(parser.State.ClassMap[f.ClassName()].Module))
}
case "void", "GLvoid", "":
{
if strings.Contains(vOld, "*") {
if parser.UseJs() {
if f.SignalMode == parser.CALLBACK {
return "uintptr_t"
}
for _, p := range append(f.Parameters, &parser.Parameter{Value: f.Output}) {
if parser.IsPackedList(p.Value) || parser.IsPackedMap(p.Value) {
return "uintptr_t"
}
switch parser.CleanValue(p.Value) {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
return "uintptr_t"
}
}
}
return "void*"
}
return "void"
}
case "bool", "GLboolean":
{
if strings.Contains(vOld, "*") {
if parser.UseJs() {
if f.SignalMode == parser.CALLBACK {
return "uintptr_t"
}
for _, p := range append(f.Parameters, &parser.Parameter{Value: f.Output}) {
if parser.IsPackedList(p.Value) || parser.IsPackedMap(p.Value) {
return "uintptr_t"
}
switch parser.CleanValue(p.Value) {
case "char", "qint8", "uchar", "quint8", "GLubyte", "QString", "QStringList":
return "uintptr_t"
}
}
}
return "char*"
}
return "char"
}
case "short", "qint16", "GLshort":
{
return "short"
}
case "ushort", "unsigned short", "quint16", "GLushort":
{
return "unsigned short"
}
case "int", "qint32", "GLint", "GLsizei", "GLintptrARB", "GLsizeiptrARB", "GLfixed", "GLclampx":
{
return "int"
}
case "uint", "unsigned int", "quint32", "GLenum", "GLbitfield", "GLuint", "QRgb":
{
return "unsigned int"
}
case "long":
{
return "long"
}
case "ulong", "unsigned long":
{
return "unsigned long"
}
case "longlong", "long long", "qlonglong", "qint64":
{
if parser.UseJs() && f.BoundByEmscripten {
return "long" //TODO:
}
return "long long"
}
case "ulonglong", "unsigned long long", "qulonglong", "quint64":
{
if parser.UseJs() && f.BoundByEmscripten {
return "unsigned long" //TODO:
}
return "unsigned long long"
}
case "float", "GLfloat", "GLclampf":
{
return "float"
}
case "double", "qreal":
{
if value == "qreal" && strings.HasPrefix(parser.State.Target, "sailfish") {
return "float"
}
return "double"
}
case "uintptr_t", "uintptr", "quintptr", "WId":
{
return "uintptr_t"
}
//non std types
case "T":
{
switch f.TemplateModeJNI {
case "Boolean":
{
return "char"
}
case "Int":
{
return "int"
}
case "Void":
{
return "void"
}
}
return "void*"
}
case "JavaVM", "jclass", "jobject":
{
return "void*"
}
case "...":
{
var tmp = make([]string, 10)
for i := 0; i < 10; i++ {
if i == 9 {
tmp[i] = "void*"
} else {
tmp[i] = fmt.Sprintf("void* v%v", i)
}
}
return strings.Join(tmp, ", ")
}
}
switch {
case isEnum(f.ClassName(), value):
{
if parser.UseJs() && f.BoundByEmscripten {
return "long" //TODO:
}
return "long long"
}
case isClass(value):
{
return "void*"
}
case parser.IsPackedList(value) || parser.IsPackedMap(value):
{
if parser.UseJs() {
return "emscripten::val"
}
return fmt.Sprintf("struct %v_PackedList", strings.Title(parser.State.ClassMap[f.ClassName()].Module))
}
}
f.Access = fmt.Sprintf("unsupported_cppType(%v)", value)
return f.Access
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
package parser
func (m *Module) remove() {
m.removeClasses()
}
func (m *Module) removeClasses() {
for _, c := range SortedClassesForModule(m.Project, false) {
switch {
case
!(c.Access == "public" || c.Access == "protected"),
c.Name == "qoutputrange":
delete(State.ClassMap, c.Name)
}
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
package cmd
import (
//only needed for module support ->
_ "github.com/gopherjs/gopherjs/js"
//<-
)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册