Skip to content

Commit

Permalink
Fix more go-uic. Add cgo-rcc. Add signal/slot connect destroy.
Browse files Browse the repository at this point in the history
  • Loading branch information
drswinghead committed Aug 12, 2018
1 parent 2824a97 commit 830054b
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 5 deletions.
169 changes: 169 additions & 0 deletions cmd/cgo-rcc/main.go
@@ -0,0 +1,169 @@
package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"strings"

"github.com/kitech/qt.go/qtrt"
"github.com/kitech/qt.go/toolutil"
)

var file string
var filep string // file name without externsion

var cp = toolutil.NewCodePager()

const (
INSEC_NONE = iota
INSEC_RES_DATA
INSEC_RES_NAME
INSEC_RES_STRUCT
INSEC_DONE
)

// cgo version rcc compile. feature: decrease go compile time RAM usage(~72%, 2.8G=>0.8G). but depend on gcc.
// usage: go-rcc <rcc.qrc>
// depend on: /usr/bin/rcc
func main() {
log.SetFlags(log.Flags() | log.Lshortfile)
file = os.Args[1]
filep = path.Base(file)[0:strings.LastIndex(path.Base(file), ".")]
filep = qtrt.IfElseStr(path.Dir(file) == "", filep, path.Dir(file)+"/"+filep)
log.Println(file, filep)

scc, err := toolutil.RunCmdOut("rcc", file)
qtrt.ErrPrint(err, "rcc", file)
if err != nil {
os.Exit(1)
}

lines := strings.Split(scc, "\n")
log.Println("lines:", len(lines), "size:", len(scc))

cp.APf("header", "")
cp.APf("header", "/*")
cp.APf("header", "#include <string.h>")

hasRccData, hasRccName, hasRccStruct := false, false, false
insection := INSEC_NONE
for _, line := range lines {
line = strings.TrimSpace(line)

if strings.Contains(line, "qt_resource_data[]") {
insection = INSEC_RES_DATA
hasRccData = true
// cp.APf("body", "var qt_resource_data = []byte{")
cp.APf("body", line[7:])
continue
}

if strings.Contains(line, "qt_resource_name[]") {
insection = INSEC_RES_NAME
hasRccName = true
// cp.APf("body", "var qt_resource_name = []byte{")
cp.APf("body", line[7:])
continue
}

if strings.Contains(line, "qt_resource_struct[]") {
insection = INSEC_RES_STRUCT
hasRccStruct = true
// cp.APf("body", "var qt_resource_struct = []byte{")
cp.APf("body", line[7:])
continue
}

if strings.HasPrefix(line, "#ifdef QT_NAMESPACE") {
insection = INSEC_DONE
break
}

switch insection {
case INSEC_RES_DATA:
// do smth...
// log.Println(line)
transformMember(line)
case INSEC_RES_NAME:
onSetupUi(line)
case INSEC_RES_STRUCT:
onRetranslateUi(line)
}
}

// fix not exists
if !hasRccData {
cp.APf("body", "var qt_resource_data = []byte{} // empty")
}
if !hasRccName {
cp.APf("body", "var qt_resource_name = []byte{} // empty")
}
if !hasRccStruct {
cp.APf("body", "var qt_resource_struct = []byte{} // empty")
}

cp.APf("header2", "*/")
cp.APf("header2", "import \"C\"")
cp.APf("header2", "import \"unsafe\"")
cp.APf("header2", "// import \"github.com/kitech/qt.go/qtcore\"")
cp.APf("header2", "import \"github.com/kitech/qt.go/qtmock\"")

saveCode()
}

func transformMember(line string) {
home := os.Getenv("HOME")
line = strings.Replace(line, home, "/home/me", -1)
cp.APf("body", line)
}

func onSetupUi(line string) {
cp.APf("body", line)
}

func onRetranslateUi(line string) {
cp.APf("body", line)
}

func saveCode() {
var code string
var mod os.FileMode = 0644

// bool qRegisterResourceData (int, const unsigned char *, const unsigned char *, const unsigned char *).
// bool qUnregisterResourceData (int, const unsigned char *, const unsigned char *, const unsigned char *)
cp.APf("bodygo", "var qt_rcc_version = 0x2 // >= 5.8.0, else 0x1")
cp.APf("bodygo", "func qInitResources(){")
cp.APf("bodygo", " if C.sizeof_qt_resource_name > 0 {")
cp.APf("bodygo", " qtmock.QRegisterResourceData(qt_rcc_version, unsafe.Pointer(&C.qt_resource_struct[0]), unsafe.Pointer(&C.qt_resource_name[0]), unsafe.Pointer(&C.qt_resource_data[0]))")
cp.APf("bodygo", " }")
cp.APf("bodygo", "}")

cp.APf("bodygo", "func qCleanupResources(){")
cp.APf("bodygo", " if C.sizeof_qt_resource_name > 0 {")
cp.APf("bodygo", " qtmock.QUnregisterResourceData(qt_rcc_version, unsafe.Pointer(&C.qt_resource_struct[0]), unsafe.Pointer(&C.qt_resource_name[0]), unsafe.Pointer(&C.qt_resource_data[0]))")
cp.APf("bodygo", " }")
cp.APf("bodygo", "}")

cp.APf("bodygo", "func init(){qInitResources()}")

log.Printf("saving... %s_rc.go...\n", filep)
code = "package main\n"
code += cp.ExportAll()
savefile := fmt.Sprintf("%s_rc.go", filep)
err := ioutil.WriteFile(savefile, []byte(code), mod)
qtrt.ErrPrint(err, savefile)

// gofmt the code
gofmtPath, err := exec.LookPath("gofmt")
qtrt.ErrPrint(err)
cmd := exec.Command(gofmtPath, "-w", savefile)
err = cmd.Run()
qtrt.ErrPrint(err, cmd)
}

func colon2uline(s string) string { return strings.Replace(s, ":", "_", -1) }
func untitle(s string) string { return strings.ToLower(s[0:1]) + s[1:] }
14 changes: 10 additions & 4 deletions cmd/go-uic/main.go
Expand Up @@ -185,6 +185,7 @@ func onSetupUi(line string) {
reg6 := regexp.MustCompile(`(Q[A-Z][iconfont]+) ([iconfont0-9]+);`)
reg7 := regexp.MustCompile(`QSizePolicy (.+)\((.+), (.+)\);`)
reg8 := regexp.MustCompile(`(.+) = new (QSpacerItem)\(([0-9]+), ([0-9]+), (.+), (.+)\);`)
reg9 := regexp.MustCompile(`if \((.+)->([rowCountcolumn]+)\(\) < ([0-9]+)\)`) // if (tableWidget->rowCount() < 3)
reg100 := regexp.MustCompile(`QMetaObject::connectSlotsByName\((.+)\);`)
if reg100.MatchString(line) {
mats := reg100.FindAllStringSubmatch(line, -1)
Expand Down Expand Up @@ -258,7 +259,7 @@ func onSetupUi(line string) {
refmtsuf := ""
switch mats[0][2] {
case "Spacing", "HorizontalStretch", "VerticalStretch":
case "PointSize", "Weight", "ColumnCount": // do nothing
case "PointSize", "Weight", "ColumnCount", "RowCount": // do nothing
case "ContentsMargins", "CurrentIndex", "LineWidth":
case "MaxVisibleItems", "ModelColumn", "VerticalSpacing":
case "Orientation", "TextFormat":
Expand All @@ -284,10 +285,10 @@ func onSetupUi(line string) {
refmtval = strings.Replace(refmtval, "|", "|qtwidgets.", -1)
case "Geometry":
refmtval = strings.TrimRight(refmtval[6:], ")")
case "HorizontalScrollBarPolicy", "ContextMenuPolicy":
case "HorizontalScrollBarPolicy", "VerticalScrollBarPolicy", "ContextMenuPolicy":
refmtval = "qtcore." + strings.Replace(refmtval, ":", "_", -1)
case "SizeAdjustPolicy", "SizeConstraint", "FrameShape", "FrameShadow",
"SelectionBehavior":
"SelectionBehavior", "SelectionMode":
refmtval = "qtwidgets." + strings.Replace(refmtval, ":", "_", -1)
case "ResizeMode":
refmtval = "qtquickwidgets." + strings.Replace(refmtval, ":", "_", -1)
Expand All @@ -304,7 +305,7 @@ func onSetupUi(line string) {
refmtval = fmt.Sprintf("qtcore.NewQUrl_1(\"%s\", 0)", strings.Split(refmtval, "\"")[1])
case "HeightForWidth":
refmtval = "this." + strings.Replace(refmtval, "->", ".", -1)
case "HorizontalHeaderItem":
case "HorizontalHeaderItem", "VerticalHeaderItem":
refmtval = strings.Replace(refmtval, ",", ", this.", 1)
// refmtval = "false" // TODO label_x.SizePolicy().HasHeightForWidth() crash
// case "SizePolicy": // TODO 可能值有点问题,过滤掉设置setSizePolicy
Expand Down Expand Up @@ -392,6 +393,11 @@ func onSetupUi(line string) {
cp.APf("setupUi", " this.%s = qtwidgets.NewQSpacerItem(%s, %s, %s, %s)",
strings.Title(mats[0][1]), a0, a1, a2, a3)
cp.APf("setupUi", " qtrt.ReleaseOwnerToQt(this.%s)", strings.Title(mats[0][1]))
} else if reg9.MatchString(line) {
mats := reg9.FindAllStringSubmatch(line, -1)
log.Println(len(mats), mats, "//", line)
cp.APf("setupUi", " // if this.%s.%s() > %s // 119",
strings.Title(mats[0][1]), strings.Title(mats[0][2]), mats[0][3])
} else {
cp.APf("setupUi", fmt.Sprintf("// %s // 126", line))
}
Expand Down
2 changes: 1 addition & 1 deletion qtqt/qt.go
Expand Up @@ -140,7 +140,7 @@ func Recover(fn string) {
}

func Debug(fn ...interface{}) {
if strings.ToLower(os.Getenv("QT_DEBUG")) == "true" {
if strings.ToLower(os.Getenv("QT_DEBUG")) == "true" || runtime.GOARCH == "js" {
Logger.Println(fn...)
}
}
Expand Down
43 changes: 43 additions & 0 deletions qtqt/qt_ext.go
@@ -0,0 +1,43 @@
package qtqt

import "unsafe"

func DisconnectObject(cPtr unsafe.Pointer) {
signalsMutex.Lock()
if _, ok := signals[cPtr]; ok {
delete(signals, cPtr)
}
signalsMutex.Unlock()
Unregister(cPtr)
}

func DumpSignalsByObj(cPtr unsafe.Pointer) {
Debug("##############################\tSIGNALSTABLE_START\t##############################")
signalsMutex.Lock()
if entry, ok := signals[cPtr]; ok {
Debug(cPtr, entry)
}
signalsMutex.Unlock()
Debug("##############################\tSIGNALSTABLE_END\t##############################")
}

// get connected signals
func GetActiveSignals(cPtr unsafe.Pointer) (names []string) {
signalsMutex.Lock()
if _, ok := signals[cPtr]; ok {
for signame, _ := range signals[cPtr] {
names = append(names, signame)
}
}
signalsMutex.Unlock()
return
}

func CountSignalsByObj(cPtr unsafe.Pointer) (c int) {
signalsMutex.Lock()
if entry, ok := signals[cPtr]; ok {
c = len(entry)
}
signalsMutex.Unlock()
return
}
7 changes: 7 additions & 0 deletions qtqt/qt_js.go
@@ -0,0 +1,7 @@
// +build js

package qt

// import "github.com/gopherjs/gopherjs/js"

// var WASM = js.Global.Call("eval", "Module")
10 changes: 10 additions & 0 deletions qtrt/qdynslotobject.go
Expand Up @@ -138,6 +138,16 @@ func (*QDynSlotObject) _ConnectSwitch(src unsafe.Pointer, signame string, on boo
// TODO
func Disconnect(cobj CObjectITF, signame string) {
qt.DisconnectAllSignals(cobj.GetCthis(), signame)

}

// the same as QObject.Disconnect_2_()
func DisconnectAll(cobj CObjectITF) {
var convArg0 unsafe.Pointer
var convArg1 unsafe.Pointer
var convArg2 unsafe.Pointer
rv, err := InvokeQtFunc6("_ZNK7QObject10disconnectEPKcPKS_S1_", FFI_TYPE_POINTER, cobj.GetCthis(), convArg0, convArg1, convArg2)
ErrPrint(err, rv)
}

// or direct use qtcore.QObject_Connect
Expand Down

0 comments on commit 830054b

Please sign in to comment.