123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155 |
- package qt
- /*
- #include <stdlib.h>
- #include "qtbinding/qtbinding.h"
- */
- // #cgo LDFLAGS: -L./build -lqtbinding -Wl,-rpath=\$ORIGIN/
- import "C"
- import (
- _ "embed"
- "fmt"
- "errors"
- "unsafe"
- "reflect"
- "unicode"
- "strings"
- "kumachan/standalone/qt/cgohelper"
- )
- // QObject
- type Object struct {
- ptr unsafe.Pointer
- }
- func (obj Object) findChild(name string) (Object, bool) {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var ptr = C.QtObjectFindChild(obj.ptr, new_str(name))
- if ptr != nil {
- return Object{ptr}, true
- } else {
- return Object{}, false
- }
- }
- func (obj Object) FindChild(name string, v reflect.Value) error {
- var child, ok = obj.findChild(name)
- if !(ok) {
- return errors.New(fmt.Sprintf("child Object %s not found", name))
- }
- var err = child.ExactlyAssignTo(v)
- if err != nil {
- return fmt.Errorf("child %s: %w", name, err)
- }
- return nil
- }
- func (obj Object) ExactlyAssignTo(v reflect.Value) error {
- if v.Kind() != reflect.Ptr { panic("invalid argument") }
- var class = obj.GetClassName()
- var required = (func() string {
- var type_name = v.Elem().Type().Name()
- if strings.HasPrefix(type_name, "Custom") {
- return strings.TrimPrefix(type_name, "Custom")
- } else {
- return ("Q" + type_name)
- }
- })()
- if class == required {
- var target = v.Elem().Field(0)
- for !(reflect.TypeOf(obj).AssignableTo(target.Type())) {
- target = target.Field(0)
- }
- target.Set(reflect.ValueOf((interface{})(obj)))
- return nil
- } else {
- return errors.New(fmt.Sprintf(
- "class not matching: %s (%s)", class, required))
- }
- }
- func (obj Object) ExactlyAssignChildrenTo(v reflect.Value) error {
- if v.Kind() != reflect.Ptr { panic("invalid argument") }
- if v.Elem().Kind() != reflect.Struct { panic("invalid argument") }
- var struct_v = v.Elem()
- var struct_t = struct_v.Type()
- for i := 0; i < struct_t.NumField(); i += 1 {
- var field_name = struct_t.Field(i).Name
- var field_type = struct_t.Field(i).Type
- var t = ([] rune)(field_type.Name())
- t[0] = unicode.ToLower(t[0])
- var field_type_name = string(t)
- var child_name = (field_type_name + field_name)
- var err = obj.FindChild(child_name, struct_v.Field(i).Addr())
- if err != nil { return err }
- }
- return nil
- }
- func (obj Object) BlockSignals() (error, func()) {
- C.QtBlockSignals(obj.ptr, 1)
- return nil, func() {
- // NOTE: previous blocking state NOT recovered (always unblock)
- C.QtBlockSignals(obj.ptr, 0)
- }
- }
- func (obj Object) BlockCallbacks() (error, func()) {
- C.QtBlockCallbacks(obj.ptr, 1)
- return nil, func() {
- // NOTE: previous blocking state NOT recovered (always unblock)
- C.QtBlockCallbacks(obj.ptr, 0)
- }
- }
- func (obj Object) GetClassName() string {
- return ConsumeString(String(C.QtObjectGetClassName(obj.ptr)))
- }
- func (obj Object) getPropQtString(prop string) String {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var value = C.QtObjectGetPropString(obj.ptr, new_str(prop))
- return String(value)
- }
- func (obj Object) setPropQtString(prop string, val String) {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- C.QtObjectSetPropString(obj.ptr, new_str(prop), C.QtString(val))
- }
- func (obj Object) GetPropString(prop string) string {
- var value = obj.getPropQtString(prop)
- var value_runes = ConsumeString(value)
- return value_runes
- }
- func (obj Object) SetPropString(prop string, val string) {
- var q_val, del_str = NewString(val)
- defer del_str()
- obj.setPropQtString(prop, q_val)
- }
- func (obj Object) GetPropBool(prop string) bool {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var val = C.QtObjectGetPropBool(obj.ptr, new_str(prop))
- return getBool(val)
- }
- func (obj Object) SetPropBool(prop string, val bool) {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var int_val int
- if val {
- int_val = 1
- } else {
- int_val = 0
- }
- C.QtObjectSetPropBool(obj.ptr, new_str(prop), C.int(int_val))
- }
- func (obj Object) GetPropInt(prop string) int {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- return int(C.QtObjectGetPropInt(obj.ptr, new_str(prop)))
- }
- func (obj Object) SetPropInt(prop string, val int) {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- C.QtObjectSetPropInt(obj.ptr, new_str(prop), C.int(val))
- }
- // QWidget
- type Widget struct { Object }
- func (w Widget) Show() {
- C.QtWidgetShow(w.ptr)
- }
- func (w Widget) MoveToScreenCenter() {
- C.QtWidgetMoveToScreenCenter(w.ptr)
- }
- func (w Widget) FindChildAssumeWidget(name string) (Widget, bool) {
- var child, ok = w.findChild(name)
- if ok {
- return Widget{child}, true
- } else {
- return Widget{}, false
- }
- }
- func (w Widget) FindChildAssumeAction(name string) (Action, bool) {
- var child, ok = w.findChild(name)
- if ok {
- return Action{child}, true
- } else {
- return Action{}, false
- }
- }
- func (w Widget) SetEnabled(value bool) {
- w.SetPropBool("enabled", value)
- }
- func (w Widget) OnFocusOut(cb func()) func() {
- return Listen(w.Object, EventFocusOut(), false, func(_ Event) {
- cb()
- })
- }
- // Subclasses
- type _ struct {}
- type Action struct { Object }
- type MainWindow struct { Widget }
- type Dialog struct { Widget }
- type WebEngineView struct { Widget }
- type Label struct { Widget }
- type PushButton struct { Widget }
- type LineEdit struct { Widget }
- type PlainTextEdit struct { Widget }
- type ListWidget struct { Widget }
- type TreeWidget struct { Widget }
- type TextBrowser struct { Widget }
- type GroupBox struct { Widget }
- type WebWindow struct { MainWindow }
- type CustomWebView struct { WebEngineView }
- // Events
- type _ struct {}
- type Event C.QtEvent
- type EventKind uint
- func EventMove() EventKind { return EventKind(uint(C.QtEventMove)) }
- func EventResize() EventKind { return EventKind(uint(C.QtEventResize)) }
- func EventClose() EventKind { return EventKind(uint(C.QtEventClose)) }
- func EventFocusIn() EventKind { return EventKind(uint(C.QtEventFocusIn)) }
- func EventFocusOut() EventKind { return EventKind(uint(C.QtEventFocusOut)) }
- func EventDynamicPropertyChange() EventKind { return EventKind(uint(C.QtEventDynamicPropertyChange)) }
- func (ev Event) ResizeEventGetWidth() uint {
- return uint(C.QtResizeEventGetWidth(C.QtEvent(ev)))
- }
- func (ev Event) ResizeEventGetHeight() uint {
- return uint(C.QtResizeEventGetHeight(C.QtEvent(ev)))
- }
- func (ev Event) DynamicPropertyChangeEventGetPropertyName() string {
- return ConsumeString(String(C.QtDynamicPropertyChangeEventGetPropertyName(C.QtEvent(ev))))
- }
- // Utility Types
- type _ struct {}
- type String C.QtString
- type ByteArray C.QtByteArray
- type VariantMap C.QtVariantMap
- type Icon C.QtIcon
- type Pixmap C.QtPixmap
- type Point struct {
- X int
- Y int
- }
- type Color struct {
- H uint
- S uint
- L uint
- A uint
- }
- func getBool(number C.QtBool) bool {
- return (number != 0)
- }
- func makeQtBool(p bool) C.QtBool {
- if p {
- return C.int(int(1))
- } else {
- return C.int(int(0))
- }
- }
- func getPoint(p C.QtPoint) Point {
- return Point { X: int(C.QtPointGetX(p)), Y: int(C.QtPointGetY(p)) }
- }
- func makeQtPoint(p Point) C.QtPoint {
- return C.QtMakePoint(C.int(p.X), C.int(p.Y))
- }
- func NewString(data string) (String, func()) {
- var str C.QtString
- if len(data) > 0 {
- var hdr = (*reflect.StringHeader)(unsafe.Pointer(&data))
- var ptr = (*C.uint8_t)(unsafe.Pointer(hdr.Data))
- var size = (C.size_t)(len(data))
- str = C.QtNewStringUTF8(ptr, size)
- } else {
- str = C.QtNewStringUTF8(nil, 0)
- }
- return String(str), func() {
- C.QtDeleteString(str)
- }
- }
- func NewStringFromUtf8Binary(data ([] byte)) (String, func()) {
- var str C.QtString
- if len(data) > 0 {
- var ptr, size = addrlen(data)
- str = C.QtNewStringUTF8(ptr, size)
- } else {
- str = C.QtNewStringUTF8(nil, 0)
- }
- return String(str), func() {
- C.QtDeleteString(str)
- }
- }
- func copyString(str String) string {
- var q_str = (C.QtString)(str)
- var size16 = uint(C.QtStringUTF16Length(q_str))
- if size16 == 0 {
- return ""
- }
- var buf = make([] rune, size16)
- if size16 > 0 {
- var size32 = uint(C.QtStringWriteToUTF32Buffer(q_str,
- (*C.uint32_t)(unsafe.Pointer(&buf[0]))))
- buf = buf[:size32]
- }
- return string(buf)
- }
- func ConsumeString(str String) string {
- var go_str = copyString(str)
- C.QtDeleteString((C.QtString)(str))
- return go_str
- }
- func ConsumeByteArray(b ByteArray) ([] byte) {
- var buf = unsafe.Pointer(C.QtByteArrayGetBuffer(C.QtByteArray(b)))
- var size = int(C.QtByteArrayGetSize(C.QtByteArray(b)))
- var data = make([] byte, size, size)
- for i := 0; i < size; i += 1 {
- data[i] = *(*byte)(unsafe.Pointer(uintptr(buf) + uintptr(i)))
- }
- C.QtDeleteByteArray(C.QtByteArray(b))
- return data
- }
- func VariantMapGetString(m VariantMap, key String) string {
- var val = C.QtVariantMapGetString(C.QtVariantMap(m), C.QtString(key))
- var val_runes = ConsumeString(String(val))
- return val_runes
- }
- func VariantMapGetFloat(m VariantMap, key String) float64 {
- var val = C.QtVariantMapGetFloat(C.QtVariantMap(m), C.QtString(key))
- return float64(val)
- }
- func VariantMapGetBool(m VariantMap, key String) bool {
- var val = C.QtVariantMapGetBool(C.QtVariantMap(m), C.QtString(key))
- return getBool(val)
- }
- type ImageData struct {
- Bytes [] byte
- Format ImageDataFormat
- }
- type ImageDataFormat int
- const (
- PNG ImageDataFormat = iota
- JPEG
- )
- type iconPool (map[*ImageData] iconPoolItem)
- type iconPoolItem struct {
- icon Icon
- del func()
- }
- func makeIconPool() (iconPool, func()) {
- var p = make(iconPool)
- return p, func() {
- for _, item := range p {
- item.del()
- }
- }
- }
- func (p iconPool) GetIcon(img *ImageData) Icon {
- var cached, is_cached = p[img]
- if is_cached {
- return cached.icon
- } else {
- var new_icon, del_icon = (func() (Icon, func()) {
- if img != nil {
- var pm, del_pm = NewPixmap(img.Bytes, img.Format)
- defer del_pm()
- return NewIcon(pm)
- } else {
- return NewIconEmpty()
- }
- })()
- p[img] = iconPoolItem {
- icon: new_icon,
- del: del_icon,
- }
- return new_icon
- }
- }
- func NewPixmap(data ([] byte), format ImageDataFormat) (Pixmap, func()) {
- var buf, length = addrlen(data)
- if format == PNG {
- var pm = C.QtNewPixmapPNG(buf, length)
- return Pixmap(pm), func() { C.QtDeletePixmap(pm) }
- } else if format == JPEG {
- var pm = C.QtNewPixmapJPEG(buf, length)
- return Pixmap(pm), func() { C.QtDeletePixmap(pm) }
- } else {
- panic("qt pixmap: unsupported image format")
- }
- }
- func NewIcon(pm Pixmap) (Icon, func()) {
- var icon = C.QtNewIcon(C.QtPixmap(pm))
- return Icon(icon), func() {
- C.QtDeleteIcon(icon)
- }
- }
- func NewIconEmpty() (Icon, func()) {
- var icon = C.QtNewIconEmpty()
- return Icon(icon), func() {
- C.QtDeleteIcon(icon)
- }
- }
- // NOTE: should be called on main thread
- func Init() {
- C.QtInit()
- }
- // NOTE: should be called on main thread
- func Main() {
- C.QtMain()
- }
- // NOTE: should be called on main thread
- func Exit(code int32) {
- C.QtExit(C.int(code))
- }
- // Generate a UUID
- func UUID() string {
- var s = ConsumeString(String(C.QtNewUUID()))
- s = strings.TrimPrefix(s, "{")
- s = strings.TrimSuffix(s, "}")
- return s
- }
- // Invokes the `operation` callback in the Qt main thread.
- func CommitTask(operation func()) {
- var delete_callback (func() bool)
- var f = func() {
- operation()
- delete_callback()
- }
- callback, delete_callback := cgohelper.NewCallback(f)
- C.QtCommitTask(cgo_callback, C.size_t(callback))
- }
- // Loads `ui_xml` with `base_dir` and execute `k` in the Qt main thread.
- func LoadWidget(ui_xml string, base_dir string, k func(Widget)(error)) error {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var channel = make(chan error)
- CommitTask(func() {
- var ptr = C.QtLoadWidget(new_str(ui_xml), new_str(base_dir))
- if ptr != nil {
- channel <- k(Widget{Object{ptr}})
- } else {
- channel <- errors.New("failed to load widget from ui xml")
- }
- })
- return <- channel
- }
- // Makes a signal connection. `callback` will be called in the Qt main thread.
- func Connect(obj Object, signal string, callback func()) func() {
- var new_str, del_all_str = str_alloc()
- defer del_all_str()
- var cb, del_cb = cgohelper.NewCallback(callback)
- var channel = make(chan C.QtConnHandle)
- // Note: Although connect() is documented as "thread-safe",
- // it is not clear what will happen if the goroutine
- // is preempted and moved to another thread while
- // calling connect(), thus CommitTask() is used here.
- CommitTask(func() {
- var conn = C.QtConnect(obj.ptr, new_str(signal), cgo_callback, C.size_t(cb))
- channel <- conn
- })
- var conn = <- channel
- if getBool(C.QtIsConnectionValid(conn)) {
- return func() {
- var wait = make(chan struct{})
- CommitTask(func() {
- C.QtDisconnect(conn)
- // Note: Use CommitTask() to prevent pending callbacks
- // from being removed.
- CommitTask(func() {
- del_cb()
- })
- wait <- struct{}{}
- })
- <- wait
- }
- } else {
- panic("invalid connection")
- }
- }
- // Installs an event filter. `callback` will be called in the Qt main thread.
- func Listen(obj Object, kind EventKind, prevent bool, callback func(Event)) func() {
- var l C.QtEventListener
- var cb, del_cb = cgohelper.NewCallback(func() {
- var ev = C.QtGetCurrentEvent(l)
- callback(Event(ev))
- })
- var ok = make(chan struct{})
- CommitTask(func() {
- var prevent_flag = makeQtBool(prevent)
- l = C.QtAddEventListener(obj.ptr, C.size_t(kind), prevent_flag, cgo_callback, C.size_t(cb))
- ok <- struct{} {}
- })
- <- ok
- return func() {
- var wait = make(chan struct{})
- CommitTask(func() {
- C.QtRemoveEventListener(obj.ptr, l)
- // Note: Use CommitTask() to prevent pending callbacks
- // from being removed.
- CommitTask(func() {
- del_cb()
- })
- wait <- struct{}{}
- })
- <- wait
- }
- }
- func (a Action) OnTrigger(cb func()) func() {
- return Connect(a.Object, "triggered()", cb)
- }
- func (w MainWindow) OnClose(cb func()) func() {
- return Listen(w.Object, EventClose(), true, func(_ Event) {
- cb()
- })
- }
- func (w Dialog) OnClose(cb func()) func() {
- return Listen(w.Object, EventClose(), true, func(_ Event) {
- cb()
- })
- }
- func (w Dialog) OnRejected(cb func()) func() {
- return Connect(w.Object, "rejected()", cb)
- }
- func (w Dialog) Exec() {
- C.QtDialogExec(w.ptr)
- }
- func (w Dialog) Accept() {
- C.QtDialogAccept(w.ptr)
- }
- func (w Dialog) Reject() {
- C.QtDialogReject(w.ptr)
- }
- func (w Dialog) ShowModal() {
- C.QtDialogShowModal(w.ptr)
- }
- func (w Label) SetText(content string) {
- w.SetPropString("text", content)
- }
- func (w PushButton) OnClick(cb func()) func() {
- return Connect(w.Object, "clicked()", cb)
- }
- func (w LineEdit) SetText(content string) {
- _, unblock := w.BlockSignals()
- defer unblock()
- w.SetPropString("text", content)
- }
- func (w LineEdit) SetTextWithSignal(content string) {
- w.SetPropString("text", content)
- }
- func (w LineEdit) Text() string {
- return w.GetPropString("text")
- }
- func (w LineEdit) WatchText(cb func(string)) func() {
- return Connect(w.Object, "textChanged(const QString&)", func() {
- cb(w.Text())
- })
- }
- func (w PlainTextEdit) SetText(content string) {
- _, unblock := w.BlockSignals()
- defer unblock()
- w.SetPropString("plainText", content)
- }
- func (w PlainTextEdit) Text() string {
- return w.GetPropString("plainText")
- }
- func (w PlainTextEdit) WatchText(cb func(string)) func() {
- return Connect(w.Object, "textChanged()", func() {
- cb(w.Text())
- })
- }
- type ListWidgetItem struct {
- Key string
- Icon *ImageData
- Label string
- }
- func (w ListWidget) Clear() {
- C.QtListWidgetClear(w.ptr)
- }
- func (w ListWidget) CurrentItemKey() (string, bool) {
- if getBool(C.QtListWidgetHasCurrentItem(w.ptr)) {
- var raw_key = C.QtListWidgetGetCurrentItemKey(w.ptr)
- var key = ConsumeString(String(raw_key))
- return key, true
- } else {
- return "", false
- }
- }
- func (w ListWidget) WatchCurrentItemKey(cb func(string,bool)) func() {
- return Connect(w.Object, "currentItemChanged(QListWidgetItem*,QListWidgetItem*)", func() {
- cb(w.CurrentItemKey())
- })
- }
- func (w ListWidget) SetItems(items ([] ListWidgetItem), current *string) {
- var occurred_keys = make(map[string] bool)
- var current_key string
- var has_current = false
- for _, item := range items {
- if occurred_keys[item.Key] {
- panic(fmt.Sprintf("qt.ListWidget: duplicate item key %s", item.Key))
- }
- occurred_keys[item.Key] = true
- var is_current = (current != nil && item.Key == *current)
- if is_current {
- has_current = true
- current_key = item.Key
- }
- }
- var prev_current_key, prev_has_current = w.CurrentItemKey()
- (func() {
- if has_current {
- _, unblock := w.BlockSignals()
- defer unblock()
- }
- w.Clear()
- })()
- if has_current && prev_has_current {
- if current_key == prev_current_key {
- _, unblock := w.BlockSignals()
- defer unblock()
- }
- }
- var icon_pool, dispose = makeIconPool()
- defer dispose()
- for _, item := range items {
- var key, del_key = NewString(item.Key)
- var icon = icon_pool.GetIcon(item.Icon)
- var label, del_label = NewString(item.Label)
- var is_current = (has_current && (item.Key == current_key))
- C.QtListWidgetAddItem(
- w.ptr, C.QtString(key),
- C.QtIcon(icon), C.QtString(label),
- makeQtBool(is_current),
- )
- del_label()
- del_key()
- }
- }
- type TreeWidgetItem struct {
- Key string
- Icon *ImageData
- Labels [] string
- Children [] TreeWidgetItem
- }
- func (w TreeWidget) Clear() {
- C.QtTreeWidgetClear(w.ptr)
- }
- func (w TreeWidget) CurrentItemKey() (string, bool) {
- if getBool(C.QtTreeWidgetHasCurrentItem(w.ptr)) {
- var raw_key = C.QtTreeWidgetGetCurrentItemKey(w.ptr)
- var key = ConsumeString(String(raw_key))
- return key, true
- } else {
- return "", false
- }
- }
- func (w TreeWidget) WatchCurrentItemKey(cb func(string,bool)) func() {
- return Connect(w.Object, "currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)", func() {
- cb(w.CurrentItemKey())
- })
- }
- func (w TreeWidget) SetItems(items ([] TreeWidgetItem), current *string) {
- var occurred_keys = make(map[string] bool)
- var current_key string
- var has_current = false
- var check_keys func(TreeWidgetItem)
- check_keys = func(item TreeWidgetItem) {
- if occurred_keys[item.Key] {
- panic(fmt.Sprintf("qt.TreeWidget: duplicate item key %s", item.Key))
- }
- occurred_keys[item.Key] = true
- var is_current = (current != nil && item.Key == *current)
- if is_current {
- has_current = true
- current_key = item.Key
- }
- for _, child := range item.Children {
- check_keys(child)
- }
- }
- for _, item := range items {
- check_keys(item)
- }
- var prev_current_key, prev_has_current = w.CurrentItemKey()
- (func() {
- if has_current {
- _, unblock := w.BlockSignals()
- defer unblock()
- }
- w.Clear()
- })()
- if has_current && prev_has_current {
- if current_key == prev_current_key {
- _, unblock := w.BlockSignals()
- defer unblock()
- }
- }
- var column_count = int(C.QtTreeWidgetGetColumnCount(w.ptr))
- var icon_pool, dispose = makeIconPool()
- defer dispose()
- var add_item func(TreeWidgetItem, unsafe.Pointer)
- add_item = func(item TreeWidgetItem, parent unsafe.Pointer) {
- var key, del_key = NewString(item.Key)
- defer del_key()
- var icon = icon_pool.GetIcon(item.Icon)
- var labels = make([] String, column_count)
- var labels_del = make([] func(), column_count)
- defer (func() { for _, del := range labels_del { del() } })()
- if len(item.Labels) > column_count {
- panic("qt.TreeWidget: too many labels")
- }
- for i, label := range item.Labels {
- var label_q, label_del = NewString(label)
- labels[i] = label_q
- labels_del[i] = label_del
- }
- var is_current = (has_current && (item.Key == current_key))
- var labels_ptr unsafe.Pointer
- if len(labels) > 0 {
- labels_ptr = unsafe.Pointer(&labels[0])
- }
- var item_ptr = C.QtTreeWidgetAddItem(
- w.ptr, parent, C.QtString(key),
- C.QtIcon(icon), (*C.QtString)(labels_ptr),
- makeQtBool(is_current),
- )
- for _, child := range item.Children {
- add_item(child, item_ptr)
- }
- }
- for _, item := range items {
- add_item(item, nil)
- }
- }
- func (w TextBrowser) SetHtml(content string) {
- w.Object.SetPropString("html", content)
- }
- func (w WebEngineView) DisableContextMenu() {
- C.QtWebViewDisableContextMenu(w.ptr)
- }
- func (w WebEngineView) EnableLinkDelegation() {
- C.QtWebViewEnableLinkDelegation(w.ptr)
- }
- func (w WebEngineView) SetHTML(html String, base_url String) {
- C.QtWebViewSetHTML(w.ptr, C.QtString(html), C.QtString(base_url))
- }
- func (w WebEngineView) ScrollToAnchor(anchor String) {
- C.QtWebViewScrollToAnchor(w.ptr, C.QtString(anchor))
- }
- func (w WebEngineView) GetScroll() Point {
- return getPoint(C.QtWebViewGetScroll(w.ptr))
- }
- func (w WebEngineView) SetScroll(pos Point) {
- C.QtWebViewSetScroll(w.ptr, makeQtPoint(pos))
- }
- func WebGetAssetURL(key String) String {
- return String(C.WebGetAssetURL(C.QtString(key)))
- }
- func (view CustomWebView) LoadContent() {
- C.WebViewLoadContent(view.ptr)
- }
- func (view CustomWebView) RegisterAsset(key String, mime String, data ([] byte)) {
- var buf, length = addrlen(data)
- C.WebViewRegisterAsset(view.ptr, C.QtString(key), C.QtString(mime), buf, length)
- }
- func (view CustomWebView) InjectCSS(key String) {
- C.WebViewInjectCSS(view.ptr, C.QtString(key))
- }
- func (view CustomWebView) InjectJS(key String) {
- C.WebViewInjectJS(view.ptr, C.QtString(key))
- }
- func (view CustomWebView) InjectTTF(key String, family String, weight String, style String) {
- C.WebViewInjectTTF(view.ptr, C.QtString(key), C.QtString(family), C.QtString(weight), C.QtString(style))
- }
- func (view CustomWebView) PatchActualDOM(patch_data ([] byte)) {
- var str, del = NewStringFromUtf8Binary(patch_data)
- defer del()
- C.WebViewPatchActualDOM(view.ptr, C.QtString(str))
- }
- func (view CustomWebView) GetCurrentEventHandler() string {
- var raw_id = C.WebViewGetCurrentEventHandler(view.ptr)
- var id_str = ConsumeString(String(raw_id))
- return id_str
- }
- func (view CustomWebView) GetCurrentEventPayload() *WebEventPayload {
- return &WebEventPayload {
- VariantMap(C.WebViewGetCurrentEventPayload(view.ptr)),
- }
- }
- type WebEventPayload struct {
- Data VariantMap
- }
- func (ev *WebEventPayload) Consume(f func(*WebEventPayload) interface{}) interface{} {
- defer func() {
- C.QtDeleteVariantMap(C.QtVariantMap(ev.Data))
- } ()
- return f(ev)
- }
- func (ev *WebEventPayload) GetString(key string) string {
- var key_str, del = NewString(key)
- defer del()
- return VariantMapGetString(ev.Data, key_str)
- }
- func (ev *WebEventPayload) GetFloat(key string) float64 {
- var key_str, del = NewString(key)
- defer del()
- return VariantMapGetFloat(ev.Data, key_str)
- }
- func (ev *WebEventPayload) GetBool(key string) bool {
- var key_str, del = NewString(key)
- defer del()
- return VariantMapGetBool(ev.Data, key_str)
- }
- type WebWindowOptions struct {
- Title string
- Kind WindowKind
- Icon *ImageData
- Width uint
- Height uint
- CloseBtn bool
- Modal bool
- Debug bool
- }
- type WindowKind C.size_t
- func WindowKindOrdinary() WindowKind { return WindowKind(C.QtWindowKindOrdinary) }
- func WindowKindDialog() WindowKind { return WindowKind(C.QtWindowKindDialog) }
- func WindowKindPopup() WindowKind { return WindowKind(C.QtWindowKindPopup) }
- //go:embed default-window-icon.png
- var defaultWindowIconData ([] byte)
- func WebWindowCreate(parent Widget, opts WebWindowOptions) (WebWindow, CustomWebView, func()) {
- var title_str, del_title = NewString(opts.Title)
- defer del_title()
- var icon_data *ImageData
- if opts.Icon != nil {
- icon_data = opts.Icon
- } else {
- icon_data = &ImageData {
- Bytes: defaultWindowIconData,
- Format: PNG,
- }
- }
- var icon_pm, del_icon_pm = NewPixmap(icon_data.Bytes, icon_data.Format)
- defer del_icon_pm()
- var icon_obj, del_icon_obj = NewIcon(icon_pm)
- defer del_icon_obj()
- var w_ptr = C.WebWindowCreate (
- parent.ptr,
- C.size_t(opts.Kind),
- C.QtIcon(icon_obj),
- C.QtString(title_str),
- C.int(opts.Width),
- C.int(opts.Height),
- makeQtBool(opts.CloseBtn),
- makeQtBool(opts.Modal),
- makeQtBool(opts.Debug),
- )
- var view_ptr = C.WebWindowGetWebView(w_ptr)
- { var dialog = WebWindow{MainWindow{Widget{Object{w_ptr}}}}
- var view = CustomWebView{WebEngineView{Widget{Object{view_ptr}}}}
- var dispose = func() {
- var wait = make(chan struct{})
- CommitTask(func() {
- // behavior: hide and deleteLater
- C.WebWindowDispose(w_ptr)
- wait <- struct{}{}
- })
- <- wait
- }
- return dialog, view, dispose }
- }
- func (w WebWindow) Show(set_pos bool, x int32, y int32) {
- C.WebWindowShow(w.ptr, makeQtBool(set_pos), C.int(x), C.int(y))
- }
- func ColorDialog(parent Widget, title_ string, value Color) (Color, bool) {
- var title, del = NewString(title_)
- defer del()
- var ok = getBool(C.QtColorDialog(
- parent.ptr,
- C.QtString(title),
- (*C.size_t)(unsafe.Pointer(&(value.H))),
- (*C.size_t)(unsafe.Pointer(&(value.S))),
- (*C.size_t)(unsafe.Pointer(&(value.L))),
- (*C.size_t)(unsafe.Pointer(&(value.A))),
- ))
- if ok {
- return value, true
- } else {
- return Color {}, false
- }
- }
- type FileDialogOptions struct {
- Title string
- Cwd string
- Filter string
- }
- func fileDialogAdaptOptions(opts FileDialogOptions) (String, String, String, func()) {
- var title, del_title = NewString(opts.Title)
- var cwd, del_cwd = NewString(opts.Cwd)
- var filter, del_filter = NewString(opts.Filter)
- return title, cwd, filter, func() {
- del_title()
- del_cwd()
- del_filter()
- }
- }
- func FileDialogOpen(parent Widget, opts FileDialogOptions) string {
- var title, cwd, filter, del = fileDialogAdaptOptions(opts)
- defer del()
- var raw_path = C.QtFileDialogOpen(
- parent.ptr,
- C.QtString(title), C.QtString(cwd), C.QtString(filter),
- )
- return ConsumeString(String(raw_path))
- }
- func FileDialogOpenMultiple(parent Widget, opts FileDialogOptions) ([] string) {
- var title, cwd, filter, del = fileDialogAdaptOptions(opts)
- defer del()
- var raw_path_list = C.QtFileDialogOpenMultiple(
- parent.ptr,
- C.QtString(title), C.QtString(cwd), C.QtString(filter),
- )
- var path_list = make([] string, 0)
- var L = uint(C.QtStringListGetSize(raw_path_list))
- for i := uint(0); i < L; i += 1 {
- var raw_item = C.QtStringListGetItem(raw_path_list, C.size_t(i))
- var item = ConsumeString(String(raw_item))
- path_list = append(path_list, item)
- }
- C.QtDeleteStringList(raw_path_list)
- return path_list
- }
- func FileDialogSelectDirectory(parent Widget, opts FileDialogOptions) string {
- var title, cwd, _, del = fileDialogAdaptOptions(opts)
- defer del()
- var raw_path = C.QtFileDialogSelectDirectory(
- parent.ptr,
- C.QtString(title), C.QtString(cwd),
- )
- return ConsumeString(String(raw_path))
- }
- func FileDialogSave(parent Widget, opts FileDialogOptions) string {
- var title, cwd, filter, del = fileDialogAdaptOptions(opts)
- defer del()
- var raw_path = C.QtFileDialogSave(
- parent.ptr,
- C.QtString(title), C.QtString(cwd), C.QtString(filter),
- )
- return ConsumeString(String(raw_path))
- }
- func InputDialog(parent Widget, title string, prompt string, password bool, text *string) bool {
- var title_q, del_title = NewString(title)
- var prompt_q, del_content = NewString(prompt)
- var text_q, del_text = NewString(*text)
- defer del_title()
- defer del_content()
- defer del_text()
- var ok = getBool(C.QtInputDialog(
- parent.ptr,
- C.QtString(title_q),
- C.QtString(prompt_q),
- makeQtBool(password),
- C.QtString(text_q),
- ))
- if ok {
- *text = copyString(text_q)
- }
- return ok
- }
- func InputDialogInt32(parent Widget, title string, prompt string, min int32, max int32, step int32, value *int32) bool {
- var title_q, del_title = NewString(title)
- var prompt_q, del_content = NewString(prompt)
- var value_q C.int
- defer del_title()
- defer del_content()
- var ok = getBool(C.QtInputDialogInt(
- parent.ptr,
- C.QtString(title_q),
- C.QtString(prompt_q),
- C.int(min),
- C.int(max),
- C.int(step),
- &value_q,
- ))
- if ok {
- *value = int32(value_q)
- }
- return ok
- }
- func InputDialogFloat64(parent Widget, title string, prompt string, min float64, max float64, step float64, decimals int32, value *float64) bool {
- var title_q, del_title = NewString(title)
- var prompt_q, del_content = NewString(prompt)
- var value_q C.double
- defer del_title()
- defer del_content()
- var ok = getBool(C.QtInputDialogDouble(
- parent.ptr,
- C.QtString(title_q),
- C.QtString(prompt_q),
- C.double(min),
- C.double(max),
- C.double(step),
- C.int(decimals),
- &value_q,
- ))
- if ok {
- *value = float64(value_q)
- }
- return ok
- }
- func MessageBoxConfirm(parent Widget, title string, content string) bool {
- var title_q, del_title = NewString(title)
- var content_q, del_content = NewString(content)
- defer del_title()
- defer del_content()
- return getBool(C.QtMessageBoxConfirm(
- parent.ptr,
- C.QtString(title_q), C.QtString(content_q),
- ))
- }
- func MessageBoxError(parent Widget, title string, content string) {
- var title_q, del_title = NewString(title)
- var content_q, del_content = NewString(content)
- defer del_title()
- defer del_content()
- C.QtMessageBoxError(
- parent.ptr,
- C.QtString(title_q), C.QtString(content_q),
- )
- }
- type Kvdb struct {
- ptr unsafe.Pointer
- }
- func KvdbOpen(path string, exclusive bool) (Kvdb, error) {
- var path_q, del_path = NewString(path)
- defer del_path()
- var d Kvdb
- var ok = getBool(
- C.KvdbOpen(&(d.ptr), C.QtString(path_q), makeQtBool(exclusive)),
- )
- if ok {
- return d, nil
- } else {
- return Kvdb {}, fmt.Errorf("kvdb: failed to open database: %s", path)
- }
- }
- func (d Kvdb) Close() {
- C.KvdbClose(d.ptr)
- }
- func (d Kvdb) Insert(key string, category int32, value ([] byte)) error {
- var key_q, del_key = NewString(key)
- defer del_key()
- var vb, vl = addrlen(value)
- var ok = getBool(
- C.KvdbInsert(d.ptr, C.QtString(key_q), C.int(category), vb, vl),
- )
- if ok {
- return nil
- } else {
- return errors.New("kvdb: failed to insert record")
- }
- }
- func (d Kvdb) Remove(key string) error {
- var key_q, del_key = NewString(key)
- defer del_key()
- var ok = getBool(
- C.KvdbRemove(d.ptr, C.QtString(key_q)),
- )
- if ok {
- return nil
- } else {
- return errors.New("kvdb: failed to remove record")
- }
- }
- func (d Kvdb) Update(key string, value ([] byte)) error {
- var key_q, del_key = NewString(key)
- defer del_key()
- var vb, vl = addrlen(value)
- var ok = getBool(
- C.KvdbUpdate(d.ptr, C.QtString(key_q), vb, vl),
- )
- if ok {
- return nil
- } else {
- return errors.New("kvdb: failed to update record")
- }
- }
- func (d Kvdb) Lookup(key string) ([] byte, bool, error) {
- var key_q, del_key = NewString(key)
- defer del_key()
- var value ByteArray
- var found C.QtBool
- var ok = getBool(
- C.KvdbLookup(d.ptr, C.QtString(key_q),
- &found, (*C.QtByteArray)(&value)),
- )
- if ok {
- if getBool(found) {
- return ConsumeByteArray(value), true, nil
- } else {
- return nil, false, nil
- }
- } else {
- return nil, false, errors.New("kvdb: failed to lookup record")
- }
- }
- func (d Kvdb) ReadAll() (KvdbSelectQuery, error) {
- var q KvdbSelectQuery
- var ok = getBool(C.KvdbReadAll(d.ptr, (*C.KvdbSelectQuery)(&q)))
- if ok {
- return q, nil
- } else {
- return KvdbSelectQuery {}, errors.New("kvdb: failed to read records")
- }
- }
- func (d Kvdb) ReadCategory(category int) (KvdbSelectQuery, error) {
- var q KvdbSelectQuery
- var ok = getBool(
- C.KvdbReadCategory(d.ptr, C.int(category), (*C.KvdbSelectQuery)(&q)),
- )
- if ok {
- return q, nil
- } else {
- return KvdbSelectQuery {}, errors.New("kvdb: failed to read records")
- }
- }
- type KvdbSelectQuery C.KvdbSelectQuery
- func (q KvdbSelectQuery) Consume(item func(string, ([] byte))) {
- var key String
- var value ByteArray
- for getBool(C.KvdbSelectQueryNext(
- C.KvdbSelectQuery(q),
- (*C.QtString)(&key),
- (*C.QtByteArray)(&value),
- )) {
- item(ConsumeString(key), ConsumeByteArray(value))
- }
- C.KvdbDeleteSelectQuery(C.KvdbSelectQuery(q))
- }
|