Display text in qml based on signal generated - c++

I'm trying to create a simple login application which authenticates via firebase. My current issue is how to display a signal emitted in the .cpp file in a .qml file.
.h file:
#ifndef AUTHHANDLER_H
#define AUTHHANDLER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QtQml/qqml.h>
class AuthHandler : public QObject
{
Q_OBJECT
public:
explicit AuthHandler(QObject *parent = nullptr);
~AuthHandler();
void setAPIKey(const QString & apiKey);
//void signUserUp(const QString & emailAddress, const QString & password);
//void signUserIn(const QString & emailAddress, const QString & password);
public slots:
void networkReplyReadyRead();
void signUserIn(const QString & emailAddress, const QString & password);
void signUserUp(const QString & emailAddress, const QString & password);
void performAuthenticatedDatabaseCall();
signals:
void userSignedIn(); //void
private:
void performPOST( const QString & url, const QJsonDocument & payload);
void parseResponse( const QByteArray & response);
QString m_apiKey;
QNetworkAccessManager * m_networkAccessManager;
QNetworkReply * m_networkReply;
QString m_idToken;
};
#endif // AUTHHANDLER_H
.cpp file: This is one of the functions in my .cpp file. As you can see on running the code it displays the "User signed in successfully" in the application output window. This code works as intended.
void AuthHandler::parseResponse(const QByteArray &response)
{
QJsonDocument jsonDocument = QJsonDocument::fromJson(( response ));
if ( jsonDocument.object().contains("error"))
{
qDebug() << "Error occured!" << response;
}
else if (jsonDocument.object().contains("kind"))
{
QString idToken = jsonDocument.object().value("idToken").toString();
qDebug() << "Obtained user ID Token: " << idToken;
qDebug() << "User signed in successfully!";
m_idToken = idToken;
emit userSignedIn();
}
else
qDebug() << "The response was: " << response;
}
.qml file code:
Button {
id: loginbutton
//anchors.bottom: parent.bottom
property color colorNormal: "white"
property color colorHovered: "grey"
property color colorClicked: "black"
property color hoverColor: loginbutton.down ? colorClicked : (loginbutton.hovered ? colorHovered : colorNormal)
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: password.bottom
anchors.topMargin: 10
text: qsTr("Login");
font.family: "/fonts/Montserrat-Italic"
font.pointSize: ScreenTools.mediumFontPointSize * 1.3
background: Rectangle {
implicitWidth: mainWindow.width*0.05
implicitHeight: mainWindow.height*0.05
opacity: enabled ? 1 : 0.3
//border.color: controlBt1.down ? "#A9A9A9" : "#373737"
//border.width: 1
radius: 10
gradient: Gradient {
GradientStop { position: 0; color: "#ffffff" }
GradientStop { position: 1; color: "#ADD8E6" }
}
}
onClicked: {
console.log("login: " + username.text + " password: " + password.text);
AuthHandler.signUserIn(username.text, password.text);
This is part of my qml file. On clicking the login button, the signUserIn function executes correctly. My question is, how would I display a succesful login message via my qml if there is a succesful login attempt.

You can use Connection QML type.
Should look something like this:
Connection{
target: AuthHandler
function onUserSignedIn(){console.log("QML: User signed in!")}
}
The pattern is function on<signal name capitalized>(){...}

Related

Using StackView to push a page based on succesful authentication

I have written code for Firebase Authentication for a desktop application. The authentication is working fine, I am having issues using StackView to push the next page based on successful authentication. Here's my code:
h file:
#ifndef AUTHHANDLER_H
#define AUTHHANDLER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QtQml/qqml.h>
class AuthHandler : public QObject
{
Q_OBJECT
public:
explicit AuthHandler(QObject *parent = nullptr);
~AuthHandler();
void setAPIKey(const QString & apiKey);
//void signUserUp(const QString & emailAddress, const QString & password);
//void signUserIn(const QString & emailAddress, const QString & password);
public slots:
void networkReplyReadyRead();
void signUserIn(const QString & emailAddress, const QString & password);
void signUserUp(const QString & emailAddress, const QString & password);
void performAuthenticatedDatabaseCall();
// New slot function
void onUserSignedIn()
{
qDebug() << "onUserSignedIn called";
// Get a reference to the StackView object
QObject* stackView = this->parent()->findChild<QObject*>("stackView"); //problem here most likely
if (stackView)
{
qDebug() << "Calling push() on StackView";
//Push the main root window onto the StackView
QMetaObject::invokeMethod(stackView, "push", Q_ARG(QVariant, "qrc:/qml/MainRootWindow.qml"));
}
}
signals:
void userSignedIn(); //void
private:
void performPOST( const QString & url, const QJsonDocument & payload);
void parseResponse( const QByteArray & response);
QString m_apiKey;
QNetworkAccessManager * m_networkAccessManager;
QNetworkReply * m_networkReply;
QString m_idToken;
};
#endif // AUTHHANDLER_H
cpp file:
#include "authhandler.h"
#include <QDebug>
#include <QVariantMap>
#include <QNetworkRequest>
#include <QJsonObject>
#include <QQmlApplicationEngine>
#include <QQmlContext>
AuthHandler::AuthHandler(QObject *parent)
: QObject{parent}
, m_apiKey( QString() )
{
m_networkAccessManager = new QNetworkAccessManager( this );
connect( this, &AuthHandler::userSignedIn, this, &AuthHandler::performAuthenticatedDatabaseCall );
connect(this, &AuthHandler::userSignedIn, this, &AuthHandler::onUserSignedIn);
}
AuthHandler::~AuthHandler()
{
m_networkAccessManager->deleteLater();
}
void AuthHandler::setAPIKey(const QString &apiKey)
{
m_apiKey = apiKey;
}
void AuthHandler::signUserUp(const QString &emailAddress, const QString &password)
{
QString signUpEndpoint = "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=" + m_apiKey;
QVariantMap variantPayload;
variantPayload["email"] = emailAddress;
variantPayload["password"] = password;
variantPayload["returnSecureToken"] = true;
QJsonDocument jsonPayload = QJsonDocument::fromVariant( variantPayload );
performPOST( signUpEndpoint, jsonPayload);
}
void AuthHandler::signUserIn(const QString &emailAddress, const QString &password)
{
QString signInEndpoint = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" + m_apiKey;
QVariantMap variantPayload;
variantPayload["email"] = emailAddress;
variantPayload["password"] = password;
variantPayload["returnSecureToken"] = true;
QJsonDocument jsonPayload = QJsonDocument::fromVariant( variantPayload );
performPOST( signInEndpoint, jsonPayload);
}
void AuthHandler::networkReplyReadyRead()
{
QByteArray response = m_networkReply->readAll();
qDebug() << response;
m_networkReply->deleteLater();
parseResponse( response);
}
void AuthHandler::performAuthenticatedDatabaseCall()
{
QString endPoint = "https://karmandrones-7da76-default-rtdb.asia-southeast1.firebasedatabase.app/Pets.json?auth=" +m_idToken;
m_networkReply = m_networkAccessManager->get( QNetworkRequest(QUrl(endPoint)));
connect( m_networkReply, &QNetworkReply::readyRead, this, &AuthHandler::networkReplyReadyRead );
}
void AuthHandler::performPOST(const QString &url, const QJsonDocument &payload)
{
QNetworkRequest newRequest( (QUrl(url)));
newRequest.setHeader( QNetworkRequest::ContentTypeHeader, QString( "application/json"));
m_networkReply = m_networkAccessManager->post( newRequest, payload.toJson());
connect( m_networkReply, &QNetworkReply::readyRead, this, &AuthHandler::networkReplyReadyRead );
}
void AuthHandler::parseResponse(const QByteArray &response)
{
QJsonDocument jsonDocument = QJsonDocument::fromJson(( response ));
if ( jsonDocument.object().contains("error"))
{
qDebug() << "Error occured!" << response;
}
else if (jsonDocument.object().contains("kind"))
{
QString idToken = jsonDocument.object().value("idToken").toString();
qDebug() << "Obtained user ID Token: " << idToken;
qDebug() << "User signed in successfully!";
m_idToken = idToken;
emit userSignedIn();
}
else
qDebug() << "The response was: " << response;
}
qml file:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1
import QtQuick.LocalStorage 2.0
//import "AccountToolbar/Backend.js" as Backend
import "AuthBackend.js" as Backend
//////////
import QtQuick.Dialogs 1.3
import QtQuick.Window 2.11
import QGroundControl 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Controllers 1.0
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
id: authWindow
visible: true
width: Screen.width
height: Screen.height
minimumWidth: ScreenTools.isMobile ? Screen.width : Math.min(ScreenTools.defaultFontPixelWidth * 100, Screen.width)
minimumHeight: ScreenTools.isMobile ? Screen.height : Math.min(ScreenTools.defaultFontPixelWidth * 50, Screen.height)
title: qsTr("KarmanGCS")
property color backGroundColor : "white" // "#434343" //"#394454" // navy
property color mainAppColor: "#434343"// "#EBEBEB" //"#6fda9c" // green
property color mainTextCOlor: "grey" // gray
property color popupBackGroundColor: "#b44"
property color popupTextCOlor: "#ffffff"
property var dataBase
FontLoader {
id: fontAwesome
name: "fontawesome"
source: "qrc:/qml/fontawesome-webfont.ttf"
}
// Main stackview
StackView{
id: stackView
focus: true
anchors.fill: parent
}
// After loading show initial Login Page
Component.onCompleted: {
stackView.push("qrc:/qml/LoginPage.qml") //initial page
dataBase = userDataBase()
console.log(dataBase.version)
}
As you can see the AuthWindow.qml loads the login page qml correctly.
The userSigneIn() signal is also emitted correctly on successful login. This can be checked by the qdebug statement that I have put in the cpp file. I tried making a new slot function, which would push the MainRootWindow.qml if the userSignedIn() signal is emitted. The connection is in the cpp file. It is being called as the first qdebug statement works, but the push is not happening. Can someone help me debug or suggest an alterantive approach to push a new page to stackview?

Right QML <-> C++ declarative approach

I have some data structure updated in c++ layer. I have to display it in qml and save changes from qml layer to c++ structures. I hope there is a declarative approach to do it but I in desperate to find it.
Here is the part of code:
C++ header:
#ifndef NODEINFO_H
#define NODEINFO_H
#include <QObject>
#include <QString>
class NodeInfo : public QObject {
Q_OBJECT
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
public:
NodeInfo(QObject *parent = 0);
virtual ~NodeInfo() {}
const QString& label() const;
void setLabel(const QString& val);
signals:
void labelChanged();
private:
QString d_label;
};
#endif // NODEINFO_H
C++ body:
#include "nodeinfo.h"
#include <QDebug>
NodeInfo::NodeInfo(QObject *parent) : QObject(parent), d_label("Test string") {
}
const QString &NodeInfo::label() const {
qDebug() << "NodeInfo::label: getter";
return d_label;
}
void NodeInfo::setLabel(const QString &val) {
qDebug() << "NodeInfo::label: setter - " << val;
d_label = val;
emit labelChanged();
}
main.cpp
#include <QGuiApplication>
#include <QDebug>
#include <QQmlContext>
#include <QQuickView>
#include <QQmlApplicationEngine>
#include "nodeinfo.h"
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
// qmlRegisterType<NodeInfo>("NodeInfo", 1, 0, "NodeInfo");
NodeInfo nodeDescr;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("nodeData", &nodeDescr);
const QUrl url(QStringLiteral("qrc:/main.qml"));
engine.load(url);
QObject *root = engine.rootObjects().value(0);
if (QWindow *window = qobject_cast<QWindow *>(root))
window->show();
else
return -1;
return app.exec();
}
Qml code:
import QtQuick 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow {
id: root
width: 360
height: 520
visible: true
// property alias a_label: nodeData.label
Column {
anchors.fill: parent
TextInput {
id: simpleTxt
text: nodeData.label
}
Text {
id: txt
text: nodeData.label
}
Button {
text: "writeProp"
onClicked: nodeData.label = simpleTxt.text
}
// Binding {
// target: nodeData
// property: "label"
// value: simpleTxt.text
// }
}
}
So when I'm editing text in TextInput it should automatically set property in c++ code but it do not. Only if I press button.
There is the Binding way as you see in comments and it works but I it's not a true way I hope.
Let's imagine if I have 15-30 or more data fields in my c++ structure and it's full rubbish if I must do 30 Bindings such way or if I need to write signal/slot on each data field and connect them.
But what is right way?
Any ideas appreciated
A simpler solution is to assign the signal associated to the property text:
Text {
id: txt
text: nodeData.label
onTextChanged: {
if(nodeData.label != simpleTxt.text)
nodeData.label = simpleTxt.text
}
}
text: nodeData.label sets binding nodeData.label --> text (one direction). I.e. text is updated whenever nodeData.label is changed. When the user types some text in the field, this binding is destroyed.
So if you want to update nodeData.label when the user changes text, you need to use onTextChaged event.
Text {
onTextChanged: nodeData.label = text
}
One more note: you need to check if the property is really changed before emitting the appropriate changed signal. So the code should be something like this:
void NodeInfo::setLabel(const QString &val) {
qDebug() << "NodeInfo::label: setter - " << val;
if (d_label != val)
{
d_label = val;
emit labelChanged();
}
}
This will prevent your code from endless binding loops.

Best practice accessing Q_PROPERTY in qml from another thread

I have a larger project that crashes randomly after a few hours. I believe it is due to qml accessing Q_PROPERTY in my C++ QObject, where the Q_PROPERTY is set in another thread, causing a data race.
I have a simple toy project here. In it main.qml has a label that accesses a QProperty test.testChild.time. test.testChild.time is set in another thread when a QTimer expires and calls Test::timerExpired(). Test::timerExpired() has a QThread::usleep(100000) to simulate a long operation. When I comment the moveToThread(&m_workerThread) line below, the ui is much less responsive than before but everything is in the same thread so I believe data race cannot occur. If I don't comment moveToThread(&m_workerThread) and have timer.setInterval(0), the ui is very responsive but a crash occurs usually within a few minutes on my Ubuntu VM.
The code below is a section from test.cpp in my simple toy project here
Test::Test(QObject *parent) : QObject(parent)
// , testChild(this) // uncommenting this line will cause testChild to move to m_workerThread
{
uiThread = QThread::currentThreadId();
// move this object to a separate thread so does not interrupt UI thread
moveToThread(&m_workerThread); // commenting this line will make test::timerExpired() run on UI thread and slow down UI
timer.setInterval(0); // with interval 0, more likely to seg fault due to data race
connect(&timer, SIGNAL(timeout()), this, SLOT(timerExpired()));
connect(&m_workerThread, SIGNAL(started()), &timer, SLOT(start()));
m_workerThread.start();
}
void Test::timerExpired()
{
if (uiThread == QThread::currentThreadId())
qCritical() << "timerExpired() Controller thread is same as UI thread";
QMutexLocker locker(&mutex);// prevent UI thread from accessing objects below while they update with a QMutexLocker
QString time;
time = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
QThread::usleep(100000); // long operation
setTime(time);
testChild.setTime(time);
}
How can I safely have two threads, one for qml and another for long operations, while qml can access QProperties that update in the long operations thread?
I believe I have solved this using a model so the QML can safely communicate with the another thread.
The model is instantiated in the UI thread. The model receives data using signals and slots from the other thread (which is threadsafe). The model has QProperties that QML can interface with. When the model receives new data from another thread, QProperties are updated and QML receives new data.
The project is here but is also included below
TestQPropertyThread.pro
QT += quick
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
QMAKE_CXXFLAGS += -g -Wall -Werror
SOURCES += \
controller.cpp \
controllerchild.cpp \
main.cpp \
model.cpp
RESOURCES += qml.qrc
HEADERS += \
controller.h \
controllerchild.h \
model.h
main.cpp
#include "controller.h"
#include "model.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Controller test;
Model model(test);
engine.rootContext()->setContextProperty(QStringLiteral("model"), &model);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
controller.cpp
#include "controller.h"
Controller::Controller(QObject *parent) : QObject(parent), testChild(this), timer(this) // testChild to move to m_workerThread
{
uiThread = QThread::currentThreadId();
// move this object to a separate thread so does not interrupt UI thread
moveToThread(&m_workerThread); // commenting this line will make test::timerExpired() run on UI thread and slow down UI
timer.setInterval(0); // with interval 0, more likely to seg fault due to data race
connect(&timer, SIGNAL(timeout()), this, SLOT(timerExpired()));
connect(&m_workerThread, SIGNAL(started()), &timer, SLOT(start()));
m_workerThread.start();
}
void Controller::timerExpired()
{
if (uiThread == QThread::currentThreadId())
qCritical() << "Controller::timerExpired() Controller thread is same as UI thread";
// prevent UI thread from accessing objects below while they update with a QMutexLocker
QMutexLocker locker(&mutex);
QString time;
time = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
qDebug() << "Controller::timerExpired()" << time; // this can impact preformance when usleep is commented out
QThread::usleep(100000); // long operation
testChild.setTime(time);
}
controller.h
#ifndef TEST_H
#define TEST_H
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QMutex>
#include <QDebug>
#include <QDateTime>
#include "controllerchild.h"
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
ControllerChild testChild;
public slots:
void timerExpired();
private:
QTimer timer;
QThread m_workerThread;
Qt::HANDLE uiThread;
QMutex mutex;
};
#endif // TEST_H
controllerchild.cpp
#include "controllerchild.h"
ControllerChild::ControllerChild(QObject *parent) : QObject(parent)
{
}
void ControllerChild::setTime(const QString &value)
{
time = value;
emit timeChanged(time);
}
void ControllerChild::onButtonPress(const QString &value)
{
qDebug() << "ControllerChild::onButtonPress()" << value << QThread::currentThreadId() << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
emit onBoolChanged(value); // send value back to UI label
}
controllerchild.h
#ifndef TESTCHILD_H
#define TESTCHILD_H
#include <QObject>
#include <QDebug>
#include <QThread>
#include <QDateTime>
class ControllerChild : public QObject
{
Q_OBJECT
public:
explicit ControllerChild(QObject *parent = nullptr);
void setTime(const QString &value);
public slots:
void onButtonPress(const QString &value);
signals:
void timeChanged(const QString &value);
void onBoolChanged(QString value);
private:
QString time;
};
#endif // TESTCHILD_H
model.cpp
#include "model.h"
Model::Model(Controller &test, QObject *parent) : QObject(parent), test(test)
{
connect(&test.testChild, &ControllerChild::timeChanged, this, [=](const QString &time){ this->setTime(time); });
connect(this, &Model::onButtonPressChanged, &test.testChild, &ControllerChild::onButtonPress);
connect(&test.testChild, &ControllerChild::onBoolChanged, this, [=](const QString &value){ this->setBoolValue(value); });
}
QString Model::getTime() const
{
// return QString("test Child %1").arg(time);
return time;
}
void Model::setTime(const QString &value)
{
time = value;
emit timeChanged();
}
void Model::onButtonPress(const QString &value)
{
qDebug() << "Model::onButtonPress()" << value << QThread::currentThreadId() << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
emit onButtonPressChanged(value);
}
void Model::onBool(const QString &value)
{
qDebug() << "Model::onBool()" << value << QThread::currentThreadId() << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
emit onBoolChanged(value);
}
void Model::setBoolValue(const QString &value)
{
boolValue = value;
qDebug() << "Model::setBoolValue()" << value << QThread::currentThreadId() << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
emit onBoolChanged(value);
}
model.h
#ifndef MODEL_H
#define MODEL_H
#include <QObject>
#include "controller.h"
class Model : public QObject
{
Q_OBJECT
Q_PROPERTY(QString time READ getTime WRITE setTime NOTIFY timeChanged)
Q_PROPERTY(QString boolValue MEMBER boolValue NOTIFY onBoolChanged)
public:
explicit Model(Controller &test, QObject *parent = nullptr);
QString getTime() const;
void setTime(const QString &value);
void setBoolValue(const QString &value);
public slots:
void onButtonPress(const QString &value);
void onBool(const QString &value);
signals:
void timeChanged();
void onButtonPressChanged(const QString &value);
void onBoolChanged(const QString &value);
private:
QString time;
Controller &test;
QString boolValue;
};
#endif // MODEL_H
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Label {
id: time1
text: model.time
}
BusyIndicator {
id: busyIndicator
x: 0
y: 23
}
PathView {
id: pathView
x: 0
y: 135
width: 640
height: 130
delegate: Column {
spacing: 5
Rectangle {
width: 40
height: 40
color: colorCode
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
x: 5
text: name
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
}
}
path: Path {
startY: 100
startX: 120
PathQuad {
x: 120
y: 25
controlY: 75
controlX: 260
}
PathQuad {
x: 120
y: 100
controlY: 75
controlX: -20
}
}
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
}
Button {
id: button
x: 0
y: 271
text: qsTr("Press me!!")
checkable: true
onToggled: model.onButtonPress(button.checked)
}
Label {
id: label
x: 106
y: 294
text: model.boolValue
}
}

Dynamically set imageSource in ImageView Blackberry 10

Please help me.,i m stuck with this for more than a week.I am emitting a signal with image from my cpp file.I need to replace the default image that i placed in the imageView at QMl using this emitted image.
Here is my full code.
PostHttp.hpp
/* Copyright (c) 2012 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef POSTHTTP_HPP
#define POSTHTTP_HPP
#include "qvariant.h"
#include <bb/ImageData>
#include <bb/cascades/GroupDataModel>
#include <QtCore/QObject>
#include <bb/data/JsonDataAccess>
#include <bb/cascades/QListDataModel>
#include <bb/cascades/Image>
#include <bb/cascades/ImageView>
#include <bb/cascades/CustomControl>
namespace bb {
namespace cascades {
class Container;
}
}
using namespace bb::cascades;
class QNetworkAccessManager;
class PostHttp: public QObject {
Q_OBJECT
public:
PostHttp(QObject* parent = 0);
bb::cascades::Image m_image;
ImageView* imageView;
Container* mRootContainer;
bool createFolder(QString path);
bool openAndSaveFile(QString filePathWithName, QNetworkReply* reply);
public Q_SLOTS:
void loginWebService(const QString &body, const QString &pass,
bool istoken);
void newsFeedWebService(const qint16 num);
void logoutWebService();
void imageFetcher();
void get(const QUrl &url);
void post(const QVariantMap &body, const QUrl &url);
Q_SIGNALS:
void complete(const QVariantList &info);
void newsfeedComplete(const QVariantList &info);
void imageLoaded(const QVariant &image);
private Q_SLOTS:
void onGetReply();
void onNewsFeedReply();
void onImageReply();
Q_INVOKABLE void generatePage();
Q_INVOKABLE void loadImages();
private:
bb::cascades::QListDataModel<QObject*>* m_model;
QImage setImage(const QImage &image);
bb::cascades::DataModel* model() const;
QNetworkAccessManager* m_networkAccessManager;
bb::data::JsonDataAccess* dataAccess;
public:
QString token;
};
#endif
PostHttp.cpp
#include "PostHttp.hpp"
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QSslConfiguration>
#include <QUrl>
#include <bb/data/JsonDataAccess>
#include <QDateTime>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/Page>
#include <bb/cascades/StandardListItem>
#include <QFile>
#include <bb/ImageData>
#include <QNetworkReply>
#include <QNetworkDiskCache>
#include <QDesktopServices>
#include <bb/cascades/Image>
#include <bb/cascades/Container>
#include <bb/cascades/ImageView>
#include <bb/cascades/ScalingMethod>
#include <bb/cascades/DockLayout>
#include <bb/cascades/controls/activityindicator.h>
#include <bb/cascades/controls/scrollview.h>
#include <bb/cascades/controls/page.h>
#include <bb/cascades/NavigationPaneProperties>
#include <bb/cascades/Color>
using namespace bb::data;
using namespace bb::cascades;
using namespace bb::utility;
QString globalTokenValue;
int globalUserId;
bool flag = true;
bool flag1 = true;
QVariantList data;
PostHttp::PostHttp(QObject* parent) :
QObject(parent), m_networkAccessManager(
new QNetworkAccessManager(this)), m_model(
new QListDataModel<QObject*>()) {
}
//! [0]
/**
* PostHttp::post
*
* Make a network request to httpbin.org/post with POST data and get
* the response
*/
//! [1]
void PostHttp::post(const QVariantMap &body, const QUrl &url) {
JsonDataAccess jda;
QByteArray jsonData;
jda.saveToBuffer(*(&body), &jsonData);
QByteArray postDataSize = QByteArray::number(jsonData.size());
QNetworkRequest request(*(&url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setHeader(QNetworkRequest::ContentLengthHeader,
QString(postDataSize).toUtf8());
//QNetworkReply* reply = m_networkAccessManager->post(request, body.toAscii());
qDebug() << "json" << jsonData;
QNetworkReply* reply = m_networkAccessManager->post(request, jsonData);
qDebug() << "strdgfyusujnm kjh " << (&url)->toString();
if ((&url)->toString()
== "http:///GetNewsFeed") {
connect(reply, SIGNAL(finished()), this, SLOT(onNewsFeedReply()));
} else {
connect(reply, SIGNAL(finished()), this, SLOT(onGetReply()));
}
}
void PostHttp::loginWebService(const QString &body, const QString &pass,
bool istoken) {
qint64 date = QDateTime::currentMSecsSinceEpoch();
QString time = QString::number(date);
QVariantMap data;
QVariantMap loginData;
QVariantMap devicedata;
devicedata.insert("OS", "BlackBerry OS 6.0.0.706");
devicedata.insert("deviceId", "232BC441");
devicedata.insert("deviceModel", "9800");
devicedata.insert("screenSize", "480x360");
loginData.insert("device", devicedata);
loginData.insert("email", *(&body));
loginData.insert("password", *(&pass));
loginData.insert("requestDate", "/Date(" + time + "+200)/");
data.insert("apiKey", "4f74721be9b51f24f065b044");
data.insert("data", loginData);
data.insert("requestDate", "/Date(" + time + "+200)/");
if (istoken) {
} else {
data.insert("token", "");
}
const QUrl url(
"http:///LoginRequest");
post(data, url);
}
void PostHttp::newsFeedWebService(const qint16 num) {
qint64 date = QDateTime::currentMSecsSinceEpoch();
QString time = QString::number(date);
QVariantMap data;
QVariantMap newsfeedData;
newsfeedData.insert("postId", 0);
newsfeedData.insert("requestType", 2);
newsfeedData.insert("requestedCount", num);
newsfeedData.insert("userId", globalUserId);
data.insert("apiKey", "4f74721be9b51f24f065b044");
data.insert("data", newsfeedData);
data.insert("requestDate", "/Date(" + time + "+200)/");
data.insert("token", globalTokenValue);
const QUrl url(
"http:///GetNewsFeed");
if (flag == true) {
post(data, url);
}
}
void PostHttp::logoutWebService() {
qint64 date = QDateTime::currentMSecsSinceEpoch();
QString time = QString::number(date);
QVariantMap data;
QVariantMap logoutData;
logoutData.insert("logoutRequestType", 1);
logoutData.insert("userId", globalUserId);
data.insert("apiKey", "4f74721be9b51f24f065b044");
data.insert("data", logoutData);
data.insert("requestDate", "/Date(" + time + "+200)/");
data.insert("token", globalTokenValue);
const QUrl url(
"http:///LogoutUser");
post(data, url);
}
void PostHttp::imageFetcher() {
const QUrl url(
"http://upload.wikimedia.org/wikipedia/commons/e/e7/Nuvola_filesystems_services.png");
if (flag1 == true) {
get(url);
}
}
void PostHttp::get(const QUrl &url) {
QNetworkRequest request(*(&url));
QNetworkReply* reply = m_networkAccessManager->get(request);
connect(reply, SIGNAL(finished()), this, SLOT(onImageReply()));
}
/**
* PostHttp::onGetReply()
*
* SLOT
* Read and return the http response from our http post request
*/
void PostHttp::onGetReply() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QString response;
if (reply) {
if (reply->error() == QNetworkReply::NoError) {
const int available = reply->bytesAvailable();
if (available > 0) {
const QByteArray buffer(reply->readAll());
response = QString::fromUtf8(buffer);
JsonDataAccess dataAccess;
QVariantMap results =
dataAccess.loadFromBuffer(response).toMap();
QString token = (results["Token"]).value<QString>();
int userId = (results["userId"]).value<int>();
if (globalTokenValue == "") {
globalTokenValue = token;
globalUserId = userId;
} else
flag = false;
QString success = (results["Success"]).value<QString>();
}
} else {
response =
tr("Error: %1 status: %2").arg(reply- >errorString(),
reply->attribute(
QNetworkRequest::HttpStatusCodeAttribute).toString());
qDebug() << response;
}
reply->deleteLater();
}
if (response.trimmed().isEmpty()) {
response = tr("Unable to retrieve post response");
}
qDebug() << "response" << response;
}
void PostHttp::onNewsFeedReply() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QString response;
if (reply) {
if (reply->error() == QNetworkReply::NoError) {
flag = false;
const int available = reply->bytesAvailable();
if (available > 0) {
const QByteArray buffer(reply->readAll());
response = QString::fromUtf8(buffer);
JsonDataAccess dataAccess;
QVariantMap results =
dataAccess.loadFromBuffer(response).toMap();
data = results.value("Data").toList();
qDebug() << "first element is" << data.first().toString();
emit newsfeedComplete(data);
}
}
}
}
void PostHttp::onImageReply() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QString response;
QImage img;
QString filePathWithName = "data/img/";
QString imageName;
if (reply) {
if (reply->error() == QNetworkReply::NoError) {
flag1 = false;
const int available = reply->bytesAvailable();
if (available > 0) {
const QByteArray buffer(reply->readAll());
response = QString::fromUtf8(buffer);
img.loadFromData(buffer);
img = img.scaled(40, 40, Qt::KeepAspectRatioByExpanding);
const QImage swappedImage = img.rgbSwapped();
const bb::ImageData imageData = bb::ImageData::fromPixels(
swappedImage.bits(), bb::PixelFormat::RGBX,
swappedImage.width(), swappedImage.height(),
swappedImage.bytesPerLine());
QByteArray byteArray = bb::utility::ImageConverter::encode(
"image/png", imageData, 75);
qDebug() << "bytearray is" << byteArray;
// QVariant image(byteArray);
QVariant realImage(byteArray);
qDebug() << "imag of image is" << realImage;
emit imageLoaded(realImage);
}
}
}
}
//! [1]
And finally my QML file is
NewsFeed.qml
import bb.cascades 1.0
import Network.PostHttp 1.0
import bb.cascades 1.0
import "controls"
import my.library 1.0
Page {
actions: [
ActionItem {
title: "Logout"
onTriggered: {
netpost.logoutWebService();
Application.quit();
}
ActionBar.placement: ActionBarPlacement.OnBar
}
]
id:mainpage
onCreationCompleted: {
Qt.mainImageview = imageviewid;
}
Container {
layout: DockLayout {
}
// The background image
ImageView {
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
imageSource: "asset:///images/background.png"
}
//! [0]
Container {
id : innercontainer
ActivityIndicator {
id: progressIndicator
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
onStarted: {
}
onCreationCompleted: {
progressIndicator.running = true;
}
}
ListView {
id: listView
objectName: "listView"
dataModel: ArrayDataModel {
id: myListModel
}
// Override default GroupDataModel::itemType() behaviour, which is to return item type "header"
listItemComponents: ListItemComponent {
id: listcomponent
// StandardListItem is a convivience component for lists with default cascades look and feel
StandardListItem {
title: ListItemData.postText
description: ListItemData.postDate
status: ListItemData.filePath
imageSource: "asset:///images/4.png"
}
}
layoutProperties: StackLayoutProperties {
spaceQuota: 1.0
}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
}
Container {
id: root
layout: StackLayout {
}
Label {
text: ListItemData.postText
horizontalAlignment: HorizontalAlignment.Left
verticalAlignment: VerticalAlignment.Bottom
}
Label {
text: ListItemData.postDate
// textStyle.fontSize: 5
horizontalAlignment: HorizontalAlignment.Right
verticalAlignment: VerticalAlignment.Bottom
}
attachedObjects: [
QTimer {
id: timer
property int f: 0
interval: 5000
onTimeout: {
progressIndicator.running = false;
netpost.imageFetcher();
netpost.newsFeedWebService("10");
}
},
PostHttp {
id: netpost
onComplete: {
progressIndicator.running = false;
progressIndicator.visible = false;
console.log("dsfdsafs"+netpost.model)
timer.stop();
}
onImageLoaded:{
console.log("value is image from cpp jhgsdh " + image)
imageviewid.setImageSource(image)
}
onNewsfeedComplete: {
console.log("response from newsfeed is "+info)
myListModel.append(info)
}
}
]
}
onCreationCompleted: {
// this slot is called when declarative scene is created
// write post creation initialization here
console.log("Page - onCreationCompleted()")
// enable layout to adapt to the device rotation
// don't forget to enable screen rotation in bar-bescriptor.xml (Application->Orientation->Auto-orient)
OrientationSupport.supportedDisplayOrientation = SupportedDisplayOrientation.All;
// populate list view model with the sample data
timer.start();
// myListModel.load("app/native/assets/mydata.json")
}
ImageView {
id: imageviewid
imageSource: "asset:///images/4.png"
enabled: true
loadEffect: ImageViewLoadEffect.FadeZoom
}
}
}
}
Please help me with this.
So you've defined your slot with QVariant parameter however trying to emit it with QByteArray type which is returned by ImageConverter::encode() call.
Try to change that part of your code to this and give it a go:
QByteArray byteArray = bb::utility::ImageConverter::encode(QUrl(QDir::currentPath() + "/shared/camera/img.png"), imageData, 75);
QVariant image(byteArray);
emit imageLoaded(image);
Also, double check that everywhere where you declare/define this pair of signal/slot you're specified exactly the same parameter notation (ie const QVariant& in case of imageLoaded() signal and so on)
Try this sample code and implement by re-altering in your project
1.QML FILE
import bb.cascades 1.0
Page {
content: Container {
ListView {
dataModel: _app.model
function itemType (data, indexPath) {
return data["type"];
}
listItemComponents: [
]
}
}
}
2.HPP FILE
#ifndef APP_HPP
#define APP_HPP
#include <QtCore/QObject>
#include <QtNetwork/QNetworkAccessManager>
#include <bb/cascades/QListDataModel>
class App: public QObject
{
Q_OBJECT
Q_PROPERTY(bb::cascades::DataModel *model READ model NOTIFY modelChanged)
public:
App();
bb::cascades::DataModel * model() const;
Q_SIGNALS:
void modelChanged();
private Q_SLOTS:
void handleNetworkData(QNetworkReply *reply);
private:
mutable bb::cascades::QMapListDataModel *dataModel;
QNetworkAccessManager networkManager;
};
#endif // APP_HPP
3.CPP FILE
#include <bb/cascades/Page>
#include <bb/cascades/QmlDocument>
#include <bb/data/JsonDataAccess>
#include "App.hpp"
using namespace bb::cascades;
using namespace bb::data;
App::App() :
{
// Load up the QML for our view
QmlDocument *qml = QmlDocument::create("view.qml");
// Provide a reference to this class
qml->setContextProperty("_app", this);
// Create the root node of this view
Page *view = qml->createRootNode<Page>();
dataModel = new QMapListDataModel();
// Hook this signal so we can respond to network replies
connect(&networkManager, SIGNAL(finished(QNetworkReply *)), this,
SLOT(handleNetworkData(QNetworkReply *)));
// Do the request
QUrl url = "http://jsonservice.com/news/headlines/";
networkManager.get(QNetworkRequest(url));
}
DataModel * App::model() const
{
return dataModel;
}
void App::handleNetworkData(QNetworkReply *reply)
{
if (!reply->error()) {
const QByteArray response(reply->readAll());
JsonDataAccess jda;
QVariantMap results = jda.loadFromBuffer(response).toMap();
// Get the relevant parts we want from the JSON
QVariantList posts = results["data"].toMap()["children"].toList();
Q_FOREACH(QVariant post, posts) {
dataModel->append(post);
}
}
// Cleanup
reply->deleteLater();
}

navigate page after parsing in BB 10

I am try to navigate page after parsing but before i got response from server, method getLoginData() is called from Qml file and get false because at the time of calling this function response not get from server, when i click again in button where this function is call, i got accurate result because this time i already got the result. so please help me to solve it out.......
My code...
[B]main.qml[/B]
enter code here
// Navigation pane project template
import bb.cascades 1.0
import bb.system 1.0
NavigationPane {
id: navigationPane
objectName: "navigationPaneQml"
Page {
id: loginPage
objectName : "pageQml"
Container {
id: container1
background: Color.Green
leftPadding: 10
rightPadding: 10
topPadding: 10
layout: StackLayout {
orientation:LayoutOrientation.TopToBottom
}
TextField {
id: usernameBox
objectName: "textFieldRetrived"
hintText: "Enter Your Mobile Number"
topPadding: 10
inputMode: TextFieldInputMode.PhoneNumber
preferredWidth: maxWidth
input {
flags: TextInputFlag.PredictionOff |
TextInputFlag.AutoCorrectionOff
}
// validator: IntValidator {
// bottom: 0
// top: 9999999999
// }
validator: Validator {
mode: ValidationMode.Immediate
errorMessage: "Your username must be 10 characters."
onValidate: {
if (usernameBox.text.length < 10 || usernameBox.text.length > 10) state = ValidationState.Invalid;
else state = ValidationState.Valid;
}
}
// validator: RegExpValidator {
// mode: ValidationMode.Immediate
// regExp: /\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*/
// onValidate: {
// if (usernameBox.text.length <= 10) state = ValidationState.Valid;
// else state = ValidationState.Invalid;
// }
// }
}
Button {
id: submitButton
objectName : submitButtonQml
horizontalAlignment: HorizontalAlignment.Center
// verticalAlignment: VerticalAlignment.Center
text: qsTr("Submit")
preferredWidth: minWidth
// imageSource: "asset:///images/picture1thumb.png"
attachedObjects: [
SystemToast {
id: invalidUsername
body: "Invalid Username"
onFinished: {
// Application.quit();
}
},
SystemToast {
id: networkNotAvalable
body: "Network not Avalable"
onFinished: {
// Application.quit();
}
},
SystemToast {
id: invalidToast
body: "Not a valid input"
onFinished: {
// Application.quit();
}
},
ComponentDefinition {
id: pageDefinition
source: "splash.qml"
}
]
onClicked: {
if(usernameBox.text!= null && usernameBox.text!=""){
if(app.isNetworkAvailable()){
app.initiateRequest(usernameBox.text)
if (app.getLoginData() == "True"){
var newPage = pageDefinition.createObject();
navigationPane.push(newPage);
}else{
invalidUsername.show()
}
}else {
networkNotAvalable.show()
}
}else{
invalidToast.show()
}
}
}
TextArea {
id: chat
objectName: "textArea"
inputMode: TextAreaInputMode.Default
}
Container {
id: cntrUpdates
horizontalAlignment: HorizontalAlignment.Center
// verticalAlignment: VerticalAlignment.Top
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
preferredWidth: 1280.0
leftPadding: 90.0
topPadding: 20.0
Label {
objectName: "lblRetrieve"
text: "Retrieving contact list ..."
textStyle.textAlign: TextAlign.Right
verticalAlignment: VerticalAlignment.Center
}
// The activity indicator has an object name set so that
// we can start and stop it from C++ code.
ActivityIndicator {
objectName: "indicator"
running: false
}
}
}
}
onCreationCompleted: {
// this slot is called when declarative scene is created
// write post creation initialization here
console.log("NavigationPane - onCreationCompleted()");
// enable layout to adapt to the device rotation
// don't forget to enable screen rotation in bar-bescriptor.xml (Application->Orientation->Auto-orient)
OrientationSupport.supportedDisplayOrientation = SupportedDisplayOrientation.All;
}
}
[B]DemoProject2.cpp[/B]
// Navigation pane project template
#include "DemoProject2.hpp"
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <QIODevice>
#include <bb/cascades/XmlDataModel>
#include <bb/cascades/Color>
#include <bps/bps.h>
#include <bps/netstatus.h>
#include <bps/locale.h>
#include <QXmlStreamReader>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <iostream>
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QDomDocument>
#include <QDomNodeList>
#include <QtXml/qxml.h>
#include <QString>
#include <bb/cascades/ValidationMode>
#include <bb/cascades/Validator>
#include <bb/system/SystemToast>
#include <bb/system/SystemUiPosition>
#include <QtCore/QDebug>
using namespace bb::cascades;
using namespace bb::system;
DemoProject2::DemoProject2(bb::cascades::Application *app)
: QObject(app)
{
// create scene document from main.qml asset
// set parent to created document to ensure it exists for the whole application lifetime
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
// Expose this class to QML so that we can call it's functions from C++ code.
qml->setContextProperty("app", this);
// create root object for the UI
AbstractPane *root = qml->createRootObject<AbstractPane>();
// set created root object as a scene
// Retrieve the activity indicator from QML so that we can start
// and stop it from C++ code.
myActivityIndicator = root->findChild<ActivityIndicator*>("indicator");
myTextField = root->findChild<TextField*>("textFieldRetrived");
myLabel = root->findChild<Label*>("lblRetrieve");
textArea = root->findChild<TextArea*>("textArea");
submitButton = root->findChild<Button*>("submitButtonQml");
// navigationPane = root->findChild<NavigationPane*>("navigationPaneQml");
// root = qml->createRootObject<NavigationPane>();
// QmlDocument *qml1 = QmlDocument::create("asset:///splash.qml").parent(this);
//// mNewPage = new Page();
// mNewPage = qml1->createRootObject<Page>();
myNetworkAccessManager = new QNetworkAccessManager(this);
connect(myNetworkAccessManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(requestFinished(QNetworkReply*)));
// Create a file in the file system that we can use to save the data model.
myFile = new QFile("data/model.xml");
app->setScene(root);
}
bool DemoProject2::isNetworkAvailable() {
QNetworkConfigurationManager netMgr;
QList<QNetworkConfiguration> mNetList = netMgr.allConfigurations(
QNetworkConfiguration::Active);
if (mNetList.count() > 0) {
if (netMgr.isOnline()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
void DemoProject2::initiateRequest(QString text){
text.trimmed();
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","hhhh");
isComplete = false;
// Start the activity indicator.
myActivityIndicator->start();
myLabel->setVisible(true);
myLabel->setText("Retrieving contact list ...");
// Create and send the network request.
QNetworkRequest request = QNetworkRequest();
request.setUrl(QUrl("******************"));
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","00");
myNetworkAccessManager->get(request);
}
void DemoProject2::requestFinished(QNetworkReply* reply){
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","NUM 0");
myActivityIndicator->stop();
myLabel->setVisible(false);
// Check the network reply for errors.
if (reply->error() == QNetworkReply::NoError){
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","NUM 1");
/****** Sax Parsing code Section..................******/
QByteArray data = reply->readAll();
xmlSaxParser(data);
/****** dom parsing code section ........******/
// QByteArray byteArray = reply->readAll();
// xmlDomParser(byteArray);
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","NUM 2");
reply->deleteLater();
}
}
bool DemoProject2:: getCompleteVariable(){
return isComplete;
}
void DemoProject2 :: setLoginData(QString data){
loginData = data;
}
QString DemoProject2 :: getLoginData(){
while(!getCompleteVariable()){
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","shivang");
}
return loginData;
}
void DemoProject2:: xmlSaxParser(QByteArray data){
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","NUM 3");
// The XML stream reader that is used to extract the articles from the RSS feed
QXmlStreamReader m_xml;
m_xml.addData(data);
QString currentTag = "";
QString linkString;
QString titleString;
while (!m_xml.atEnd())
{
m_xml.readNext();
if (m_xml.isStartElement())
{
if (m_xml.name() == "contacts"){
linkString = m_xml.attributes().value("title").toString();
currentTag = m_xml.name().toString();
myLabel->setVisible(true);
myLabel->setText(linkString);
}else if(m_xml.name() == "return"){
currentTag = m_xml.name().toString();
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","ns:return");
}
}
else if (m_xml.isEndElement())
{
if (m_xml.name() == "return")
{
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","return");
// linkString = m_xml.attributes().value("rss:about").toString();
titleString.clear();
// linkString.clear();
}
} else if (m_xml.isCharacters() && !m_xml.isWhitespace())
{
if (currentTag == "return"){
titleString += m_xml.text().toString();
myLabel->setVisible(true);
myLabel->setText(titleString);
setLoginData(titleString);
// textArea->setText(titleString);
// currentTag = "";
}
}
}
if (m_xml.error() && m_xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
// m_feeds.append(
// QString::fromLatin1("XML ERROR: %1: %2").arg(m_xml.lineNumber()).arg(m_xml.errorString()));
}
fprintf(stderr, "Debug::::::::::::::::::::::::::: %s\n","NUM 4");
// navigationPane->push(mNewPage);
isComplete = true;
}
[B]DemoProject2.hpp[/B]
// Navigation pane project template
#ifndef DemoProject2_HPP_
#define DemoProject2_HPP_
#include <QObject>
#include <QFile>
#include <QString>
#include <bb/cascades/ActivityIndicator>
#include <bb/cascades/TextField>
#include <bb/AbstractBpsEventHandler>
#include <bb/cascades/Application>
#include <bb/cascades/Label>
#include <bb/cascades/TextArea>
#include <bb/cascades/Button>
#include <bb/cascades/NavigationPane>
#include <bb/cascades/Page>
using namespace bb::cascades;
namespace bb { namespace cascades { class Application; }}
/*!
* #brief Application pane object
*
*Use this object to create and init app UI, to create context objects, to register the new meta types etc.
*/
class DemoProject2 : public QObject
{
Q_OBJECT
public:
DemoProject2(bb::cascades::Application *app);
virtual ~DemoProject2() {}
// void parseXml (QByteArray data);
Q_INVOKABLE void initiateRequest(QString text);
Q_INVOKABLE bool isNetworkAvailable();
Q_INVOKABLE void xmlSaxParser(QByteArray data);
Q_INVOKABLE void xmlDomParser(QByteArray data);
Q_INVOKABLE QString getLoginData();
Q_INVOKABLE void setLoginData(QString data);
Q_INVOKABLE bool getCompleteVariable();
// NavigationPane *root;
// signals:
// void networkStatusUpdated(bool status, QString type);
private slots:
void requestFinished(QNetworkReply* reply);
// void networkStatusUpdateHandler(bool status, QString type);
private:
bb::cascades::TextField *myTextField;
bb::cascades::ActivityIndicator *myActivityIndicator;
bb::cascades::Label *myLabel;
bb::cascades::TextArea *textArea;
bb::cascades::Button *submitButton;
// bb::cascades::NavigationPane* navigationPane;
// bb::cascades:: Page* mNewPage;
QNetworkAccessManager *myNetworkAccessManager;
QFile *myFile;
QString loginData;
QByteArray data;
bool isComplete;
// Page* mNewPage;
// StatusEvent *statusEvent;
};
#endif /* DemoProject2_HPP_ */
use event loop....
QNetworkAccessManager* netManager = new QNetworkAccessManager();
QUrl myurl("http://******");
QNetworkRequest req(myurl);
QNetworkReply* ipReply = netManager->get(req);
QEventLoop eventLoop;
QObject::connect(ipReply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec();
std::cout << "finished" << std::endl; //request finished here
requestFinished(ipReply);