2015-10-24 18:18:24 +03:00
|
|
|
package templater
|
|
|
|
|
|
|
|
import (
|
2016-04-28 20:43:44 +03:00
|
|
|
"bytes"
|
2017-01-29 20:43:19 +03:00
|
|
|
"crypto/sha1"
|
|
|
|
"encoding/hex"
|
2015-10-24 18:18:24 +03:00
|
|
|
"fmt"
|
2015-12-06 02:56:16 +03:00
|
|
|
"sort"
|
2015-10-24 18:18:24 +03:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/therecipe/qt/internal/binding/parser"
|
2017-01-27 22:22:58 +03:00
|
|
|
"github.com/therecipe/qt/internal/utils"
|
2015-10-24 18:18:24 +03:00
|
|
|
)
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
func CppTemplate(module string) []byte {
|
2017-01-27 22:22:58 +03:00
|
|
|
utils.Log.WithField("0_module", module).Debug("generating cpp")
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
var bb = new(bytes.Buffer)
|
|
|
|
defer bb.Reset()
|
2016-01-08 04:44:20 +03:00
|
|
|
|
2017-01-02 19:01:18 +03:00
|
|
|
if !parser.State.Moc {
|
2016-12-31 01:37:32 +03:00
|
|
|
module = "Qt" + module
|
2017-01-29 20:43:19 +03:00
|
|
|
} else {
|
2017-02-15 19:48:35 +03:00
|
|
|
for _, c := range parser.SortedClassNamesForModule(module, true) {
|
2017-01-29 20:43:19 +03:00
|
|
|
var class, e = parser.State.ClassMap[c]
|
|
|
|
if !e {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var typeMap = make(map[string]string)
|
|
|
|
for _, f := range class.Functions {
|
|
|
|
if parser.IsPackedMap(f.Output) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(f.Output))
|
|
|
|
typeMap[f.Output] = hex.EncodeToString(tHash.Sum(nil)[:3])
|
|
|
|
}
|
|
|
|
for _, p := range f.Parameters {
|
|
|
|
if parser.IsPackedMap(p.Value) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(p.Value))
|
|
|
|
typeMap[p.Value] = hex.EncodeToString(tHash.Sum(nil)[:3])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-03 01:01:46 +03:00
|
|
|
for _, p := range class.Properties {
|
|
|
|
if parser.IsPackedMap(p.Output) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(p.Output))
|
|
|
|
typeMap[p.Output] = hex.EncodeToString(tHash.Sum(nil)[:3])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 20:43:19 +03:00
|
|
|
for typ, hash := range typeMap {
|
|
|
|
fmt.Fprintf(bb, "typedef %v type%v;\n", typ, hash)
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 01:37:32 +03:00
|
|
|
}
|
|
|
|
|
2016-12-17 03:18:44 +03:00
|
|
|
if module == "QtCharts" || module == "QtDataVisualization" {
|
2017-02-15 19:48:35 +03:00
|
|
|
for _, classname := range parser.SortedClassNamesForModule(module, true) {
|
2016-12-17 03:18:44 +03:00
|
|
|
fmt.Fprintf(bb, "typedef %v::%v %v;\n", module, classname, classname)
|
|
|
|
}
|
|
|
|
fmt.Fprint(bb, "\n")
|
|
|
|
}
|
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
for _, className := range parser.SortedClassNamesForModule(module, true) {
|
2017-01-02 19:01:18 +03:00
|
|
|
var class = parser.State.ClassMap[className]
|
2016-04-16 19:48:26 +03:00
|
|
|
|
2017-01-02 19:01:18 +03:00
|
|
|
if class.IsSupported() {
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-02 19:01:18 +03:00
|
|
|
if class.HasCallbackFunctions() || parser.State.Moc {
|
2015-12-15 04:01:51 +03:00
|
|
|
|
2017-01-13 22:14:08 +03:00
|
|
|
//TODO: split
|
2016-04-28 20:43:44 +03:00
|
|
|
fmt.Fprintf(bb,
|
|
|
|
`class %v%v: public %v
|
|
|
|
{
|
|
|
|
%vpublic:
|
|
|
|
`,
|
|
|
|
func() string {
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Moc {
|
2016-04-28 20:43:44 +03:00
|
|
|
return ""
|
2016-01-04 04:05:31 +03:00
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
return "My"
|
|
|
|
}(),
|
|
|
|
|
|
|
|
class.Name,
|
|
|
|
|
|
|
|
func() string {
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Moc {
|
2016-04-28 20:43:44 +03:00
|
|
|
return class.GetBases()[0]
|
|
|
|
}
|
|
|
|
return class.Name
|
|
|
|
}(),
|
|
|
|
|
|
|
|
func() string {
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Moc {
|
2017-01-13 22:14:08 +03:00
|
|
|
var bb = new(bytes.Buffer)
|
|
|
|
defer bb.Reset()
|
|
|
|
fmt.Fprintln(bb, "Q_OBJECT")
|
|
|
|
|
|
|
|
for _, p := range class.Properties {
|
2017-02-03 01:01:46 +03:00
|
|
|
|
|
|
|
var ty = p.Output
|
|
|
|
if parser.IsPackedMap(p.Output) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(p.Output))
|
|
|
|
ty = fmt.Sprintf("type%v", hex.EncodeToString(tHash.Sum(nil)[:3]))
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(bb, "Q_PROPERTY(%v %v READ %v WRITE set%v NOTIFY %vChanged)\n", ty, p.Name,
|
2017-01-13 22:14:08 +03:00
|
|
|
func() string {
|
|
|
|
if p.Output == "bool" {
|
|
|
|
return "is" + strings.Title(p.Name)
|
|
|
|
}
|
|
|
|
return p.Name
|
|
|
|
}(), strings.Title(p.Name), p.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
return bb.String()
|
2016-04-28 20:43:44 +03:00
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}())
|
|
|
|
|
|
|
|
if !hasUnimplementedPureVirtualFunctions(class.Name) {
|
|
|
|
for _, function := range class.Functions {
|
2017-01-18 21:28:40 +03:00
|
|
|
if function.Meta != parser.CONSTRUCTOR || !function.IsSupported() {
|
|
|
|
continue
|
|
|
|
}
|
2016-01-04 04:05:31 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
var input = make([]string, len(function.Parameters))
|
|
|
|
for i, p := range function.Parameters {
|
|
|
|
input[i] = p.Name
|
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
var out = fmt.Sprintf("\t%v%v(%v) : %v(%v) {};\n",
|
|
|
|
func() string {
|
|
|
|
if parser.State.Moc {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return "My"
|
|
|
|
}(),
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
function.ClassName(),
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
strings.Split(strings.Split(function.Signature, "(")[1], ")")[0],
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
func() string {
|
|
|
|
if parser.State.Moc {
|
|
|
|
return class.GetBases()[0]
|
|
|
|
}
|
|
|
|
return function.ClassName()
|
|
|
|
}(),
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
strings.Join(input, ", "),
|
|
|
|
)
|
|
|
|
|
|
|
|
fmt.Fprint(bb, out)
|
2015-12-15 04:01:51 +03:00
|
|
|
}
|
2016-01-04 04:05:31 +03:00
|
|
|
}
|
2015-12-15 04:01:51 +03:00
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
//callback functions
|
|
|
|
var implementedVirtuals = make(map[string]struct{})
|
|
|
|
for i, parentClassName := range append([]string{class.Name}, class.GetAllBases()...) {
|
|
|
|
var parentClass, e = parser.State.ClassMap[parentClassName]
|
|
|
|
if !e || !parentClass.IsSupported() {
|
|
|
|
continue
|
2015-12-23 18:22:00 +03:00
|
|
|
}
|
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
for _, f := range parentClass.Functions {
|
|
|
|
var _, e = implementedVirtuals[f.Name+f.OverloadNumber]
|
|
|
|
if e || !f.IsSupported() {
|
|
|
|
continue
|
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
if parentClass.Module == parser.MOC && f.Meta == parser.SLOT {
|
|
|
|
continue
|
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
if i > 0 && (f.Meta == parser.CONSTRUCTOR || f.Meta == parser.DESTRUCTOR) {
|
|
|
|
continue
|
2015-12-06 02:56:16 +03:00
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
var f = *f
|
|
|
|
f.SignalMode = parser.CALLBACK
|
|
|
|
f.Fullname = fmt.Sprintf("%v::%v", class.Name, f.Name)
|
|
|
|
f.Fullname = fmt.Sprintf("%v::%v", f.FindDeepestImplementation(), f.Name)
|
|
|
|
|
|
|
|
if f.Meta == parser.SLOT || f.Meta == parser.SIGNAL || f.Virtual == parser.IMPURE || f.Virtual == parser.PURE {
|
|
|
|
implementedVirtuals[f.Name+f.OverloadNumber] = struct{}{}
|
|
|
|
fmt.Fprintf(bb, "\t%v\n", cppFunctionCallback(&f))
|
|
|
|
}
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
|
|
|
}
|
2016-01-04 04:05:31 +03:00
|
|
|
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Moc {
|
2017-01-13 22:14:08 +03:00
|
|
|
for _, p := range class.Properties {
|
2017-02-03 01:01:46 +03:00
|
|
|
|
|
|
|
var ty = p.Output
|
|
|
|
if parser.IsPackedMap(p.Output) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(p.Output))
|
|
|
|
ty = fmt.Sprintf("type%v", hex.EncodeToString(tHash.Sum(nil)[:3]))
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(bb, "\t%v %v() { return _%v; };\n", ty, func() string {
|
2017-01-13 22:14:08 +03:00
|
|
|
if p.Output == "bool" {
|
|
|
|
return "is" + strings.Title(p.Name)
|
|
|
|
}
|
|
|
|
return p.Name
|
|
|
|
}(), p.Name)
|
2017-02-03 01:01:46 +03:00
|
|
|
fmt.Fprintf(bb, "\tvoid set%v(%v p) { if (p != _%v) { _%v = p; %vChanged(_%v); } };\n", strings.Title(p.Name), ty, p.Name, p.Name, p.Name, p.Name)
|
2017-01-13 22:14:08 +03:00
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
fmt.Fprintln(bb, "signals:")
|
|
|
|
for _, function := range class.Functions {
|
|
|
|
if function.Meta == parser.SIGNAL {
|
|
|
|
var function = *function
|
|
|
|
function.Meta = parser.SLOT
|
|
|
|
fmt.Fprintf(bb, "\t%v;\n", cppFunctionCallbackHeader(&function))
|
2016-04-16 19:48:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
fmt.Fprintln(bb, "public slots:")
|
|
|
|
for _, function := range class.Functions {
|
|
|
|
if function.Meta == parser.SLOT {
|
|
|
|
fmt.Fprintf(bb, "\t%v\n", cppFunctionCallback(function))
|
2016-04-16 19:48:26 +03:00
|
|
|
}
|
|
|
|
}
|
2017-01-13 22:14:08 +03:00
|
|
|
|
|
|
|
fmt.Fprintln(bb, "private:")
|
|
|
|
for _, p := range class.Properties {
|
2017-02-03 01:01:46 +03:00
|
|
|
var ty = p.Output
|
|
|
|
if parser.IsPackedMap(p.Output) {
|
|
|
|
var tHash = sha1.New()
|
|
|
|
tHash.Write([]byte(p.Output))
|
|
|
|
ty = fmt.Sprintf("type%v", hex.EncodeToString(tHash.Sum(nil)[:3]))
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(bb, "\t%v _%v;\n", ty, p.Name)
|
2017-01-13 22:14:08 +03:00
|
|
|
}
|
2016-04-16 19:48:26 +03:00
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
fmt.Fprint(bb, "};\n\n")
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Moc {
|
2016-11-18 22:10:11 +03:00
|
|
|
fmt.Fprintf(bb, "Q_DECLARE_METATYPE(%v*)\n\n", class.Name)
|
|
|
|
}
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
|
2017-02-15 19:48:35 +03:00
|
|
|
if !parser.State.Moc {
|
|
|
|
cTemplate(bb, class, cppEnum, cppFunction, "\n\n", false)
|
|
|
|
}
|
2017-01-18 21:28:40 +03:00
|
|
|
}
|
2016-12-14 23:12:51 +03:00
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
if parser.State.Moc {
|
2017-02-15 19:48:35 +03:00
|
|
|
for _, className := range parser.SortedClassNamesForModule(module, true) {
|
|
|
|
var class = parser.State.ClassMap[className]
|
|
|
|
|
|
|
|
if class.IsSupported() {
|
|
|
|
cTemplate(bb, class, cppEnum, cppFunction, "\n\n", false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-18 21:28:40 +03:00
|
|
|
fmt.Fprintln(bb, "#include \"moc_moc.h\"")
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
return preambleCpp(module, bb.Bytes())
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
func preambleCpp(module string, input []byte) []byte {
|
|
|
|
var bb = new(bytes.Buffer)
|
|
|
|
defer bb.Reset()
|
2015-10-24 18:18:24 +03:00
|
|
|
|
2016-05-28 19:18:42 +03:00
|
|
|
fmt.Fprintf(bb, `%v
|
|
|
|
|
|
|
|
#define protected public
|
2016-04-28 20:43:44 +03:00
|
|
|
#define private public
|
2015-10-24 18:18:24 +03:00
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
#include "%v.h"
|
|
|
|
#include "_cgo_export.h"
|
2015-12-06 02:56:16 +03:00
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
`,
|
2017-01-18 21:28:40 +03:00
|
|
|
buildTags(module, false),
|
2016-05-28 19:18:42 +03:00
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
func() string {
|
|
|
|
switch module {
|
|
|
|
case "QtAndroidExtras":
|
|
|
|
{
|
2017-01-02 19:01:18 +03:00
|
|
|
return fmt.Sprintf("%v_android", goModule(module))
|
2016-04-28 20:43:44 +03:00
|
|
|
}
|
2016-01-04 04:05:31 +03:00
|
|
|
|
2016-06-19 05:24:38 +03:00
|
|
|
case "QtSailfish":
|
|
|
|
{
|
2017-01-02 19:01:18 +03:00
|
|
|
return fmt.Sprintf("%v_sailfish", goModule(module))
|
2016-06-19 05:24:38 +03:00
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
default:
|
|
|
|
{
|
2017-01-02 19:01:18 +03:00
|
|
|
if parser.State.Minimal {
|
|
|
|
return fmt.Sprintf("%v-minimal", goModule(module))
|
2016-10-14 20:06:35 +03:00
|
|
|
}
|
2017-01-02 19:01:18 +03:00
|
|
|
|
|
|
|
if parser.State.Moc {
|
|
|
|
return "moc"
|
|
|
|
}
|
|
|
|
|
|
|
|
return goModule(module)
|
2016-04-28 20:43:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
)
|
|
|
|
|
|
|
|
var classes = make([]string, 0)
|
2017-01-02 19:01:18 +03:00
|
|
|
for _, class := range parser.State.ClassMap {
|
2016-04-28 20:43:44 +03:00
|
|
|
if strings.Contains(string(input), class.Name) && !(strings.HasPrefix(class.Name, "Qt") || class.Module == parser.MOC) {
|
|
|
|
classes = append(classes, class.Name)
|
2016-04-16 19:48:26 +03:00
|
|
|
}
|
2015-12-06 02:56:16 +03:00
|
|
|
}
|
2016-04-28 20:43:44 +03:00
|
|
|
sort.Stable(sort.StringSlice(classes))
|
2015-12-06 02:56:16 +03:00
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
for _, class := range classes {
|
2016-06-19 05:24:38 +03:00
|
|
|
if class == "SailfishApp" {
|
2017-01-22 20:34:39 +03:00
|
|
|
fmt.Fprint(bb, "#include <sailfishapp.h>\n")
|
2016-06-19 05:24:38 +03:00
|
|
|
} else {
|
2016-12-11 23:03:06 +03:00
|
|
|
if strings.HasPrefix(class, "Q") && !(class == "QBluetooth" || class == "QDBus" || class == "QCss" || class == "QPdf" || class == "QSsl" || class == "QPrint" || class == "QScript" || class == "QSql" || class == "QTest" || class == "QWebSocketProtocol") {
|
2016-12-01 20:35:01 +03:00
|
|
|
fmt.Fprintf(bb, "#include <%v>\n", class)
|
|
|
|
}
|
2016-06-19 05:24:38 +03:00
|
|
|
}
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|
2017-02-16 18:38:33 +03:00
|
|
|
|
|
|
|
if parser.State.Minimal {
|
|
|
|
if module == "QtCore" {
|
|
|
|
fmt.Fprint(bb, "#include <QObject>\n")
|
|
|
|
} else if module == "QtNetwork" {
|
|
|
|
fmt.Fprint(bb, "#include <QSslError>\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
fmt.Fprint(bb, "\n")
|
|
|
|
|
|
|
|
bb.Write(input)
|
2015-10-24 18:18:24 +03:00
|
|
|
|
2016-04-28 20:43:44 +03:00
|
|
|
return bb.Bytes()
|
2015-10-24 18:18:24 +03:00
|
|
|
}
|