Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Developer
welsenKiriono
Posts: 202
Registered: ‎04-19-2011
My Device: Blackberry Bold 9780
Accepted Solution

How to displat this XML in List View QML

To developers,

I want to ask how to add this xml to ListView. Here is my example XML

<root>
  <Venue>
    <IdVenue>501</IdVenue>
    <Name>guan sheng di jin miao. kelengteng guang gong</Name>
    <IdCategory>122</IdCategory>
    <Address>jalan martadinata</Address>
    <City>Tuban</City>
    <Latitude>-6.8908800000000001</Latitude>
    <Longitude>112.0459175</Longitude>
    <Distance>13091</Distance>
    <UserLike>False</UserLike>
    <CommentCount>0</CommentCount>
    <LikeCount>0</LikeCount>
  </Venue>
  <Venue>
    <IdVenue>1757</IdVenue>
    <Name>Galang's Mansion</Name>
    <IdCategory>41</IdCategory>
    <Address>Jalan Basuki Rahmad Nomor 99</Address>
    <City>Tulungagung</City>
    <Latitude>-7.1284299999999998</Latitude>
    <Longitude>112.11834</Longitude>
    <Distance>19305</Distance>
    <UserLike>False</UserLike>
    <CommentCount>0</CommentCount>
    <LikeCount>0</LikeCount>
  </Venue>\
</root>

What i want to view is:

1. ViewList without header (i've used  headerMode: ListHeaderMode.None to create non-group view)

2. Each row contains 1 Venue, which include it's name, address, and distance.

Can you help me?

Thank you very much for your help..

BlackBerry Development Advisor (Retired)
smacmartin
Posts: 499
Registered: ‎05-07-2012
My Device: developer

Re: How to displat this XML in List View QML

Take a look at sample cascadescookbookqml, especially files:

   recipemodel.xml

   main.qml (the ListView)

   RecipeItem.qml (defining the component used by the ListView.

 

In your case the XML does not map directly to what you want to display.  A few choices come to mind:

- change your XML to a format that XmlDataModel can easily handle, e.g. use attributes

- In C++, use QXmlSimpleParser to read your XML and feed the data to a QListDataModel or to a GroupDataModel with grouping set to none

- In C++, use QXmlSimpleParser to read your XML but use your own data model subclass to feed the data to the list view.  See http://supportforums.blackberry.com/t5/Cascades-Development-Knowledge/Using-your-own-DataModel/ta-p/...

 

Stuart

Developer
welsenKiriono
Posts: 202
Registered: ‎04-19-2011
My Device: Blackberry Bold 9780

Re: How to displat this XML in List View QML

Thank you for your reply.

Sorry if i'm not quite understand with your solution :

1. if i want to use XML for dataModel, it means i have to translate my xml into using attributes?

2. Can i use your second and third solution in QML? (I'm still blank how to integrate C++ and QML in 1 app)

3. Sorry if i'm asking more, but can you give me tutorial, how to parse XML into my own custom data model? Maybe with some code, so i can understand how to use it..

BlackBerry Development Advisor (Retired)
smacmartin
Posts: 499
Registered: ‎05-07-2012
My Device: developer

Re: How to displat this XML in List View QML

To do things entirely in QML, you will need to format your XML in a way that XmlDataModel supports, so yes you will need to use attributes.  Look at the cascadescookbookqml sample.

To learn how to integrate C++ and QML in one application, there are many resources:

  • read the documentation at https://developer.blackberry.com/cascades/documentation/
    Be sure to take the time to work through the worked examples.
  • download and study the samples, starting with cascadescookbook and also stampcollector
  • the knowledge base article I pointed to is a small example

To learn C++ there are many good online tutorials, books, and other resources.

 

Stuart

New Developer
setiawand
Posts: 41
Registered: ‎07-12-2012
My Device: Orlando, Dev Alpha

Re: How to displat this XML in List View QML

yup, you have to convert the structure into xmldatamodel compatible structure, you can use C++ code to do the conversion, and pass the result into QML

 

<root>
  <Venue IdVenue="501" Name="guan sheng di jin miao. kelengteng guang gong" IdCategory="122" .../>
<Venue .../>
 </root>
Developer
soaman
Posts: 849
Registered: ‎03-03-2011
My Device: Z10

Re: How to displat this XML in List View QML

Of course then it is better to manually in C++ fill variant list with variant maps containing those key-values.

Look at https://developer.blackberry.com/cascades/documentation/ui/lists/groupdatamodel.html under 'Creating a GroupDataModel in C++'.
--------------------------------------------------------------------------------------
Leader of Ljubljana BlackBerry Developer Group
BlackBerry Certified Builder for Native Application Development
Developer
alecaserez
Posts: 18
Registered: ‎08-26-2012
My Device: Z10

Re: How to displat this XML in List View QML

an example?

Developer
raj_jyani
Posts: 107
Registered: ‎05-11-2011
My Device: BlackBerry Z10 LE

Re: How to displat this XML in List View QML

hi,

 

XML

 

<?xml version="1.0" encoding="UTF-8" ?>
<persons>
    <person id="1">
        <firstname>John</firstname>
        <surname>Doe</surname>
        <email>john.doe@example.com</email>
        <website>http://aptratech.com</website>
    </person>
    <person id="2">
        <firstname>Jane</firstname>
        <surname>Doe</surname>
        <email>jane.doe@example.com</email>
        <website>http://aptratech.com</website>
    </person>
    <person id="3">
        <firstname>Matti</firstname>
        <surname>Meikäläinen</surname>
        <email>matti.meikalainen@example.com</email>
        <website>http://aptratech.com</website>
    </person>
</persons>

 

 

Cpp Code

 

#include <QObject>
#include <QIODevice>

//#include <QXmlStreamReader>
#include <QtXml/QDomDocument>
#include <bb/cascades/QListDataModel>

#include <bb/cascades/Application>
#include <bb/cascades/ListView>
#include <bb/cascades/GroupDataModel>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>

using namespace bb::cascades;

App::App() {
    // Load the QML document and retrieve the root node
    QmlDocument *qml = QmlDocument::create("main.qml");
    AbstractPane *root = qml->createRootNode<AbstractPane>();

    GroupDataModel *model = new GroupDataModel(
            QStringList() << "firstname" << "surname" << "email");
    model->setGrouping(ItemGrouping::ByFirstChar);

    ListView *listView = root->findChild<ListView *>("listView");

    QString appFolder(QDir::currentPath());
    QString fileName = appFolder + "/app/native/assets/models/items.xml";
    fprintf(stderr, "File Path :  %s\n", fileName.toAscii().constData());

    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        fprintf(stderr, "Error to open file.\n");
        return;
    } else {
        fprintf(stderr, "File opened.\n");
    }

    QList<QMap<QString, QString> > persons;

    QDomDocument doc("mydocument");
    if (!doc.setContent(&file)) {
        return;
    }

    //Get the root element
    QDomElement docElem = doc.documentElement();

    // you could check the root tag name here if it matters
    QString rootTag = docElem.tagName(); // == persons

    // get the node's interested in, this time only caring about person's
    QDomNodeList nodeList = docElem.elementsByTagName("person");

    //Check each node one by one.
    QMap<QString, QVariant> person;
    for (int ii = 0; ii < nodeList.count(); ii++) {

        // get the current one as QDomElement
        QDomElement el = nodeList.at(ii).toElement();

        //    person["id"] = el.attribute("id"); // get and set the attribute ID

        //get all data for the element, by looping through all child elements
        QDomNode pEntries = el.firstChild();
        while (!pEntries.isNull()) {
            QDomElement peData = pEntries.toElement();
            QString tagNam = peData.tagName();

            if (tagNam == "firstname") {
                //We've found first name.
                person["firstname"] = peData.text();
            } else if (tagNam == "surname") {
                //We've found surname.
                person["surname"] = peData.text();
            } else if (tagNam == "email") {
                //We've found email.
                person["email"] = peData.text();
            } else if (tagNam == "website") {
                //We've found website.
                person["website"] = peData.text();
            }
            pEntries = pEntries.nextSibling();
        }
        model->insert(person);
    }

    listView->setDataModel(model);

    // Set the scene using the root node
    Application::setScene(root);
}

 

 

Qml File

 

import bb.cascades 1.0

Page {
    content: Container {
        ListView {
            id: contactList
            objectName: "listView"
            listItemComponents: [
                ListItemComponent {
                    type: "header"
                    HeaderListItem {
                        title: ListItemData
                    }
                },
                ListItemComponent {
                    type: "item"
                    Container {
                        Label {
                            text: ListItemData.firstname
                        }
                        Label {
                            text: ListItemData.surname
                        }
                        Label {
                            text: ListItemData.email
                        }
                        Container {
                            preferredWidth: 768
                            preferredHeight: 5
                            background: Color.Red
                        }
                    }
                }
            ] // end of listItemComponents list        
        }
    }
}

Developer
alecaserez
Posts: 18
Registered: ‎08-26-2012
My Device: Z10

Re: How to displat this XML in List View QML

thanks!

Developer
welsenKiriono
Posts: 202
Registered: ‎04-19-2011
My Device: Blackberry Bold 9780

Re: How to displat this XML in List View QML

Sorry for my late reply, i'm trying to merge this sample code in creating my own data model..

But, i can't structure my group data model.

The result just show address, but not the others data information.

Can you help me to find what is the problem. Thank you..

 

Here is my own group data model :

1. VenueDataModel.h

#ifndef VENUEDATAMODEL_H_
#define VENUEDATAMODEL_H_

#include <QVector>
#include <QtXml/QDomDocument>
#include <bb/cascades/DataModel>
#include <bb/cascades/GroupDataModel>
#include <bb/cascades/QListDataModel>
#include <bb/cascades/QmlDocument>

class VenueDataModel : public bb::cascades::GroupDataModel{
private:
public:
	VenueDataModel();
	virtual ~VenueDataModel();
	void createDataModel();
};

#endif /* VENUEDATAMODEL_H_ */

 2. VenueDataModel.cpp

#include "VenueDataModel.h"

VenueDataModel::VenueDataModel() {
	// TODO Auto-generated constructor stub
	createDataModel();
}

VenueDataModel::~VenueDataModel() {
	// TODO Auto-generated destructor stub
}

void VenueDataModel::createDataModel() {
	//open file locastion
	QString appFolder(QDir::currentPath());
	QString fileName = appFolder + "/app/native/assets/resource/xml/venueTag.xml";
	QFile file(fileName);

	//create document
	QDomDocument doc("venueListDocument");
	doc.setContent(&file);
	QDomElement docElem = doc.documentElement();
	QDomNodeList nodeList = docElem.elementsByTagName("Venue");

	//parsing XML
	QString id = "";
	QString name = "";
	QMap<QString, QVariant> venueList;
	for (int i = 0; i < nodeList.count(); i++)
	{
		QDomElement el = nodeList.at(i).toElement();
		QDomNode entryRow = el.firstChild();
		while (!entryRow.isNull()) {
			QDomElement entryValue = entryRow.toElement();
			QString entryTag = entryValue.tagName();

			if (entryTag == "IdVenue")
			{
				venueList["IdVenue"] = entryValue.text();
			}
			else if (entryTag == "Name")
			{
				venueList["Name"] = entryValue.text();
			}
			else if (entryTag == "IdCategory")
			{
				venueList["IdCategory"] = entryValue.text();
			}
			else if (entryTag == "Address")
			{
				venueList["Address"] = entryValue.text();
			}
			else if (entryTag == "City")
			{
				venueList["City"] = entryValue.text();
			}
			else if (entryTag == "Latitude")
			{
				venueList["Latitude"] = entryValue.text();
			}
			else if (entryTag == "Longitude")
			{
				venueList["Longitude"] = entryValue.text();
			}
			else if (entryTag == "Distance")
			{
				venueList["Distance"] = entryValue.text();
			}
			else if (entryTag == "UserLike")
			{
				venueList["UserLike"] = entryValue.text();
			}
			else if (entryTag == "CommentCount")
			{
				venueList["CommentCount"] = entryValue.text();
			}
			else if (entryTag == "LikeCount")
			{
				venueList["LikeCount"] = entryValue.text();
			}
			entryRow = entryRow.nextSibling();
		}
		this->insert(venueList);
	}
}

 3. i add custom lib in my app.cpp

#include <QObject>
#include <QIODevice>
#include <QVector>

#include <QtXml/QDomDocument>
#include <bb/cascades/QListDataModel>

#include <bb/cascades/Application>
#include <bb/cascades/ListView>
#include <bb/cascades/GroupDataModel>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>

#include "app.hpp"
#include "VenueDataModel.h"


using namespace bb::cascades;

App::App()
{
	qmlRegisterType<VenueDataModel>("custom.lib", 1, 0, "VenueDataModel");
	QmlDocument *qml = QmlDocument::create("main.qml");
    //-- setContextProperty expose C++ object in QML as an variable
    //-- uncomment next line to introduce 'this' object to QML name space as an 'app' variable
    qml->setContextProperty("_app", this);
    
    AbstractPane *root = qml->createRootNode<AbstractPane>();
    Application::setScene(root);
}

 4. Then in my listview, i insert my own group data model

ListView {
	                     id: venueListID
	                     dataModel: VenueDataModel {
                            grouping: ItemGrouping.None
                        }
                        selectionMode: SelectionMode.Single
	                     layout: StackListLayout {
	                        headerMode: ListHeaderMode.None
	                     }
	                     
	                     listItemComponents: [      
	                         ListItemComponent {
	                             type: "Venue"
	                             VenueManagerList {
	                             }
	                         }
	                     ]
	                 
	                     onTriggered: {
	                         // When an item is selected we push the recipe Page in the chosenItem file attribute.
	                         var chosenItem = dataModel.data(indexPath);
	     
	                         // The _contentView property can be resolved in by the ContentPage since it will
	                         // share the same context as the main file.
	                         _contentView = chosenItem;                    
	                         
	                         // Push the Content Page on top to drill down and show details about the stamp.
	                         homeScreenNav.deprecatedPushQmlByString("VenueDetailScreen.qml");                    
	                     }
	                }

4. This is my VenueManagerList.qml 

import bb.cascades 1.0

Container {
    id: venueManager
    layout: StackLayout {
        layoutDirection: LayoutDirection.TopToBottom
    }
    
    Container{
        id: listContainerManagerID
        layout: StackLayout {
            layoutDirection: LayoutDirection.LeftToRight
            leftPadding: 10.0
            rightPadding: 10.0
            topPadding: 0.0
            bottomPadding: 0.0
        }
        
        ImageView {
		    id: venueCategoryID
		    imageSource: "asset:///resource/icon/venueCategory/" + ListItemData.IdCategory + ".png"
		    layoutProperties: StackLayoutProperties {
	             horizontalAlignment: HorizontalAlignment.Left
	             verticalAlignment: VerticalAlignment.Center
	        }
        }
        
        Container{
            id: informationManagerID
            layout: StackLayout {
                leftPadding: 10.0
                rightPadding: 10.0
            }
            layoutProperties: StackLayoutProperties {
                horizontalAlignment: HorizontalAlignment.Fill
                verticalAlignment: VerticalAlignment.Center
                spaceQuota: 8
            }
            
            Label {
    	        id: labelVenueTitleID
    	        text: ListItemData.Name 
    	        layoutProperties: StackLayoutProperties  {
    	             horizontalAlignment: HorizontalAlignment.Left
    	        }
    	        textStyle.size: 35.0
    	        textStyle.color: Color.create("#ff71951d")
    	        topMargin: 0
    	        bottomMargin: 0
    	    }
    	    
    	    Label {
    	        id: labelVenueAddressID
    	        text: ListItemData.Address
    		    layoutProperties: StackLayoutProperties  {
    	             horizontalAlignment: HorizontalAlignment.Left
    	        }
    	        textStyle.size: 25.0
    	        textStyle.color: Color.create("#ff666666")
    	        topMargin: 0
    	        bottomMargin: 0
    	    }
    	    
    	    Label {
    	        id: labelVenueCityID
    	        text: ListItemData.City
    		    layoutProperties: StackLayoutProperties  {
    	             horizontalAlignment: HorizontalAlignment.Left
    	        }
    	        textStyle.size: 25.0
    	        textStyle.color: Color.create("#ff666666")
    	        topMargin: 0
    	        bottomMargin: 0
    	    }
        }
        
        Container{
            id: iconManagerID
            layout: StackLayout {
            }
            layoutProperties: StackLayoutProperties {
                horizontalAlignment: HorizontalAlignment.Right 
                spaceQuota: 1.5
                verticalAlignment: VerticalAlignment.Center
            }
            
            Container{
                id: likeIconManagerID
                layout: StackLayout {
                    leftPadding: 5.0
                    rightPadding: 5.0
                    layoutDirection: LayoutDirection.LeftToRight
                }
                ImageView {
        		    id: iconLikeID
        		    imageSource: "asset:///resource/icon/" + 
        		       ((ListItemData.UserLike == "True") ? "LikeON.png" : "LikeOFF.png")
        		    layoutProperties: StackLayoutProperties {
        	             horizontalAlignment: HorizontalAlignment.Left
        	             verticalAlignment: VerticalAlignment.Center
        	        }
                }
                Label {
        	        id: labelLikeCountID
        	        text: ListItemData.LikeCount
        		    textStyle.size: 25.0
        	        textStyle.color: Color.create("#ff666666")
        	        topMargin: 0
        	        bottomMargin: 0
        	    }
            }
            
            Container{
                id: commentIconManagerID
                layout: StackLayout {
                    leftPadding: 5.0
                    rightPadding: 5.0
                    layoutDirection: LayoutDirection.LeftToRight
                }
                ImageView {
        		    id: iconCommentID
        		    imageSource: "asset:///resource/icon/Comment.png"        		     
            		layoutProperties: StackLayoutProperties {
        	             horizontalAlignment: HorizontalAlignment.Left
        	             verticalAlignment: VerticalAlignment.Center
        	        }
                }
                Label {
        	        id: labelCommentCountID
        	        text: ListItemData.CommentCount
        		    textStyle.size: 25.0
        	        textStyle.color: Color.create("#ff666666")
        	        topMargin: 0
        	        bottomMargin: 0
        	    }
                
            }
        }
    }
    
    Container{
        id: bottomManagerListID
        layout: StackLayout {
            leftPadding: 0.0
            rightPadding: 0.0
            topPadding: 0.0
            bottomPadding: 0.0
        }
        layoutProperties: StackLayoutProperties {
            verticalAlignment: VerticalAlignment.Bottom
        }
        background: Color.create ("#ffbad79d")
        minWidth: 250.0
        Label {
	        id: labelVenueDistanceID
	        text: "Distance : " + ListItemData.Distance + " m  "
		    layoutProperties: StackLayoutProperties  {
	             horizontalAlignment: HorizontalAlignment.Left
	        }
	        textStyle.size: 25.0
	        textStyle.color: Color.create("#ff666666")
	        topMargin: 0
	        bottomMargin: 0
	    }
    }
    
    Divider {
        topMargin: 0.0
        bottomMargin: 0.0
    }
}