[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: vendorDelegate

        Text {
           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.0

    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()" }
    }
    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: vendorDelegate

        Text {
           text: text
           color: "black"
           font.bold: true; font.pixelSize: 18
        }
    }
    ListView {
        id: listView
        anchors.fill: parent
        model: vendorsModelNonXml
        delegate: vendorDelegate
        spacing: 1
        clip: true
    }
    

    }@



  • Still can't refer to vendortitle in the example above;( always states "undefined". How should I explicitly make this variable available to javascript?

    Tried inserting JS function almost everywhere now...plz help!



  • 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...


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.