Open eivindro opened 10 years ago
For the record, working with model views is already possible and convenient today via the indexed mechanism.
Here is a good example:
Let's keep this bug open, though, as there might be advantages in supporting an implementation of QAbstractItemModel.
Regarding TableView
s, I had the problem, that role
did not work. (At least I could not find out how to get it to work. So I use this workaround:
TableView {
model: contactList.len
TableViewColumn {
title: qsTr("Name")
delegate: Item {
Text {
anchors.verticalCenter: parent.verticalCenter
color: styleData.textColor
elide: styleData.elideMode
text: contactList.name(styleData.row)
}
}
}
}
Is there an efficient way to remove/add a single item out of 1000 with the index model?
Just setting model = array.length
will re-create all 999/1001 elements rather than just tweak the single one that was changed.
To answer myself; yes there is. For example:
ListModel {
id: myModel
}
...
myModel.append({"itemId":rs.item(i).id});
itemId
will then exist as a variable in the delagate component that is created as a result. myModel
can be located from go so that its functions can be called from there if one wants to.
@quarnster I am trying to figure out what you did here. Is there any chance you could elaborate?
Sure, here's a quick freestanding example:
package main
import (
"gopkg.in/qml.v1"
"log"
)
var qmlFile = `
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.0
ApplicationWindow {
id: main
width: 800
height: 600
function validate() {
for (var i = 0; i < gomodel.len(); i++) {
var godata = gomodel.get(i);
var qmldata = lmodel.get(i).goitem;
// Note that "godata" and "qmldata" are not
// pointing to the same address though...
if (godata.text != qmldata.text) {
console.log(godata.text, qmldata.text);
}
}
}
function insert(i, data) {
lmodel.insert(i, {"goitem": data});
validate();
}
function removed(i) {
lmodel.remove(i);
validate();
}
ListModel {
id: lmodel
}
ColumnLayout {
Button {
text: "add"
onClicked: {
console.log("adding!!");
gomodel.add("Item " + Math.floor(Math.random()*1024));
}
}
Button {
text: "remove"
onClicked: {
console.log("removing!!");
gomodel.remove(lv.currentIndex);
}
}
ScrollView {
Layout.fillHeight: true
ListView {
id: lv
model: lmodel
height: contentHeight
delegate: Rectangle {
id: item
color: lv.currentIndex == index ? Qt.rgba(0.9,0.9,0.9,1.0) : "white"
width: Math.max(t.width, parent.width)
height: t.height
clip: true
Text {
id: t
text: goitem.text
}
MouseArea {
anchors.fill: parent
onClicked: lv.currentIndex = index
}
}
}
}
}
}
`
var window *qml.Window
type (
Item struct {
Text string
}
Model struct {
items []*Item
}
)
func (m *Model) Add(text string) {
i := len(m.items)
m.items = append(m.items, &Item{text})
window.Call("insert", i, m.items[i])
}
func (m *Model) Remove(i int) {
copy(m.items[i:], m.items[i+1:])
m.items = m.items[:len(m.items)-1]
window.Call("removed", i)
}
func (m *Model) Len() int {
return len(m.items)
}
func (m *Model) Get(i int) *Item {
return m.items[i]
}
func main() {
model := &Model{}
log.Println(qml.Run(func() error {
engine := qml.NewEngine()
defer engine.Destroy()
engine.Context().SetVar("gomodel", model)
component, err := engine.LoadString("main.qml", qmlFile)
if err != nil {
return err
}
window = component.CreateWindow(nil)
window.Show()
window.Wait()
return nil
}))
}
@quarnster Thanks for the response. That window.Call in Add is very clever! I would not have thought of that.
This should be added to the delegate dir of the examples.
Though putting things through a QML ListModel is workable, in my experience that won't perform anything near the QAbstractItemModel, that can efficiently signal changes in the model directly to the QML ListView, see e.g. beginInsertRows/endInsertRows. This is especially true if you are doing insertion/removal of mutliple items at once. So having a way to implement this QAbstractItemlModel interface in go would be really cool :D
Ohh I just saw that there is already a list-model branch with some work in progress for this, anything we can do to help?
I'm not sure. The main blocker is researching in depth how to implement these interfaces in a sane way, and the reason it's taking so long is because the interface seems extensive and non-trivial on the C++ side. Whatever we do needs to be straightforward and sensible, and I haven't managed to work on it enough to get to that point.
Niemeyer we should get in contact. I'm the author of the DOtherSide project that bring Qml bindings for Nim and D. I worked on this topic maybe i can share my implementation and see if it works for you too.
Also lemme know if there is anything i can do to help. I have been using QAbstractItemList for interfacing C++ and QML for several years by now (since sometime from Qt 4.7beta). I'm on IRC freenode (as pjoe or pjoe_dj) during daytime CET
model-view objects like TableView has a model property which needs to be set. Now to feed the view from a proper dynamic model this should probably be a go interface that mimics the virtual functions in C++ class QAbstractItemModel.
Since all other model classes inherits from this C++ class, that's all that needs to be implemented. Convenience interfaces for specialized view like listview and tableview may be implemented purely in Go to make life it easier for the Go user.
For an introduction to the C++ model classes have a look here: http://qt-project.org/doc/qt-5.1/qtquick/qtquick-modelviewsdata-cppmodels.html
Now, the implementation of this is essential to be able to support GUIs with larger amounts of non static data. And it also gives a very clean cut between data and gui as the same data model could be visualized in many different ways without having to make any changes to the data model itself.