Reputation: 55
I'm making a TV-Guide on Sailfish OS, and have met an - for now - obstacle.
As I want to have the possiblity to mark each entry for a customized list
I need to modify the model behind. I have tried modifying the model directly:
model.favorite = true
but that doesn't work. I have tried to modify the underlying
arrayOfObjects
, but that isn't reflected in the UI, and I can't trigger an update because I can't access the ListView. I have tried to make a customized model, but since I can't reference it's instance, to no avail.
Below is a very simplified representation of the layout using mostly basic QML.
Page {
Flickable {
Column {
SlideshowView { // PathView
model: arrayOfObjects
delegate: channelDelegate
}
}
}
Component {
id: channelDelegate
ListView {
id: channelList
// ProgramModel just iterates thru arrayOfObjects and appends them
model: ProgramModel {
programs: arrayOfObjects
}
delegate: programDelegate
Component.onCompleted: {
// I can't reference channelList from here.
}
}
}
Component {
id: programDelegate
ListItem {
Button {
onClicked: {
// How do I reference channelList?
// Doing it by name doesn't work.
}
}
}
}
}
I have tried calling ApplicationWindow (which works), to send a signal that I connect to in channelList.onCompleted (which also works), but since I can't reference the list from there it doesn't help.
I'm on QT 5.6 so some solutions may not work. And I would really prefer keeping it pure QML; no C++.
Upvotes: 0
Views: 1033
Reputation: 55
Because the SlideshowView replaces the focus in DaszuOne's answer, i.e. switches slide, list.model = listModel
causes the entire view to change. Changing a single entry in the model, doesn't trigger an update, so it would require even more code to make that happen. So after considering back and forth, I decided that doing it "the right way" would be more cumbersome and hard to read, than doing it the easy way.
I made a very simple wrapper, that can use what kind of persistent storage you use, having only two methods: setFavorite()
and isFavorite
.
In the delegate I update the property in onCompleted so it will be called every time the element needs to be rendered:
Component.onCompleted: {
favorite = favorites.isFavorite(model.channelId, model.id)
}
My conclusion is, that DaszuOne's answer is the correct answer - but not in this case ;)
Thank you for all your help, it made me understand QML better.
Upvotes: 0
Reputation: 809
I can't reproduce your case exactly, but maybe this quick example help you somehow.
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
id: mainWrapper
visible: true
width: 640
height: 480
title: qsTr("Hello World")
signal updateModel(int id, string name)
Component {
id: listWrapper
ListView {
id: list
model: [
{ name: "name0" },
{ name: "name1" },
{ name: "name2" }
]
delegate: Loader {
width: parent.width
property variant model: modelData
property int modelIndex: index
sourceComponent: listDelegate
}
function updateModelName(id, name) {
var listModel = list.model
listModel[id].name = name
list.model = listModel
}
}
}
Loader {
id: loadedList
x: 0
anchors.fill: parent
sourceComponent: listWrapper
Component.onCompleted: {
mainWrapper.updateModel.connect(loadedList.item.updateModelName)
}
}
Component {
id: listDelegate
Rectangle {
id: listRow
width: 200
height: 80
Text {
text: model.name
}
Button {
x: 100
text: "update"
onClicked: {
mainWrapper.updateModel(modelIndex, "better_name"+modelIndex)
}
}
}
}
}
The clue of this example is to use signal and function to update model.
Upvotes: 1