cutego/internal/binding/templater/template_cpp.go

276 lines
6.8 KiB
Go
Raw Normal View History

2015-10-24 18:18:24 +03:00
package templater
import (
"bytes"
2015-10-24 18:18:24 +03:00
"fmt"
"sort"
2015-10-24 18:18:24 +03:00
"strings"
"github.com/therecipe/qt/internal/binding/parser"
)
func CppTemplate(module string) []byte {
var bb = new(bytes.Buffer)
defer bb.Reset()
2017-01-02 19:01:18 +03:00
if !parser.State.Moc {
2016-12-31 01:37:32 +03:00
module = "Qt" + module
}
if module == "QtCharts" || module == "QtDataVisualization" {
2017-01-02 19:01:18 +03:00
for _, classname := range sortedClassNamesForModule(module) {
fmt.Fprintf(bb, "typedef %v::%v %v;\n", module, classname, classname)
}
fmt.Fprint(bb, "\n")
}
2017-01-02 19:01:18 +03:00
for _, className := range sortedClassNamesForModule(module) {
var class = parser.State.ClassMap[className]
2017-01-02 19:01:18 +03:00
if class.IsSupported() {
2016-12-11 23:03:06 +03:00
var implementedVirtuals = make(map[string]struct{})
2017-01-02 19:01:18 +03:00
if class.HasCallbackFunctions() || parser.State.Moc {
//TODO: split
fmt.Fprintf(bb,
`class %v%v: public %v
{
%vpublic:
`,
func() string {
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
return ""
}
return "My"
}(),
class.Name,
func() string {
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
return class.GetBases()[0]
}
return class.Name
}(),
func() string {
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
var bb = new(bytes.Buffer)
defer bb.Reset()
fmt.Fprintln(bb, "Q_OBJECT")
for _, p := range class.Properties {
fmt.Fprintf(bb, "Q_PROPERTY(%v %v READ %v WRITE set%v NOTIFY %vChanged)\n", p.Output, p.Name,
func() string {
if p.Output == "bool" {
return "is" + strings.Title(p.Name)
}
return p.Name
}(), strings.Title(p.Name), p.Name)
}
return bb.String()
}
return ""
}())
if !hasUnimplementedPureVirtualFunctions(class.Name) {
for _, function := range class.Functions {
if function.Meta == parser.CONSTRUCTOR {
2017-01-02 19:01:18 +03:00
if function.IsSupported() {
var input = make([]string, len(function.Parameters))
for i, p := range function.Parameters {
input[i] = func() string {
if p.Name == "" {
return "v"
}
return p.Name
}()
}
fmt.Fprintf(bb, "\t%v%v(%v) : %v(%v) {};\n",
func() string {
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
return ""
}
return "My"
}(),
2016-12-11 23:03:06 +03:00
function.ClassName(),
strings.Split(strings.Split(function.Signature, "(")[1], ")")[0],
func() string {
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
return class.GetBases()[0]
}
2016-12-11 23:03:06 +03:00
return function.ClassName()
}(),
strings.Join(input, ", "),
)
}
}
}
}
//all class functions
for _, function := range class.Functions {
2016-12-11 23:03:06 +03:00
implementedVirtuals[fmt.Sprint(function.Fullname, function.OverloadNumber)] = struct{}{}
2017-01-02 19:01:18 +03:00
if function.IsSupported() {
if function.Virtual == parser.IMPURE || function.Virtual == parser.PURE || function.Meta == parser.SIGNAL || function.Meta == parser.SLOT {
2017-01-02 19:01:18 +03:00
if !(parser.State.Moc && function.Meta == parser.SLOT) {
2016-12-19 23:13:41 +03:00
var function = *function
function.SignalMode = parser.CALLBACK
fmt.Fprintf(bb, "\t%v\n", cppFunctionCallback(&function))
}
}
}
}
//virtual parent functions
for _, parentClassName := range class.GetAllBases() {
2017-01-02 19:01:18 +03:00
var parentClass = parser.State.ClassMap[parentClassName]
if parentClass.IsSupported() {
for _, function := range parentClass.Functions {
if _, exists := implementedVirtuals[fmt.Sprint(fmt.Sprintf("%v::%v", class.Name, function.Name), function.OverloadNumber)]; !exists {
2017-01-02 19:01:18 +03:00
if function.IsSupported() && function.Meta != parser.DESTRUCTOR {
var function = *function
function.Fullname = fmt.Sprintf("%v::%v", class.Name, function.Name)
2016-12-19 23:13:41 +03:00
function.SignalMode = parser.CALLBACK
if function.Virtual == parser.IMPURE || function.Virtual == parser.PURE || function.Meta == parser.SLOT {
2016-12-14 23:12:51 +03:00
implementedVirtuals[fmt.Sprint(fmt.Sprintf("%v::%v", class.Name, function.Name), function.OverloadNumber)] = struct{}{}
fmt.Fprintf(bb, "\t%v\n", cppFunctionCallback(&function))
}
}
}
}
2015-10-24 18:18:24 +03:00
}
}
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
for _, p := range class.Properties {
fmt.Fprintf(bb, "\t%v %v() { return _%v; };\n", p.Output, func() string {
if p.Output == "bool" {
return "is" + strings.Title(p.Name)
}
return p.Name
}(), p.Name)
fmt.Fprintf(bb, "\tvoid set%v(%v p) { if (p != _%v) { _%v = p; %vChanged(_%v); } };\n", strings.Title(p.Name), p.Output, p.Name, p.Name, p.Name, p.Name)
}
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))
}
}
fmt.Fprintln(bb, "public slots:")
for _, function := range class.Functions {
if function.Meta == parser.SLOT {
fmt.Fprintf(bb, "\t%v\n", cppFunctionCallback(function))
}
}
fmt.Fprintln(bb, "private:")
for _, p := range class.Properties {
fmt.Fprintf(bb, "\t%v _%v;\n", p.Output, p.Name)
}
}
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-12-14 23:12:51 +03:00
cTemplate(bb, class, cppEnum, cppFunction, "\n\n")
2015-10-24 18:18:24 +03:00
}
return preambleCpp(module, bb.Bytes())
2015-10-24 18:18:24 +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
#define private public
2015-10-24 18:18:24 +03:00
#include "%v.h"
#include "_cgo_export.h"
`,
2016-12-14 23:12:51 +03:00
buildTags(module),
2016-05-28 19:18:42 +03:00
func() string {
switch module {
case "QtAndroidExtras":
{
2017-01-02 19:01:18 +03:00
return fmt.Sprintf("%v_android", goModule(module))
}
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
}
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)
}
}
}(),
)
var classes = make([]string, 0)
2017-01-02 19:01:18 +03:00
for _, class := range parser.State.ClassMap {
if strings.Contains(string(input), class.Name) && !(strings.HasPrefix(class.Name, "Qt") || class.Module == parser.MOC) {
classes = append(classes, class.Name)
}
}
sort.Stable(sort.StringSlice(classes))
for _, class := range classes {
2016-06-19 05:24:38 +03:00
if class == "SailfishApp" {
fmt.Fprintln(bb, "#include <sailfishapp.h>")
} 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
}
fmt.Fprint(bb, "\n")
bb.Write(input)
2015-10-24 18:18:24 +03:00
2017-01-02 19:01:18 +03:00
if parser.State.Moc {
fmt.Fprintln(bb, "#include \"moc_moc.h\"")
}
return bb.Bytes()
2015-10-24 18:18:24 +03:00
}