PDA

View Full Version : Best way to pass data from backend c++



Nio74
15th March 2019, 10:33
Hi, I need to link the data from the classes connected to the backend, for example I have this class where it receives the data from the server through this method:



void ClientServices::readyRead()
{
QDataStream in(tcpSocket);//QtcpSocket

int code = 0;
double pCost = 0;
double pPublic = 0;

in >> code >> pCost >> pPublic;

qDebug() << code << pCost << pPublic;


}



the Backend is declare in this mode:

qmlRegisterType<Backend>("io.qt.Backend", 1, 0, "Backend");

can I do?

I think to do with the Q_Property but but I wouldn't go for the backend anymore. In practice I have to fill in text boxes with variable :

code >> pCost >> pPublic;

see my schema:
13047

anda_skoa
15th March 2019, 13:16
Since your other thread suggests that you will get multiple "rows" of these three values, the best way to present these rows of values to QML/QtQuick is a list model.

The ClientService object needs to notify the model about new incoming data, maybe via signal.

Easiest way is probably to do all the object creation and connecting on the C++ side and simply expose the fully working model to QML via QQmlContext::setContextProperty() on the engine's rootContext().

Cheers,
_

Nio74
15th March 2019, 13:42
I think I'll follow your path,when I have done I'll show you,tanks for help me

Nio74
15th March 2019, 21:39
there are almost, the signal emit sendCode (c_code); is data download, I will look in the qml when I call it "ReferenceError: c_code is not defined" error
13050

this is my code Qml:


Backend {
id: backend

onSendCode: {
console.log( "This is code---> " + c_code);
}

}

Nio74
16th March 2019, 07:08
Good moorning it give me a error in the row 16: ReferenceError: code is not defined

this is my Riparazioni.qml



import QtQuick 2.10
import QtQuick.Controls 2.3
import io.qt.Backend 1.0

Item
{
id: element

Backend {
id: backend

onSendCode: {

console.log( "This is code---> " + code); // errrrrrrrrrorrrrrrrr
}

}


Row {
id: row1
height: 50
anchors.right: parent.right
anchors.rightMargin: 5
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 3

Rectangle {
id: rectangle_Search
height: 44
color: "#0e99b2"
anchors.top: parent.verticalCenter
anchors.topMargin: -25
anchors.left: parent.left

anchors.right: parent.right


Text {
id:lbl_SearchCode
color: "#0a0808"
text: qsTr("Codice")
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 4
font.pixelSize: 12
}

CustomTextEdit {
id: c_Txt_codice
y: 0
width: 50
height: 20
anchors.verticalCenter: parent.verticalCenter
anchors.bottom: parent
anchors.bottomMargin: 0
anchors.left: lbl_SearchCode.right
anchors.leftMargin: 20

}

CustomButton {
id: btnSearchKey
x: 583
y: 3
text: "S"
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 5
anchors.top: parent.verticalCenter
anchors.topMargin: -22
color: enabled ? this.down ? "#78C37F" : "#87DB8D" : "gray"
onClicked: {
// backend.connectClicked()
backend.connectClicked()
backend.sendClicked(c_Txt_codice.text)
}
}

}
}
Row {
id: row2
height: 200
anchors.right: parent.right
anchors.rightMargin: 3
anchors.left: parent.left
anchors.leftMargin: 3
anchors.top: row1.bottom
anchors.topMargin: 2

Rectangle{
id: rectangle_Articolo
color: "#0e99b2"
anchors.fill: parent



Label{
id: lbl_NBusta
color: "#ebedef"
text: "NĀ°Busta"
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 10
}

CustomTextEdit {
id: txtCodice
width: 40
height: 18
anchors.top: parent.top
anchors.topMargin: 10
anchors.left: lbl_NBusta.right
anchors.leftMargin: 10
}

}

}
}


this is my main.cpp



int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDp iScaling);

QGuiApplication app(argc, argv);

//Pass my c++ to Qml

//qmlRegisterType<ClientServices>("io.qt.Clienteservices", 1, 0, "Clientservices");


qmlRegisterType<Backend>("io.qt.Backend", 1, 0, "Backend");
// Backend backend;

// QQmlContext *context = engine.rootContext();
// context->setContextProperty("backend",&backend);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));


if (engine.rootObjects().isEmpty())
return -1;

return app.exec();
}



this is the Signal with send at Riparazioni.qml and I have do the debug it has data:

13051

anda_skoa
16th March 2019, 09:26
How is the sendCode() parameter called in the signal's declaration?

And: have you decided against using a model?

Cheers,
_

Nio74
16th March 2019, 09:48
in the backend constructor


#include "backend.h"

Backend::Backend(QObject *parent) : QObject(parent)
{
client = new ClientServices("192.168.1.72",6547);

connect(client, &ClientServices::hasReadSome, this, &Backend::receivedSomething);
connect(client, &ClientServices::statusChanged, this, &Backend::setStatus);
// FIXME change this connection to the new syntax
connect(client->tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(gotError(QAbstractSocket::SocketError)));

//connect data to source database
connect(client, &ClientServices::sendRiparazione, this ,&Backend::recivedRiparazione);


}


bool Backend::getStatus()
{
return client->getStatus();
}

void Backend::setStatus(bool newStatus)
{
//qDebug() << "new status is:" << newStatus;
if (newStatus)
{ emit statusChanged("CONNECTED"); }
else
{ emit statusChanged("DISCONNECTED"); }
}

void Backend::recivedRiparazione(int code, double p_pCosto, double p_Pubblico)
{
emit sendCode(code);
emit sendPCosto(p_pCosto);
emit sendPPubblico(p_Pubblico);

}

void Backend::receivedSomething(QString msg)
{
emit someMessage(msg);
}



void Backend::gotError(QAbstractSocket::SocketError err)
{
//qDebug() << "got error";
QString strError = "unknown";
switch (err)
{
case 0:
strError = "Connection was refused";
break;
case 1:
strError = "Remote host closed the connection";
break;
case 2:
strError = "Host address was not found";
break;
case 5:
strError = "Connection timed out";
break;
default:
strError = "Unknown error";
}

emit someError(strError);
}

void Backend::connectClicked()
{
client->connect2host();
}

void Backend::sendClicked(QString msg)
{
QByteArray arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
//out.setVersion(QDataStream::Qt_5_10);
out << quint16(0) << msg;

out.device()->seek(0);
out << quint16(arrBlock.size() - sizeof(quint16));

client->tcpSocket->write(arrBlock);
}

void Backend::disconnectClicked()
{
client->closeConnection();
}




this is clientService.cpp:

#include "clientservices.h"
#include <QBuffer>


ClientServices::ClientServices(const QString hostAddress, int portNumber) : QObject (),m_nNextBlockSize(0)
{
status = false;
tcpSocket = new QTcpSocket();

host = hostAddress;
port = portNumber;

timeoutTimer = new QTimer();
timeoutTimer->setSingleShot(true);
connect(timeoutTimer, &QTimer::timeout, this, &ClientServices::connectionTimeout);

connect(tcpSocket, &QTcpSocket::disconnected, this, &ClientServices::closeConnection);

}

bool ClientServices::getStatus(){return status;
}

void ClientServices::closeConnection()
{
timeoutTimer->stop();

//qDebug() << tcpSocket->state();
disconnect(tcpSocket, &QTcpSocket::connected, 0, 0);
disconnect(tcpSocket, &QTcpSocket::readyRead, 0, 0);

bool shouldEmit = false;
switch (tcpSocket->state())
{
case 0:
tcpSocket->disconnectFromHost();
shouldEmit = true;
break;
case 2:
tcpSocket->abort();
shouldEmit = true;
break;
default:
tcpSocket->abort();
}

if (shouldEmit)
{
status = false;
emit statusChanged(status);
}

}

void ClientServices::connect2host()
{

timeoutTimer->start(3000);

tcpSocket->connectToHost(host, port);
connect(tcpSocket, &QTcpSocket::connected, this, &ClientServices::connected);
connect(tcpSocket, &QTcpSocket::readyRead, this, &ClientServices::readyRead);
}

void ClientServices::readyRead()
{
QDataStream in(tcpSocket);//QtcpSocket

in >> code >> pCost >> pPublic;

qDebug() << code << pCost << pPublic;

emit sendRiparazione(code,pCost,pPublic);

}

void ClientServices::connected()
{
status = true;
emit statusChanged(status);

}

void ClientServices::connectionTimeout()
{
//qDebug() << tcpSocket->state();
if(tcpSocket->state() == QAbstractSocket::ConnectingState)
{
tcpSocket->abort();
emit tcpSocket->error(QAbstractSocket::SocketTimeoutError);
}
}


my Idea Controller Backend.cpp Model clientservice.cpp(and Other) View clsses Qml

anda_skoa
16th March 2019, 09:54
Interesting but neither of the two code sections contains the declaration of the sendCode() signal.

The argument name in that declaration is the name available on the QML side.
It is irrelevant how the variable is called to you pass at emit time.

Cheers,
_

Nio74
16th March 2019, 10:22
Backend.h



#ifndef BACKEND_H
#define BACKEND_H

#include <QObject>
#include "clientservices.h"

class Backend : public QObject
{
Q_OBJECT
Q_PROPERTY(bool currentStatus READ getStatus NOTIFY statusChanged)
public:
explicit Backend(QObject *parent = nullptr);
bool getStatus();

signals:
void statusChanged(QString newStatus);
void someError(QString err);
void someMessage(QString msg);
void sendCode(int c_Code);
void sendPCosto(double p_pCosto);
void sendPPubblico(double p_pPubblico);

public slots:

void setStatus(bool newStatus);

void recivedRiparazione(int code,double p_pCosto,double p_Pubblico);
void receivedSomething(QString msg);
void gotError(QAbstractSocket::SocketError err);
void sendClicked(QString msg);
void connectClicked();
void disconnectClicked();
private:
ClientServices *client;
int codiceBusta;
double prezzoCosto,prezzoPubblico;

};

#endif // BACKEND_H


Added after 19 minutes:

you say i should declare the variable code? I'm following this wiki (https://wiki.qt.io/Receiving_signals_with_arguments_in_QML_from_C%2B% 2B)

anda_skoa
16th March 2019, 10:29
void sendCode(int c_Code);





onSendCode: console.log("code=" + c_Code);


Cheers,
_

Nio74
16th March 2019, 11:19
what a fool I am now works thanks