mirror of
https://github.com/gosticks/gml.git
synced 2025-10-16 12:05:33 +00:00
new listmodel syntax. Also added code gen support to list models
This commit is contained in:
parent
b78c4fc6b7
commit
f5ca35ce27
@ -89,6 +89,7 @@ func init() {
|
|||||||
|
|
||||||
func (_v *{{$struct.Name}}) GmlInit() {
|
func (_v *{{$struct.Name}}) GmlInit() {
|
||||||
goPtr := pointer.Save(_v)
|
goPtr := pointer.Save(_v)
|
||||||
|
_v.GmlObject_SetGoPointer(goPtr)
|
||||||
_v.GmlObject_SetPointer(unsafe.Pointer(C.{{$struct.CBaseName}}_new(goPtr)))
|
_v.GmlObject_SetPointer(unsafe.Pointer(C.{{$struct.CBaseName}}_new(goPtr)))
|
||||||
runtime.SetFinalizer(_v, func(_v *{{$struct.Name}}) {
|
runtime.SetFinalizer(_v, func(_v *{{$struct.Name}}) {
|
||||||
C.{{$struct.CBaseName}}_free((C.{{$struct.CBaseName}})(_v.GmlObject_Pointer()))
|
C.{{$struct.CBaseName}}_free((C.{{$struct.CBaseName}})(_v.GmlObject_Pointer()))
|
||||||
|
|||||||
93
listmodel.go
93
listmodel.go
@ -50,6 +50,10 @@ func init() {
|
|||||||
C.gml_list_model_init()
|
C.gml_list_model_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type listModelInitializer interface {
|
||||||
|
initListModel(handler ListModelHandler)
|
||||||
|
}
|
||||||
|
|
||||||
type ListModelHandler interface {
|
type ListModelHandler interface {
|
||||||
RowCount() int
|
RowCount() int
|
||||||
Data(row int) interface{}
|
Data(row int) interface{}
|
||||||
@ -58,75 +62,86 @@ type ListModelHandler interface {
|
|||||||
type ListModel struct {
|
type ListModel struct {
|
||||||
Object
|
Object
|
||||||
|
|
||||||
freed bool
|
ptr C.gml_list_model
|
||||||
lm C.gml_list_model
|
|
||||||
ptr unsafe.Pointer
|
|
||||||
|
|
||||||
handler ListModelHandler
|
handler ListModelHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListModel(handler ListModelHandler) *ListModel {
|
func InitListModel(m interface{}) {
|
||||||
lm := &ListModel{handler: handler}
|
lmi, ok := m.(listModelInitializer)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("failed to assert to list model"))
|
||||||
|
}
|
||||||
|
|
||||||
lm.ptr = pointer.Save(lm)
|
handler, ok := m.(ListModelHandler)
|
||||||
lm.lm = C.gml_list_model_new(lm.ptr)
|
if !ok {
|
||||||
lm.GmlObject_SetPointer(unsafe.Pointer(lm.lm))
|
panic(fmt.Errorf("failed to assert to list model handler"))
|
||||||
|
}
|
||||||
|
|
||||||
// Always free the C++ value.
|
lmi.initListModel(handler)
|
||||||
runtime.SetFinalizer(lm, freeListModel)
|
}
|
||||||
|
|
||||||
|
func (lm *ListModel) initListModel(handler ListModelHandler) {
|
||||||
|
lm.handler = handler
|
||||||
|
|
||||||
|
// If signals, slots or properties are defined on the model handler,
|
||||||
|
// then use the generated C++ type by calling GmlInit...
|
||||||
|
// Otherwise this is a standalone ListModel.
|
||||||
|
switch ht := lm.handler.(type) {
|
||||||
|
case objectInitializer:
|
||||||
|
ht.GmlInit()
|
||||||
|
lm.ptr = (C.gml_list_model)(lm.GmlObject_Pointer())
|
||||||
|
|
||||||
|
default:
|
||||||
|
handlerGoPtr := pointer.Save(lm.handler)
|
||||||
|
lm.GmlObject_SetGoPointer(handlerGoPtr)
|
||||||
|
|
||||||
|
lm.ptr = C.gml_list_model_new(handlerGoPtr)
|
||||||
|
lm.GmlObject_SetPointer(unsafe.Pointer(lm.ptr))
|
||||||
|
|
||||||
|
// Always cleanup.
|
||||||
|
runtime.SetFinalizer(lm, func(lm *ListModel) {
|
||||||
|
C.gml_list_model_free(lm.ptr)
|
||||||
|
pointer.Unref(handlerGoPtr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Check if something failed.
|
// Check if something failed.
|
||||||
// This should never happen is signalizes a fatal error.
|
// This should never happen. It signalizes a fatal error.
|
||||||
if lm.lm == nil {
|
if lm.ptr == nil {
|
||||||
panic(fmt.Errorf("failed to create gml list model: C pointer is nil"))
|
panic(fmt.Errorf("failed to create gml list model: C pointer is nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return lm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lm *ListModel) Free() {
|
|
||||||
freeListModel(lm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func freeListModel(lm *ListModel) {
|
|
||||||
if lm.freed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lm.freed = true
|
|
||||||
C.gml_list_model_free(lm.lm)
|
|
||||||
pointer.Unref(lm.ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *ListModel) Reset(dataModifier func()) {
|
func (lm *ListModel) Reset(dataModifier func()) {
|
||||||
RunMain(func() {
|
RunMain(func() {
|
||||||
// Begin the reset operation.
|
// Begin the reset operation.
|
||||||
C.gml_list_model_begin_reset_model(lm.lm)
|
C.gml_list_model_begin_reset_model(lm.ptr)
|
||||||
// Perform the data modifications.
|
// Perform the data modifications.
|
||||||
dataModifier()
|
dataModifier()
|
||||||
// End the reset operation.
|
// End the reset operation.
|
||||||
C.gml_list_model_end_reset_model(lm.lm)
|
C.gml_list_model_end_reset_model(lm.ptr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *ListModel) Insert(row, count int, dataModifier func()) {
|
func (lm *ListModel) Insert(row, count int, dataModifier func()) {
|
||||||
RunMain(func() {
|
RunMain(func() {
|
||||||
// Begin the insert operation.
|
// Begin the insert operation.
|
||||||
C.gml_list_model_begin_insert_rows(lm.lm, C.int(row), C.int(count))
|
C.gml_list_model_begin_insert_rows(lm.ptr, C.int(row), C.int(count))
|
||||||
// Perform the data modification.
|
// Perform the data modification.
|
||||||
dataModifier()
|
dataModifier()
|
||||||
// End the insert operation.
|
// End the insert operation.
|
||||||
C.gml_list_model_end_insert_rows(lm.lm)
|
C.gml_list_model_end_insert_rows(lm.ptr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *ListModel) Move(row, count, dstRow int, dataModifier func()) {
|
func (lm *ListModel) Move(row, count, dstRow int, dataModifier func()) {
|
||||||
RunMain(func() {
|
RunMain(func() {
|
||||||
// Begin the move operation.
|
// Begin the move operation.
|
||||||
C.gml_list_model_begin_move_rows(lm.lm, C.int(row), C.int(count), C.int(dstRow))
|
C.gml_list_model_begin_move_rows(lm.ptr, C.int(row), C.int(count), C.int(dstRow))
|
||||||
// Perform the data modification.
|
// Perform the data modification.
|
||||||
dataModifier()
|
dataModifier()
|
||||||
// End the move operation.
|
// End the move operation.
|
||||||
C.gml_list_model_end_move_rows(lm.lm)
|
C.gml_list_model_end_move_rows(lm.ptr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,18 +150,18 @@ func (lm *ListModel) Reload(row, count int, dataModifier func()) {
|
|||||||
// Perform the data modification.
|
// Perform the data modification.
|
||||||
dataModifier()
|
dataModifier()
|
||||||
// Signal the changed operation.
|
// Signal the changed operation.
|
||||||
C.gml_list_model_rows_data_changed(lm.lm, C.int(row), C.int(count))
|
C.gml_list_model_rows_data_changed(lm.ptr, C.int(row), C.int(count))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *ListModel) Remove(row, count int, dataModifier func()) {
|
func (lm *ListModel) Remove(row, count int, dataModifier func()) {
|
||||||
RunMain(func() {
|
RunMain(func() {
|
||||||
// Begin the remove operation.
|
// Begin the remove operation.
|
||||||
C.gml_list_model_begin_remove_rows(lm.lm, C.int(row), C.int(count))
|
C.gml_list_model_begin_remove_rows(lm.ptr, C.int(row), C.int(count))
|
||||||
// Perform the data modification.
|
// Perform the data modification.
|
||||||
dataModifier()
|
dataModifier()
|
||||||
// End the remove operation.
|
// End the remove operation.
|
||||||
C.gml_list_model_end_remove_rows(lm.lm)
|
C.gml_list_model_end_remove_rows(lm.ptr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,12 +171,12 @@ func (lm *ListModel) Remove(row, count int, dataModifier func()) {
|
|||||||
|
|
||||||
//export gml_list_model_row_count_go_slot
|
//export gml_list_model_row_count_go_slot
|
||||||
func gml_list_model_row_count_go_slot(goPtr unsafe.Pointer) C.int {
|
func gml_list_model_row_count_go_slot(goPtr unsafe.Pointer) C.int {
|
||||||
return C.int((pointer.Restore(goPtr)).(*ListModel).handler.RowCount())
|
return C.int((pointer.Restore(goPtr)).(ListModelHandler).RowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
//export gml_list_model_data_go_slot
|
//export gml_list_model_data_go_slot
|
||||||
func gml_list_model_data_go_slot(goPtr unsafe.Pointer, row C.int) C.gml_variant {
|
func gml_list_model_data_go_slot(goPtr unsafe.Pointer, row C.int) C.gml_variant {
|
||||||
data := (pointer.Restore(goPtr)).(*ListModel).handler.Data(int(row))
|
data := (pointer.Restore(goPtr)).(ListModelHandler).Data(int(row))
|
||||||
|
|
||||||
v := ToVariant(data)
|
v := ToVariant(data)
|
||||||
// Release, because C++ is handling memory.
|
// Release, because C++ is handling memory.
|
||||||
|
|||||||
18
object.go
18
object.go
@ -35,12 +35,17 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type objectInitializer interface {
|
||||||
|
GmlInit()
|
||||||
|
}
|
||||||
|
|
||||||
type objectGetter interface {
|
type objectGetter interface {
|
||||||
GmlObject() *Object
|
GmlObject() *Object
|
||||||
}
|
}
|
||||||
|
|
||||||
type Object struct {
|
type Object struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
|
goPtr unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Object) GmlObject_Pointer() unsafe.Pointer {
|
func (o *Object) GmlObject_Pointer() unsafe.Pointer {
|
||||||
@ -54,6 +59,17 @@ func (o *Object) GmlObject_SetPointer(ptr unsafe.Pointer) {
|
|||||||
o.ptr = ptr
|
o.ptr = ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Object) GmlObject_GoPointer() unsafe.Pointer {
|
||||||
|
if o.goPtr == nil {
|
||||||
|
panic(fmt.Errorf("gml.Object go pointer is nil: did you call GmlInit()?"))
|
||||||
|
}
|
||||||
|
return o.goPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) GmlObject_SetGoPointer(goPtr unsafe.Pointer) {
|
||||||
|
o.goPtr = goPtr
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Object) GmlObject() *Object {
|
func (o *Object) GmlObject() *Object {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/desertbit/gml"
|
"github.com/desertbit/gml"
|
||||||
_ "github.com/desertbit/gml/samples/hello_world/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@ -15,14 +15,4 @@ ApplicationWindow {
|
|||||||
font.pointSize: 24
|
font.pointSize: 24
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
|
||||||
anchors.fill: parent
|
|
||||||
delegate: Text {
|
|
||||||
color: "red"
|
|
||||||
text: display
|
|
||||||
}
|
|
||||||
model: m
|
|
||||||
Component.onCompleted: console.log(m.get(5))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
5
samples/list_model/.gitignore
vendored
Normal file
5
samples/list_model/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/build
|
||||||
|
/list_model
|
||||||
|
gml_gen*
|
||||||
|
*.qrc
|
||||||
|
|
||||||
36
samples/list_model/main.go
Normal file
36
samples/list_model/main.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* GML - Go QML
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Roland Singer <roland.singer[at]desertbit.com>
|
||||||
|
* Copyright (c) 2019 Sebastian Borchers <sebastian[at]desertbit.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/desertbit/gml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
gml.ExecExit("qrc:/qml/app.qml")
|
||||||
|
}
|
||||||
@ -25,19 +25,23 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package model
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/desertbit/gml"
|
"github.com/desertbit/gml"
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//#############//
|
||||||
|
//### Slots ###//
|
||||||
|
//#############//
|
||||||
|
|
||||||
var M *model
|
var M *model
|
||||||
|
|
||||||
type model struct {
|
type model struct {
|
||||||
*gml.ListModel
|
gml.ListModel
|
||||||
|
|
||||||
_ struct {
|
_ struct {
|
||||||
get func(row int) string `gml:"slot"`
|
get func(row int) string `gml:"slot"`
|
||||||
@ -54,12 +58,11 @@ func (m *model) Data(row int) interface{} {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
M = &model{}
|
M = &model{}
|
||||||
M.ListModel = gml.NewListModel(M)
|
gml.InitListModel(M)
|
||||||
M.GmlInit()
|
|
||||||
|
|
||||||
err := gml.SetContextProperty("m", M)
|
err := gml.SetContextProperty("m", M)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("init")
|
log.Fatalln("failed to set model context property")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,5 +71,5 @@ func init() {
|
|||||||
//#############//
|
//#############//
|
||||||
|
|
||||||
func (m *model) get(row int) string {
|
func (m *model) get(row int) string {
|
||||||
return "this is a test, lol"
|
return "slot get called"
|
||||||
}
|
}
|
||||||
22
samples/list_model/qml/app.qml
Normal file
22
samples/list_model/qml/app.qml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import QtQuick 2.11
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
|
||||||
|
ApplicationWindow {
|
||||||
|
id: window
|
||||||
|
width: 300
|
||||||
|
height: 300
|
||||||
|
visible: true
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
anchors.fill: parent
|
||||||
|
delegate: Text {
|
||||||
|
color: "red"
|
||||||
|
text: display
|
||||||
|
font.pointSize: 24
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
model: m
|
||||||
|
Component.onCompleted: console.log(m.get(5))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user