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() {
|
||||
goPtr := pointer.Save(_v)
|
||||
_v.GmlObject_SetGoPointer(goPtr)
|
||||
_v.GmlObject_SetPointer(unsafe.Pointer(C.{{$struct.CBaseName}}_new(goPtr)))
|
||||
runtime.SetFinalizer(_v, func(_v *{{$struct.Name}}) {
|
||||
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()
|
||||
}
|
||||
|
||||
type listModelInitializer interface {
|
||||
initListModel(handler ListModelHandler)
|
||||
}
|
||||
|
||||
type ListModelHandler interface {
|
||||
RowCount() int
|
||||
Data(row int) interface{}
|
||||
@ -58,75 +62,86 @@ type ListModelHandler interface {
|
||||
type ListModel struct {
|
||||
Object
|
||||
|
||||
freed bool
|
||||
lm C.gml_list_model
|
||||
ptr unsafe.Pointer
|
||||
|
||||
ptr C.gml_list_model
|
||||
handler ListModelHandler
|
||||
}
|
||||
|
||||
func NewListModel(handler ListModelHandler) *ListModel {
|
||||
lm := &ListModel{handler: handler}
|
||||
func InitListModel(m interface{}) {
|
||||
lmi, ok := m.(listModelInitializer)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("failed to assert to list model"))
|
||||
}
|
||||
|
||||
lm.ptr = pointer.Save(lm)
|
||||
lm.lm = C.gml_list_model_new(lm.ptr)
|
||||
lm.GmlObject_SetPointer(unsafe.Pointer(lm.lm))
|
||||
handler, ok := m.(ListModelHandler)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("failed to assert to list model handler"))
|
||||
}
|
||||
|
||||
// Always free the C++ value.
|
||||
runtime.SetFinalizer(lm, freeListModel)
|
||||
lmi.initListModel(handler)
|
||||
}
|
||||
|
||||
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.
|
||||
// This should never happen is signalizes a fatal error.
|
||||
if lm.lm == nil {
|
||||
// This should never happen. It signalizes a fatal error.
|
||||
if lm.ptr == 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()) {
|
||||
RunMain(func() {
|
||||
// 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.
|
||||
dataModifier()
|
||||
// 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()) {
|
||||
RunMain(func() {
|
||||
// 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.
|
||||
dataModifier()
|
||||
// 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()) {
|
||||
RunMain(func() {
|
||||
// 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.
|
||||
dataModifier()
|
||||
// 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.
|
||||
dataModifier()
|
||||
// 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()) {
|
||||
RunMain(func() {
|
||||
// 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.
|
||||
dataModifier()
|
||||
// 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
|
||||
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
|
||||
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)
|
||||
// Release, because C++ is handling memory.
|
||||
|
||||
18
object.go
18
object.go
@ -35,12 +35,17 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type objectInitializer interface {
|
||||
GmlInit()
|
||||
}
|
||||
|
||||
type objectGetter interface {
|
||||
GmlObject() *Object
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
ptr unsafe.Pointer
|
||||
ptr unsafe.Pointer
|
||||
goPtr unsafe.Pointer
|
||||
}
|
||||
|
||||
func (o *Object) GmlObject_Pointer() unsafe.Pointer {
|
||||
@ -54,6 +59,17 @@ func (o *Object) GmlObject_SetPointer(ptr unsafe.Pointer) {
|
||||
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 {
|
||||
return o
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/desertbit/gml"
|
||||
_ "github.com/desertbit/gml/samples/hello_world/model"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@ -15,14 +15,4 @@ ApplicationWindow {
|
||||
font.pointSize: 24
|
||||
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.
|
||||
*/
|
||||
|
||||
package model
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/desertbit/gml"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
//#############//
|
||||
//### Slots ###//
|
||||
//#############//
|
||||
|
||||
var M *model
|
||||
|
||||
type model struct {
|
||||
*gml.ListModel
|
||||
gml.ListModel
|
||||
|
||||
_ struct {
|
||||
get func(row int) string `gml:"slot"`
|
||||
@ -54,12 +58,11 @@ func (m *model) Data(row int) interface{} {
|
||||
|
||||
func init() {
|
||||
M = &model{}
|
||||
M.ListModel = gml.NewListModel(M)
|
||||
M.GmlInit()
|
||||
gml.InitListModel(M)
|
||||
|
||||
err := gml.SetContextProperty("m", M)
|
||||
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 {
|
||||
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