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
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha
Accepted Solution

Loading XML data in to listview from C++ after fetching data from HTTP

[ Edited ]

I am sorry did searh but was not able to find any refrence related to my problem
I am trying to load the xml data fetched from a HTTP Post web service using QNetworkRequest and QNetworkReply in c++.

 

My XML that gets donwloaded is as 

<?xml version="1.0" encoding="utf-8"?>
 <ArrayOfPeople xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
  <People>
    <uid>tu7652</uid>
    <ExtFunction>F</ExtFunction>
    <givenName>Marry</givenName>
    <sn>Wijaya</sn>
  </People>
  <People>
    <uid>23</uid>
    <ExtFunction>F</ExtFunction>
    <givenName>Marry</givenName>
    <sn>Wijaya</sn>
  </People>
</ArrayOfPeople>

 In My QML this is the ListView lets say SearchResult.qml

 

ListView {
          objectName: "resultlist"
          dataModel: feedsdatamodel
          listItemComponents: [
          	ListItemComponent {
                        type: "item"
                        PeopleListItem {
                            name: ListItemData.givenName + ", " + ListItemData.sn
                            role: ListItemData.ExtFunction
                            leftPaddingText: 40
                        }
                    }
           ]
        }
 attachedObjects: [
       // The data model that contains the content of a XML file
        GroupDataModel {
            id: feedsDataModel
            sortingKeys: [
                "givenName"
            ]
            grouping: ItemGrouping.None
        }
    ]        

 PeopleListItem.qml 

 

import bb.cascades 1.0

Container {
    property alias name: titleLabel.text
    property alias role: functionLabel.text
    property alias leftPaddingText: textcontainer.leftPadding
    
    layout: StackLayout {
        orientation: LayoutOrientation.TopToBottom
    }
    preferredWidth: 768
    preferredHeight: 135
    Container {
            
        id: textcontainer
        topPadding: 10
        
        layout: StackLayout {
            orientation: LayoutOrientation.TopToBottom
        }
        Label {
            
            id: titleLabel
            textStyle.base: SystemDefaults.TextStyles.TitleText
            textStyle.color: Color.Black
        }
        Label {
            id: functionLabel
            textStyle.base: SystemDefaults.TextStyles.BodyText
            textStyle.color: Color.Gray
        }
    }
    Divider {
        verticalAlignment: VerticalAlignment.Bottom
    }
}  

 

This is the function I use to display the QML it is been called from main.qml and is working properly.

 

void PeopleFinder::onSearchClicked() {
	qDebug() << "PeopleFinder::PeopleFinder::onSearchClicked::\t" << "begin";
	qDebug() << "PeopleFinder::PeopleFinder::onSearchClicked::\tfname:"
			<< m_fname << "\tlname:" << m_lname;

	// Create a network access manager and connect a custom slot to its
	// finished signal
	mNetworkAccessManager = new QNetworkAccessManager(this);

	// create a data model with sorting keys for lastname and firstname
	Q_ASSERT(
			connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))));

	//Load the bew QML file of Search from here
	QmlDocument *qml = QmlDocument::create("asset:///SearchResults.qml").parent(
			this);
	qml->setContextProperty("peoplefinder", this);

	Page *mypage = qml->createRootObject<Page>();
	qml->setParent(mypage);
	qDebug() << "PeopleFinder::PeopleFinder::onSearchClicked::\t s444444";

	// Retrieve the activity indicator from QML so that we can start
	// and stop it from C++
//	mActivityIndicator = mypage->findChild<ActivityIndicator*>("myIndicator");

	// Retrieve the list so we can set the data model on it once
	// we retrieve it
	mListView = mypage->findChild<ListView*>("resultlist");

	mNavigator->push(mypage);
}

 

Once the page gets loaded in the QML it call the initiate request functionin c++ file and once the
request is finished below function is called with the data. I have checked the data is downloaded properly

 

void PeopleFinder::requestFinished(QNetworkReply* reply) {
	qDebug() << "PeopleFinder::PeopleFinder::requestFinished::\t"
			<< "response received";
	// Check the network reply for errors
	if (reply->error() == QNetworkReply::NoError) {

		// Open the file and print an error if the file cannot be opened
		qDebug() << "PeopleFinder::PeopleFinder::requestFinished::\t"
				<< "No error";

		// Write to the file using the reply data and close the file
		QByteArray xml = reply->readAll();
		qDebug() << "Data&colon; \n" << xml;

		// load the xml data
		XmlDataAccess xda;
		QVariant list = xda.load(xml, "ArrayOfPeople");

		qDebug() << "List:::\n" << list;

		GroupDataModel *datamodel = (GroupDataModel*)mListView->dataModel();
		// add the data to the model
		datamodel->clear();
		datamodel->insertList(list.value<QVariantList>());
		datamodel->setSortingKeys(QStringList() << "givenName" << "sn");
		qDebug() << "PeopleFinder::PeopleFinder::requestFinished::\t"
				<< "Datamodel set size:: " << datamodel->size();

		// Set the new data model on the list and stop the activity indicator

	} else {
		qDebug() << "\n Problem with the network";
		qDebug() << "\n" << reply->errorString();
	}
}

 

But now the real problem starts as in how to convert the QByteArray data to QVariantList type which can be loaded in the datamodel
I do not wish to write the data to the xml file and then pass that as list its will be very slow once i move from test environment to production environment.

Please help me solve this problem

 

 

 

 

 

 

Developer
RileyGB
Posts: 284
Registered: ‎08-06-2010
My Device: Z10

Re: Loading XML data in to listview from C++ after fetching data from HTTP

Here's what I use

 

void StandardNetworkManager::requestFinished() {

	mReply = qobject_cast<QNetworkReply*>(sender());
	QString errorResponse("");
	QVariantMap responseMap;

	bool success = false;

	// Check network object
	if (mReply) {
		// Detect if there was a network error
		if (mReply->error() == QNetworkReply::NoError) {
			int available = mReply->bytesAvailable();
			if (available > 0) {
				// Read in bytes to a byte array buffer
				int bufSize = sizeof(char) * available + sizeof(char);
				QByteArray buffer(bufSize, 0);
				int read = mReply->read(buffer.data(), available);

				// Convert the buffer to a map
				JsonDataAccess jda;
				responseMap = jda.loadFromBuffer(buffer).toMap();

				// Success
				success = true;
			}
		} else {
			// Generate network error response
			errorResponse =
					QString("Error: ") + mReply->errorString()
							+ QString(" status:")
							+ mReply->attribute(
									QNetworkRequest::HttpStatusCodeAttribute).toString();
			qDebug() << errorResponse;
		}
		mReply->deleteLater();

		// Process response
		if (success) {
			processResponse(responseMap);
		} else {
			showErrorToast(errorResponse);
			emit errorInWebServiceCall();
		}
	}

}

 



Follow me on twitter @RileyGB - https://twitter.com/RileyGB
View my BB10 OpenSource projects - https://github.com/RileyGB/BlackBerry10-Samples
Developer
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

Thanks for reply.
But I want it with XML as my data is going to be in XML I am completely new with c++
Developer
RileyGB
Posts: 284
Registered: ‎08-06-2010
My Device: Z10

Re: Loading XML data in to listview from C++ after fetching data from HTTP

[ Edited ]

If you need to covert a QByteArray to a QVariantList, just use this snippet:

 

		if (reply->error() == QNetworkReply::NoError) {
			int available = reply->bytesAvailable();
			if (available > 0) {
				// Read in bytes to a byte array buffer
				int bufSize = sizeof(char) * available + sizeof(char);
				QByteArray buffer(bufSize, 0);
				int read = mReply->read(buffer.data(), available);

                                XmlDataAccess xda;
                                QVariantList myList = xda.loadFromBuffer(buffer).toList();
                            }
}

 



Follow me on twitter @RileyGB - https://twitter.com/RileyGB
View my BB10 OpenSource projects - https://github.com/RileyGB/BlackBerry10-Samples
Developer
Developer
lew
Posts: 174
Registered: ‎03-05-2009
My Device: Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

[ Edited ]

your code looks fine to me....whats the error you are getting?

 

 you can simplify the code below:

// Write to the file using the reply data and close the file
QByteArray xml = reply->readAll();
qDebug() << "Data&colon; \n" << xml;

// load the xml data
XmlDataAccess xda;
QVariantList list = xda.load(reply, "ArrayOfPeople").toList();
...
datamodel->insertList(list);
...
 

 

Developer
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

Well there is no error but data is not getting loaded in list vie but I see I just have to pass qnetworkreply object instead of the byte array obj. Will try this and above solutions and check if works.

Thanks for replies.
Developer
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

[ Edited ]

I have tried this and it is not working the list.size() is returning 0. This is for both the above solutions provided 

 

QVariantList list = xda.loadFromBuffer(buffer, "ArrayOfPeople").toList();

 

or 

 

QVariantList list = xda.load(reply, "ArrayOfPeople/People").toList();

 

I am able to see the entire xml in the console log but the list size is 0.

 

Developer
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

OK now I am really confused as I tried to add the data mannually and it worked as below code

 

GroupDataModel *datamodel =
					(GroupDataModel*) mListView->dataModel();
			// add the data to the model
//			datamodel->clear();
//			datamodel->insertList(list);

			QVariantMap map;
			map["givenName"] = "XXX";
			map["sn"] = "YYY";
			map["ExtFunction"] = "Consultant";
			map["uid"] = "1234";
			datamodel->insert(map);

			map["givenName"] = "ABC";
			map["sn"] = "DEF";
			map["ExtFunction"] = "Manager";
			map["uid"] = "454095";
			datamodel->insert(map);

			datamodel->setSortingKeys(QStringList() << "givenName" << "sn");

			//mListView->setVisible(true);
			qDebug() << "\n Datamodel set size:: " << datamodel->size();

 

So the only issue is the conversion or parsing of XML to the a list that I can supply to Listviews groupdatamodel.

 

Any ideas anyone.

 

Developer
nimithingu
Posts: 37
Registered: ‎09-04-2012
My Device: Blackberry 10 Dev Alpha

Re: Loading XML data in to listview from C++ after fetching data from HTTP

I got it to working by using xml parsing with QXmlStreamReader
New Developer
tho_wa
Posts: 19
Registered: ‎02-17-2013
My Device: Z30

Re: Loading XML data in to listview from C++ after fetching data from HTTP

First of all I'm very new to Cascades, so please be patient with me ;-)

 

I'm trying to read data from an XML file (over the network).

I managed to read the contend of the file, but failed transferring it into a map as described in the article "Working with XML data"

 

Does somebody has a complete example project that he is willing to share with public?

 

Thanks a lot