navigate page after parsing in BB 10 - c++

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);

Related

QML component isn't displayed if it was created programmatically from C++

My goal is to create a custom Component (lets call it ComponentLoader) which can instantiate another component (lets call it DelegateComponent) via delegate.
The problem is that the instance of DelegateComponent isn't displayed after is was created (white screen). Note: tst_component is loaded message IS present which means that DelegateComponent instance was actually created.
Here is a minimal example:
main.qml
ApplicationWindow {
id: mainWindow
width: 640
height: 480
visible: true
Component {
id: tst_component
Rectangle {
anchors.fill: parent
Component.onCompleted: {
console.debug("tst_component is loaded");
}
Label {
text: "hello world"
anchors.centerIn: parent
}
}
}
// doesn't work
ComponentLoader {
anchors.fill: parent
delegate: tst_component
}
// works
// Loader {
// anchors.fill: parent
// sourceComponent: tst_component
// }
}
componentloader.h + componentloader.cpp
#pragma once
#include <QQuickItem>
class ComponentLoader : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
public:
QQmlComponent* delegate() const;
void setDelegate(QQmlComponent*);
signals:
void delegateChanged();
private:
void generate();
protected:
void componentComplete() override;
private:
QQmlComponent* mDelegate = nullptr;
};
// componentloader.cpp
#include "componentloader.h"
#include <QtWidgets/QtWidgets>
#include <QtQmlModels/QtQmlModels>
#include <QQuickWindow>
QQmlComponent* ComponentLoader::delegate() const
{
return mDelegate;
}
void ComponentLoader::setDelegate(QQmlComponent* delegate)
{
if (delegate != mDelegate)
{
mDelegate = delegate;
emit delegateChanged();
}
}
void ComponentLoader::componentComplete()
{
QQuickItem::componentComplete();
generate();
}
void ComponentLoader::generate()
{
QQmlEngine* engine = qmlEngine(this);
QQmlContext* root_ctx = engine->rootContext();
QQmlContext* ctx = new QQmlContext(root_ctx);
QObject* item = mDelegate->create(ctx);
QQuickItem* quickItem = qobject_cast<QQuickItem*>(item);
QQuickItem* quickParent = qobject_cast<QQuickItem*>(parent());
quickItem->setParent(quickParent);
quickItem->setParentItem(quickParent);
}
Your quickParent pointer is taking the QObject parent() value instead of the QQuickItem parentItem() value.
Simply changing it to this worked for me when I tried your code:
QQuickItem* quickParent = qobject_cast<QQuickItem*>(parentItem());
I also don't think you need to call setParent() at all. Just setParentItem().

Performance problems when parsing large vectors in QML using Repeater

I'm parsing a list of ~4000 emojis from a C++ QAbstractListModel subclass using Repeatables.
The emojis are being collected in a class called EmojiList:
emojilist.h
#include <QVector>
class EmojiList {
public:
struct EmojiData {
EmojiData(const QString& _code, const QString& _shortname, const QString& _category) :
code(_code),
shortname(_shortname),
category(_category)
{}
QString code;
QString shortname;
QString category;
};
static const QVector<EmojiData>& list();
private:
QVector<EmojiData> emojiList;
void parseFromFile();
};
emojilist.cpp
#include "emojilist.h"
#include <QFile>
#include <QTextStream>
const QVector<EmojiList::EmojiData>& EmojiList::list()
{
static EmojiList list;
if (list.emojiList.isEmpty()) {
list.parseFromFile();
}
return list.emojiList;
}
void EmojiList::parseFromFile()
{
QFile emojiResource { ":/media/new_emoji.list" };
if (emojiResource.open(QIODevice::ReadOnly)) {
QTextStream in { &emojiResource };
while (!in.atEnd()) {
QStringList line { in.readLine().split(',') };
emojiList.append({ line.at(0), line.at(1), line.at(2) });
}
}
emojiResource.close();
}
Then, the data is being retrieved in the QAbstractListModel subclass EmojiListModel:
emojilistmodel.cpp
QVariant EmojiListModel::data(const QModelIndex &index, int role) const
{
if (_emojiMap.isEmpty() || !index.isValid() || index.row() > _emojiMap.size()) {
return QVariant();
}
switch (role) {
case EmojiName:
return _emojiMap.at(index.row()).shortname;
case Emoji:
return _emojiMap.at(index.row()).code;
case EmojiCategory: {
return _emojiMap.at(index.row()).category;
}
default:
return QVariant();
}
}
On the front-end side, I'm displaying the model data using a Repeater:
EmojiWindow.qml
ScrollView {
// ...
clip: true
GridLayout {
id: emojiGridView
// ...
Repeater {
id: emojiContainer
model: EmojiListModel {
id: emojiListModel
objectName: "emojiListModel"
}
Rectangle {
// ...
property string delegateEmojiName: emojiName
Text {
id: emojiIcon
text: emoji
// ...
}
MouseArea {
// ...
onClicked: messageField.text += emojiIcon.text
}
}
}
}
}
Now, when starting the application, it takes about 5 minutes to create all Repeater delegates to construct and thus for the whole application to start up.
How can I optimize performance in my QML file to load about 4000 emojis on startup? Is there some way to lazy-load the data to be displayed?
Thanks a lot in advance.

How to display value of 2D Array to QML from C++, using Repeater and GridView

I have problem when display value of 2D array QString on QML from C++
I have data and a qmlRegisterType to use on QML.
This is QML file:
import QtQuick 2.12
import QtQuick.Window 2.2
import io.myserial 1.0
import QtQuick.Controls 2.3
Window {
visible: true
width: 8*square_size
height: 8*square_size
title: qsTr("Matrix LDR Value")
property int square_size: 50
Grid {
id: grid
columns: 8
Repeater{
id: rpt
model: 8*8
Rectangle{
width: square_size
height: square_size
border.color: "black"
border.width: 1
Text {
id: txt
anchors.centerIn: parent
}
MSerial{
onModelDataChanged:{
txt.text = Serial.model_data[i]
}
}
}
}
}
}
This is main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "serial.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<Serial>("io.myserial", 1, 0, "MSerial");
QQmlApplicationEngine engine;
Serial mySerial(&engine);
engine.rootContext()->setContextProperty("Serial", &mySerial);
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();
}
serial.h
#ifndef SERIAL_H
#define SERIAL_H
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QQmlApplicationEngine>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtDebug>
#include <QObject>
#include <QString>
#include <QString>
#include "toInt16.h"
class Serial: public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QString> modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
public:
explicit Serial(QObject *parent = nullptr);
QList<QString> modelData();
Q_INVOKABLE void setModelData(const QList<QString> &modelData);
void ReadSerial();
void setUpSerial();
QByteArray serialData;
QSerialPort stm32;
QString portName;
QString buffer;
bool isStm32Avaiable;
private slots:
void readSerial();
signals:
void modelDataChanged();
private:
QList<QString> myModelData;
public slots:
};
#endif // SERIAL_H
serial.cpp
#include "serial.h"
#include "toInt16.h"
Serial::Serial(QObject *parent) : QObject(parent)
{
setUpSerial();
}
QList<QString> Serial::modelData()
{
return myModelData;
}
void Serial::setUpSerial(){
buffer = "";
isStm32Avaiable = false;
portName = "";
qDebug()<<"Num port: "<<QSerialPortInfo::availablePorts().length();
foreach (const QSerialPortInfo &serialPortInfor,QSerialPortInfo::availablePorts()) {
qDebug()<<"Has Vendo ID: "<<serialPortInfor.hasVendorIdentifier();
if(serialPortInfor.hasVendorIdentifier()){
qDebug()<<"Vendo ID: "<<serialPortInfor.vendorIdentifier();
}
qDebug()<<"Has Product ID: "<<serialPortInfor.hasProductIdentifier();
if(serialPortInfor.hasProductIdentifier()){
qDebug()<<"Product ID: "<<serialPortInfor.productIdentifier();
portName = serialPortInfor.portName();
}
if(QSerialPortInfo::availablePorts().length() >0){
isStm32Avaiable = true;
}
}
if(isStm32Avaiable){
stm32.setPortName(portName);
stm32.open(QSerialPort::ReadWrite);
stm32.setBaudRate(QSerialPort::Baud115200);
stm32.setDataBits(QSerialPort::Data8);
stm32.setParity(QSerialPort::NoParity);
stm32.setStopBits(QSerialPort::OneStop);
stm32.setFlowControl(QSerialPort::NoFlowControl);
QObject::connect(&stm32, SIGNAL(readyRead()),this,SLOT(readSerial()));
}else{
qDebug()<<"warning: Port Error . Couldn't find kit";
}
}
void Serial::setModelData(const QList<QString> &modelData)
{
if (modelData == myModelData)
return;
myModelData = modelData;
emit modelDataChanged();
}
void Serial::ReadSerial()
{
serialData.clear();
serialData = stm32.readAll();
QByteArray buffer;
qDebug()<< "Serial Data: "<<serialData;
buffer = serialData;//.split(',');
// QStringList buffer2;
//uint16_t data[64];
union INT_TO_BYTE receivedData[64];
for(int i=0; i<64; i++){
receivedData[i].b[0] = buffer.data()[i*2];
receivedData[i].b[1] = buffer.data()[i*2+1];
receivedData[i].i = (uint16_t)receivedData[i].b[0]|(uint16_t)receivedData[i].b[1]<<8;
qDebug() << "This is data "<<i<<" "<<receivedData[i].i;
myModelData.append(QString::number(receivedData[i].i));
}
//setModelData(myModelData);
emit modelDataChanged();
}
toInt16.h
#ifndef TOINT16_H
#define TOINT16_H
#include <QTextCodec>
union INT_TO_BYTE
{
uint16_t i;
char b[2];
};
//union INT_TO_BYTE receivedData[128];
#endif // TOINT16_H
I received data but I cannot display it on QML whenever data is changed. I set it change 1view/sec.
My logic is: Whenever data change, QML display new data
In your code I see the following errors:
Or you register a type with qmlRegisterType or set it as contextProperty, not both. I recommend you check Choosing the Correct Integration Method Between C++ and QML.
In your repeater you are creating N MySerial but you can only have 1, the idea is that you create a MySerial and the information is passed to the model.
Do not use QList<QString> but QStringList.
Your data should not be written from QML so it is not necessary for the modelData property to be Writeble.
Considering the above and avoiding the part of the decoding of the data since I do not know the format that will replace it creating random data the solution is the following:
serial.cpp
#ifndef SERIAL_H
#define SERIAL_H
#include <QObject>
#include <QSerialPort>
class Serial : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList modelData READ modelData NOTIFY modelDataChanged)
public:
explicit Serial(QObject *parent = nullptr);
QStringList modelData() const;
Q_SIGNALS:
void modelDataChanged();
private Q_SLOTS:
void readSerial();
private:
void setUpSerial();
QStringList m_modelData;
bool isStm32Avaiable;
QString portName;
QSerialPort stm32;
};
#endif // SERIAL_H
serial.cpp
#include "serial.h"
#include "toInt16.h"
#include <QSerialPortInfo>
#include <QDebug>
Serial::Serial(QObject *parent) : QObject(parent){
m_modelData.reserve(64);
setUpSerial();
}
QStringList Serial::modelData() const{
return m_modelData;
}
void Serial::setUpSerial(){
isStm32Avaiable = false;
portName = "";
qDebug()<<"Num port: "<<QSerialPortInfo::availablePorts().length();
for (const QSerialPortInfo &serialPortInfor : QSerialPortInfo::availablePorts()) {
qDebug()<<"Has Vendo ID: "<<serialPortInfor.hasVendorIdentifier();
if(serialPortInfor.hasVendorIdentifier()){
qDebug()<<"Vendo ID: "<<serialPortInfor.vendorIdentifier();
}
if(serialPortInfor.hasProductIdentifier()){
qDebug()<<"Product ID: "<<serialPortInfor.productIdentifier();
portName = serialPortInfor.portName();
}
if(!QSerialPortInfo::availablePorts().isEmpty()){
isStm32Avaiable = true;
break;
}
}
if(isStm32Avaiable){
stm32.setPortName(portName);
stm32.open(QSerialPort::ReadWrite);
stm32.setBaudRate(QSerialPort::Baud115200);
stm32.setDataBits(QSerialPort::Data8);
stm32.setParity(QSerialPort::NoParity);
stm32.setStopBits(QSerialPort::OneStop);
stm32.setFlowControl(QSerialPort::NoFlowControl);
connect(&stm32, &QIODevice::readyRead, this, &Serial::readSerial);
}else{
qDebug()<<"warning: Port Error . Couldn't find kit";
}
}
void Serial::readSerial(){
m_modelData.clear();
// FIXME
static int counter;
for(int i=0; i<64; i++){
m_modelData.append(QString::number(counter));
counter++;
}
//
emit modelDataChanged();
}
main.cpp
#include "serial.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qmlRegisterType<Serial>("io.myserial", 1, 0, "MSerial");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
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();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import io.myserial 1.0
Window {
visible: true
width: 8*square_size
height: 8*square_size
title: qsTr("Matrix LDR Value")
property int square_size: 50
MSerial{
id: serial
}
Grid {
columns: 8
Repeater{
model: serial.modelData
Rectangle{
width: square_size
height: square_size
border.color: "black"
border.width: 1
Text {
id: txt
anchors.centerIn: parent
text: model.modelData
}
}
}
}
}

Inserting/Deleting Items in a drag&drop QML listView with cpp model

I tried to add to a ListView in QML of N Items a way to add and delete a new Item at a given index.
I did the following example, but the problem is that when I move some Items, when I try to insert a new one, the position might be incorrect and I have no clue why. When I check my DataList in my cpp model, positions are correct, however, new or deleted items won't be inserted/deleted at the right position.
It seems that the error occurs when I insert a new Item, then I move it , and then I try to delete this Item or insert an Item next to this New Item.
Here is a simple example (you can run it if you need). I called my Items Data : Blocks
#include "mainwindow.h"
#include <QApplication>
#include <QtQml>
#include <QQuickView>
#include <QQuickWidget>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
main.cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "model.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void addItem(int index);
~MainWindow();
private slots:
private:
QList<QObject*> dataList;
Ui::MainWindow *ui;
BlockModel model;
int cpt = 0;
};
#endif // MAINWINDOW_H
mainwindow.h
#include <QtQml>
#include <QQuickView>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QQuickWidget"
#include <QStringList>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
int nbItems = 5;
for(; cpt < nbItems; cpt ++) {
Block a = Block(QString("Item ")+QString::number(cpt));
model.addBlock(a);
}
ui->setupUi(this);
QQuickWidget *view = new QQuickWidget;
QQmlContext *ctxt = view->rootContext();
ctxt->setContextProperty("myModel", &model);
view->setSource(QUrl::fromLocalFile("main.qml"));
view->setGeometry(0, 200, 600, 400);
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
ui->dockWidget_3->setWidget(view);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.cpp
#include <QAbstractListModel>
#include <QStringList>
#include <qqmlcontext.h>
#include <QDebug>
#include <QStringList>
//![0]
class Block
{
public:
Block(){
}
Block(const QString &name);
QString nameBlock() const;
void setName(QString n) {
m_name = n;
}
private:
QString m_name;
};
class BlockModel : public QAbstractListModel
{
Q_OBJECT
public:
Block* getBlock(QString name);
Q_INVOKABLE void moveBlock(int from,int to);
Q_INVOKABLE void insertBlock(int index);
Q_INVOKABLE void deleteBlock(int index);
enum BlockRoles {
nameRole = Qt::UserRole + 1,
};
BlockModel(QObject *parent = 0);
void setContext(QQmlContext *ctx) {
m_ctx = ctx;
}
void setName(const QString &name);
void addBlock(const Block &Block);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
private:
QList<Block> m_blocks;
QQmlContext* m_ctx;
int cpt = 0;
};
mode.h
#include "model.h"
#include "qDebug"
Block::Block(const QString &name)
: m_name(name)
{
}
QString Block::nameBlock() const
{
return m_name;
}
BlockModel::BlockModel(QObject *parent)
: QAbstractListModel(parent)
{
}
void BlockModel::addBlock(const Block &Block)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_blocks << Block;
endInsertRows();
}
int BlockModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return m_blocks.count();
}
void BlockModel::moveBlock(int from, int to) {
m_blocks.move(from,to);
}
void BlockModel::insertBlock(int index) {
Block b =(Block(QString("New Item ")+QString::number(cpt)));
beginInsertRows(QModelIndex(),index+1,index+1);
m_blocks.insert(index+1,b);
endInsertRows();
cpt++;
}
void BlockModel::deleteBlock(int index) {
beginRemoveRows(QModelIndex(),index,index);
m_blocks.removeAt(index);
endRemoveRows();
}
QVariant BlockModel::data(const QModelIndex & index, int role) const {
if (index.row() < 0 || index.row() >= m_blocks.count())
return QVariant();
const Block &Block = m_blocks[index.row()];
if (role == nameRole)
return Block.nameBlock();
return QVariant();
}
//![0]
QHash<int, QByteArray> BlockModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[nameRole] = "nameBlock";
return roles;
}
model.cpp
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQml.Models 2.2
import QtQuick.Controls.Styles 1.4
Rectangle {
id : rootRectangle
visible: true
ScrollView {
anchors.fill:parent
ListView{
id: root
width: parent.width; height: parent.height
property int visualIndex: -1
displaced: Transition {
NumberAnimation { properties: "y"; easing.type: Easing.OutQuad }
}
model: DelegateModel {
id: visualModel
model: myModel
delegate: Component {
MouseArea {
id: delegateRoot
property int visualIndex: DelegateModel.itemsIndex
cursorShape: Qt.PointingHandCursor
width: root.width; height: 100
drag.target: icon
drag.axis: Drag.YAxis
Behavior on height {
PropertyAnimation { duration: 100 }
}
Rectangle {
anchors.top: delegateRoot.top
anchors.left: delegateRoot.left
id: icon
objectName: nameBlock
width: root.width-5; height: 100
color: "skyblue"
radius: 3
Text {
objectName: "rect"
id: title
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: nameBlock
}
Drag.active: delegateRoot.drag.active
Drag.source: delegateRoot
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
Button {
id : buttonAdd
text: "Add Block"
anchors{
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 30
}
onClicked: {
myModel.insertBlock(visualIndex)
}
}
Button {
id : buttonDelete
text: "Delete Block"
anchors{
right: buttonAdd.left
top: parent.top
bottom: parent.bottom
margins: 30
}
onClicked: {
myModel.deleteBlock(visualIndex)
}
}
states: [
State {
when: icon.Drag.active
ParentChange {
target: icon
parent: root
}
AnchorChanges {
target: icon;
anchors.horizontalCenter: undefined;
anchors.verticalCenter: undefined
}
}
]
transitions: Transition {
// Make the state changes smooth
ParallelAnimation {
ColorAnimation { property: "color"; duration: 500 }
NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width,font.pixelSize,font.bold,visible" }
}
}
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
myModel.moveBlock(drag.source.visualIndex,delegateRoot.visualInde)
}
}
}
}
}
}
}
}
main.qml
Do you have any idea of what I am doing wrong ?
Thanks a lot and have a good day !
There are two bugs when moving items. In DropArea.onEntered, if you print out both drag.source.visualIndex and delegateRoot.visualIndex before and after visualModel.items.move, you'll see that values are modified after moving. That means you are moving wrong rows when calling myModel.moveBlock. To fix the problem, save the value before moving items:
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
var from = drag.source.visualIndex;
var to = delegateRoot.visualIndex;
myModel.moveBlock(from, to);
}
}
When moving items in C++ model, QAbstractItemModel::beginMoveRows should be called just like insert/remove items. Otherwise the QML DelegateModel cannot correctly display your model. Remember that when implementing BlockModel::moveBlock, the destination row for the model is different from the one for your source list m_blocks. See the last example in QAbstractItemModel::beginMoveRows documentation for detail.
void BlockModel::moveBlock(int from, int to) {
if (from == to)
return;
auto modelFrom = from;
auto modelTo = to + (from < to ? 1 : 0);
beginMoveRows(QModelIndex(), modelFrom, modelFrom, QModelIndex(), modelTo);
m_blocks.move(from,to);
endMoveRows();
}

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();
}