[SOLVED]What is optimal way of "combining" XmlLIstView and ListView?
-
Hi All,
XmlListModel is perfect for fetching data from the network. But then it is "read only" and allows little manupulation with the actual elements. Is there a way to combine those two??I mean let's say I want XmlLIstModel to "populate" certain UI elements (such as descriptions etc) from the web, but I want users to be able to add/remove/append etc (so basically address the model with typical for ListView commands, not just get)..
Many thanks in advance!
-
I think best approach will be to populate ListModel from ready XmlListModel if you want pure qml solution. Or subclass QAbstractItemModel and parse xml there (I think it will be better solution, but it is C++ code).
-
Denis - great to hear back from you;)
Yes, I am trying this approach now as it seemed logical to me...here is the code I tried to use:XMLfile:
@<?xml version="1.0" encoding="UTF-8"?>
<vendor>
<info>
<title>Vendor1</title>
<title>Vendor2</title>
<title>Vendor3</title>
</info>
</vendor>@XmlListModel and ListView extracting the "title":
@Rectangle { // This is Vendor List Block
id: vendorList
width: 100; height: 100
XmlListModel {
id: vendorsModel
source: "vendor.xml"
query: "/vendor/info/title"
XmlRole { name: "vendortitle"; query: "string()" }
}
Component {
id: vendorDelegateText { text: vendortitle font.bold: true; font.pixelSize: 18 } } ListView { id: listView anchors.fill: parent model: vendorsModel delegate: vendorDelegate spacing: 1 clip: true }
}@
Now if I attempt to "populate" the ListModel using the XmlListModel, it gives error: "cannot use script for property value
text: vendortitle"Attempted code:
@import QtQuick 1.0Rectangle { // This is Vendor List Block
id: vendorList
width: 100; height: 100
XmlListModel {
id: vendorsModel
source: "vendor.xml"
query: "/vendor/info/title"
XmlRole { name: "vendortitle"; query: "string()" }
}
ListModel {
id: vendorsModelNonXml
ListElement {
text: vendortitle
}
}Component { id: vendorDelegate Text { text: vendortitle font.bold: true; font.pixelSize: 18 } } ListView { id: listView anchors.fill: parent model: vendorsModelNonXml delegate: vendorDelegate spacing: 1 clip: true }
}@
So I wonder if I am using wrong syntax here and getting the error...what should be the approach then? many thanks in advance!
-
you of course can't use inner name of XmlRole outside of delegate :) You should write JS function that will go throuth all items in xmlmodel and populate listmodel
-
Ehm, I see...is it the right approach then to do something like...:
@Rectangle { // This is Vendor List Block
id: vendorList
width: 100; height: 100
XmlListModel {
id: vendorsModel
source: "vendor.xml"
query: "/vendor/info/title"
XmlRole { name: "vendortitle"; query: "string()" }
Component.onCompleted: function populateListModel() {
var i = 1
for (var i=1; i < vendorsModel.count; i++)
vendorsModelNonXml.append({"title":vendorsModel.get(i).vendortitle})
}, console.log("populated")
}
ListModel {
id: vendorsModelNonXml
}
Component {
id: vendorDelegateText { text: text color: "black" font.bold: true; font.pixelSize: 18 } } ListView { id: listView anchors.fill: parent model: vendorsModelNonXml delegate: vendorDelegate spacing: 1 clip: true }
}@
-
Also the help file says:
For example, for a model like this:
@XmlListModel {
id: model
source: "http://mysite.com/feed.xml"
query: "/feed/entry"
XmlRole { name: "title"; query: "title/string()" }
}@
This will access the title value for the first item in the model:
@var title = model.get(0).title;@
Trying to apply the logic I used previously is still gets me nowhere...(undefined)
-
Nope all methods fail for me...
Where can I read on how-tos cause all existing documentation just didn't help.Here is what I ended up with:
@Rectangle { // This is Vendor List Block
id: vendorList
width: 100; height: 100
ListModel {
id: vendorsModelNonXml
ListElement {
vendortitle: "test"
}
ListElement {
vendortitle: "test"
}
ListElement {
vendortitle: "test"
}
}
XmlListModel {
id: vendorsModel
function populate() {
var vendortitle = vendorsModel.get(0).vendortitle
vendorsModelNonXml.append({"vendortitle":vendortitle})
}
source: "vendor.xml"
query: "/vendor/info/title"
XmlRole { name: "vendortitle"; query: "string()" }
Component.onCompleted: populate()
}
Component {
id: vendorDelegate
Text {
text: vendortitle
color: "black"
font.bold: true; font.pixelSize: 18
}
}
ListView {
id: listView
anchors.fill: parent
model: vendorsModelNonXml
delegate: vendorDelegate
spacing: 1
clip: true
}
}@ -
You should do it not in Component.onCompleted, but in onStatusChanged when status will be XmlListModel.Ready
-
Denis, thanks a lot - that explains things:) I will post here back the working code today's evening.
I also found a useful article re this here: "LINK":http://www.mail-archive.com/qt-qml@trolltech.com/msg00544.html
-
@onStatusChanged: {
if (status == vendorsModel.Ready);
var vendortitle = vendorsModel.get(1).vendortitle
vendorsModelNonXml.append({"vendortitle":vendortitle})
}@Here is what solved the issue. The only concern is that even though it works there is a warning in console log saying: Result of expression 'vendorsModel.get(1)' [undefined] is not an object.
Any clue what that means? did I miss something else? or I can ignore this message?
-
Change code to
@
onStatusChanged: {
if (status == vendorsModel.Ready) {
var vendortitle = vendorsModel.get(1).vendortitle
vendorsModelNonXml.append({"vendortitle":vendortitle})
}
}
@And please don't forget to mark thread as [solved] :)
-
Denis, btw your code didn't work the way it meant to be, only adding "progress" helped it:
@
onStatusChanged: {
if (status == vendorsModel.Ready, progress ==1.0) {
var vendortitle = vendorsModel.get(1).vendortitle
vendorsModelNonXml.append({"vendortitle":vendortitle})
}
}@Weird...