Is this Qt DBus signal connection code correct? - c++

This is my first time using DBus so I'm not entirely sure if I'm going about this the right way. I'm attempting to connect the the Ubuntu One DBus service and obtain login credentials for my app, however the slots I've connected to the DBus return signals detailed here never seem to be firing, despite a positive result being returned during the connection.
Before I start looking for errors in the details relating to this specific service, could someone please tell me if this code would even work in the first place, or if I'm done something wrong here?
int main()
{
UbuntuOneDBus *u1Dbus = new UbuntuOneDBus;
u1Dbus->init();
}
class UbuntuOneDBus : public QObject
{
Q_OBJECT
QString busName;
QString path;
QString interface;
QString method;
QString signature;
void connectReturnSignals();
private slots:
void credentialsFound();
void credentialsNotFound();
void credentialsError();
public:
UbuntuOneDBus();
void init();
};
UbuntuOneDBus::UbuntuOneDBus()
{
busName = "com.ubuntuone.Credentials";
path = "/credentials";
interface = "com.ubuntuone.CredentialsManagement";
method = "register";
signature = "a{ss}";
connectReturnSignals();
}
void UbuntuOneDBus::init()
{
QDBusMessage message = QDBusMessage::createMethodCall( busName, path, interface, method );
QDBusConnection::sessionBus().send( message );
}
void UbuntuOneDBus::connectReturnSignals()
{
QDBusConnection::sessionBus().connect( busName, path, interface, "CredentialsFound", this, SLOT( credentialsFound() ) );
QDBusConnection::sessionBus().connect( busName, path, interface, "CredentialsNotFound", this, SLOT( credentialsNotFound() ) );
QDBusConnection::sessionBus().connect( busName, path, interface, "CredentialsError", this, SLOT( credentialsError() ) );
}
void UbuntuOneDBus::credentialsFound()
{
qDebug() << "Credentials found";
}
void UbuntuOneDBus::credentialsNotFound()
{
std::cout << "Credentials not found" << std::endl;
}
void UbuntuOneDBus::credentialsError()
{
std::cout << "Credentials error" << std::endl;
}

I think that you forgot to run
QDBusConnection QDBusConnection::connectToBus ( BusType type,
const QString & name )
and then check
bool QDBusConnection::isConnected () const
before invoking
void UbuntuOneDBus::connectReturnSignals()
or run program with some flags, but this should be easier.
I don't want what is your goal but maybe you should also try
bool QDBusConnection::registerObject ( const QString & path, QObject * object,
RegisterOptions options = ExportAdaptors )
Here some documentation:
connectToBus
isConnected
registerObject

Related

How to make QNetworkReply to return custom data?

I am going to use QNetworkAccessManager to make requests to HTTP server by my mobile app to the server. The question is, how do you link custom data to each request ? I tried to subclass QNetworkReply but I found out that I have to implement virtual methods close() and isSequential() but I don't know what those should return so I am afraid I am going to break network request functionality.
For example, when my app does the log in procedure, it has to store the email address of the account:
class MyApp : public QObject
{
Q_OBJECT
private:
QNetworkRequest request;
QNetworkReply *reply;
QNetworkAccessManager *manager;
...
}
void MyApp::do_log_in(QString email, QString password) {
QString s;
someobject.email=email; // <-- I have to store email address before sending request to server, but where do I store it?
s.append("http://myapp.com/do-auth.php?email=");
s.append(QUrl::toPercentEncoding(email));
s.append("&password=");
s.append(QUrl::toPercentEncoding(password));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(login_finished(QNetworkReply*)));
request.setUrl(QUrl(s));
manager->get(request);
}
void MyApp::login_finished(QNetworkReply *rep) {
DepservReply *reply;
QString email;
....
email= ...... // <-- I need to get the email address from QNetworkReply object somehow
///my code here handling server reply
....
}
So, how do I implement storage and retrieval of email in my case, what classes should I subclass and what methods should I re-implement ?
You can leverage the dynamic property system available in each QObject and hold the data in the reply:
// https://github.com/KubaO/stackoverflown/tree/master/questions/network-reply-tracking-40707025
#include <QtNetwork>
class MyCtl : public QObject
{
Q_OBJECT
QNetworkAccessManager manager{this};
// ...
void reply_finished(QNetworkReply *reply);
public:
MyCtl(QObject *parent = nullptr);
void do_log_in(const QString &email, const QString &password);
};
static const char kAuthGetSalt[] = "req_auth-get-salt";
static const char kDoAuth[] = "req_do-auth";
static const char kEmail[] = "req_email";
static const char kPassword[] = "req_password";
static const auto authGetSaltUrl = QStringLiteral("https://myapp.com/auth-get-salt.php?email=%1");
static const auto doAuthUrl = QStringLiteral("https://myapp.com/do-auth.php?email=%1&passwordHash=%2");
MyCtl::MyCtl(QObject *parent) : QObject{parent}
{
connect(&manager, &QNetworkAccessManager::finished, this, &MyCtl::reply_finished);
}
void MyCtl::do_log_in(const QString &email, const QString &password) {
auto url = authGetSaltUrl.arg(email);
auto reply = manager.get(QNetworkRequest{url});
reply->setProperty(kAuthGetSalt, true);
reply->setProperty(kEmail, email);
reply->setProperty(kPassword, password);
}
void MyCtl::reply_finished(QNetworkReply *reply) {
if (!reply->property(kAuthGetSalt).isNull()) {
reply->deleteLater(); // let's not leak the reply
if (reply->error() == QNetworkReply::NoError) {
auto salt = reply->readAll();
auto email = reply->property(kEmail).toString();
auto password = reply->property(kPassword).toString();
Q_ASSERT(!password.isEmpty() && !email.isEmpty());
QCryptographicHash hasher{QCryptographicHash::Sha1};
hasher.addData(salt); // the server must hash the same way
hasher.addData("----");
hasher.addData(password.toUtf8());
auto hash = hasher.result().toBase64(QByteArray::Base64UrlEncoding);
auto url = doAuthUrl.arg(email).arg(QString::fromLatin1(hash));
auto reply = manager.get(QNetworkRequest{url});
reply->setProperty(kDoAuth, true);
reply->setProperty(kEmail, email);
}
}
else if (!reply->property(kDoAuth).isNull()) {
if (reply->error() == QNetworkReply::NoError) {
auto email = reply->property(kEmail).toString();
// ...
}
}
}
Use a constant for a property name to avoid typos by letting the compiler check that you're using a valid identifier.
The example above rectifies the following critical safety issues in your code:
Sending security credentials over a clear connection: use https://, not http://.
Sending a password in cleartext: instead, send a salted hash of it. Your server should generate a random salt for each account when the accounts are created. Existing accounts can be left unsalted, but they should acquire a salt as soon as the user changes the password.
Also note that a QString to QUrl conversion will automatically percent-encode the string, so doing it explicitly is unnecessary.
In this case email is part of the request's URL so you could just extract it from there (the QNetworkReply has access to the QNetworkRequest it is handling, see QNetworkReply::request()).
You an also store more or less any kind of data as a dynamic property because QNetworkReply is a QObject derived class, see QObject::setProperty().
You can subclass QNAM to get more control of it.
network.h
class QNAMNetwork : public QNetworkAccessManager
{
Q_OBJECT
public:
explicit QNAMNetwork(QObject *parent = 0);
~QNAMNetwork();
inline void insertUserValue(const QString & key, const QString & value){this->m_user_values.insert(key,value);}
inline QString getUserValue(const QString & key){return this->m_user_values.value(key);}
signals:
void requestFinished(ExNetwork *, QNetworkReply *);
private slots:
void _sslErrors(QNetworkReply *, const QList<QSslError> &);
void _finished(QNetworkReply *);
private:
QMap<QString, QString> m_user_values;
};
network.cpp
QNAMNetwork::QNAMNetwork(QObject *parent):QNetworkAccessManager(parent)
{
connect(this, &QNAMNetwork::sslErrors, this, &QNAMNetwork::_sslErrors);
connect(this, &QNAMNetwork::finished, this, &QNAMNetwork::_finished);
}
QNAMNetwork::~QNAMNetwork()
{
//qDebug() << __FUNCTION__ << QString::number((long)this,16);
}
void QNAMNetwork::_sslErrors(QNetworkReply * reply, const QList<QSslError> & errors)
{
reply->ignoreSslErrors(errors);
}
void QNAMNetwork::_finished(QNetworkReply * reply)
{
emit requestFinished(this, reply);
}
usecase:
QNAMNetwork * network = new QNAMNetwork(this);
network->insertUserValue("email","yourmail#mail.com");
connect(network, SIGNAL(requestFinished(QNAMNetwork*,QNetworkReply*)), this, SLOT(requestFinished(QNAMNetwork*,QNetworkReply*)));
QNetworkRequest req(QUrl::fromUserInput(query)); //get url
network->get(req);
...
void YourClass::requestFinished(QNAMNetwork * net, QNetworkReply * rep)
{
QString email = net->getUserValue("email");
net->deleteLater();
rep->deleteLater();
}

QT SQL notification with payload

I'm currently working on applciation that will add to table view new row, that was inserted into db's table. I started with basic class to handle notifies and setted up triggers:
CREATE OR REPLACE FUNCTION notify_tableIWantToObserve_update()
RETURNS trigger AS $$
DECLARE
BEGIN
PERFORM pg_notify(
CAST('tableIWantToObserve_update' AS text),
(NEW.tableIWantToObserve_id)::text);
return new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tRIGGER_notify_tableIWantToObserve_update
AFTER UPDATE
ON tableIWantToObserve
FOR EACH ROW
EXECUTE PROCEDURE notify_tableIWantToObserve_update();
So it will jsut send notfy with id of updated row in payload. That is what i want - becous reloading whole table just won't do the trick later.
I checked documentaton of QSqlDriver
http://doc.qt.io/qt-5/qsqldriver.html#notification-1
With it, I created my "handler":
// That's its constructor
MyDB = new QSqlDatabase(QSqlDatabase::addDatabase("QPSQL", "Main"));
//Removed my data from here (just fro sake of this post)
MyDB->setHostName("-");
MyDB->setPort(0);
MyDB->setDatabaseName("-");
MyDB->setUserName("-");
MyDB->setPassword("-");
MyDB->open();
if( MyDB->isOpen() )
{
qDebug()<<"Connected to DB!";
QObject::connect(
MyDB->driver(),
SIGNAL(notification(const QString&, QSqlDriver::NotificationSource, const QVariant)),
this,
SLOT(slot_DBNotification_Recieved_NotifiAndPayload((const QString&, const QVariant)));
);
}
else
qDebug()<<"NOT connected to DB!";
But it jsut wont work. Only with driver's signal useing single QString it will connect it - version i needed (with additional info) wont connect.
I updated my QT to 5.7, but still even in QTCreater, it just shows me that driver's signal is only with single string.
Is there any fix for that? I realy need to use that signal to retrieve that updated row id.
EDIT 1:
that slot of my handler:
void NotifiHandlerr::slot_DBNotification_Recieved_NotifiAndPayload(const QString& MSG, const QVariant &payload)
{
qDebug() << "I WAS NOTIFIED ABOUT : " + MSG+" WITH DATA : "+payload.toString();
}
EDIT 2:
I tried to add QSqlDriver::NotificationSource as argument in my slot, but i couldn't - it still repeated error in .h that NotificationSource wasn't declared.
EDIT 3:
I'm adding here most of the code (handler class)
// WHOLE .h
#include <QDebug>
#include <QObject>
#include <QString>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QVariant>
#include <QSqlDriverPlugin>
#include <qsqldriver.h>
class Handler : public QObject
{
Q_OBJECT
public slots:
void slot_DBNotification_Recieved_NotifiAndPayload
(const QString& name, QSqlDriver::NotificationSource source, const QVariant& payload);
public:
explicit Handler();
~Handler();
private:
QSqlDatabase MyDB;
};
//WHOLE .cpp
#include "Handler.h"
Handler::Handler()
{
MyDB = new QSqlDatabase(QSqlDatabase::addDatabase("QPSQL", "Main"));
MyDB->setHostName("-");
MyDB->setPort(0);
MyDB->setDatabaseName("-");
MyDB->setUserName("-");
MyDB->setPassword("-");
MyDB->open();
if( MyDB->isOpen() )
{
qDebug()<<"Connected to DB!";
MyDB->driver()->subscribeToNotification("tableIWantToObserve_update");
QObject::connect(
MyDB->driver(),
SIGNAL(notification(const QString&, QSqlDriver::NotificationSource, const QVariant)),
this,
SLOT(slot_DBNotification_Recieved_NotifiAndPayload((const QString&, const QVariant)));
);
}
else
qDebug()<<"NOT connected to DB!";
}
Handler::~Handler()
{
MyDB->driver()->unsubscribeFromNotification("tableIWantToObserve_update");
MyDB->cloe();
}
void NotificationMaster::slot_DBNotification_Recieved_NotifiAndPayload
(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload)
{
qDebug() << "I WAS NOTIFIED ABOUT : " + name+" WITH DATA : "+payload.toString();
}
And just to eliminate this idea - I added
QT += sql
in my .pro file
Your slot has a wrong signature, Here is how you should define it.
In your header file:
//in order to be able to use the enum QSqlDriver::NotificationSource
#include <QSqlDriver>
...
...
class Handler : public QObject{
Q_OBJECT
public:
explicit Handler(QObject *parent = 0);
~Handler();
...
...
...
public slots:
void SqlNotification(const QString& name, QSqlDriver::NotificationSource source,
const QVariant& payload);
...
...
};
and in the constructor, when you are connecting the slot, you should subscribe to the notification first:
QSqlDatabase::database().driver()->subscribeToNotification("notification_name");
connect(QSqlDatabase::database().driver(),
SIGNAL(notification(QString,QSqlDriver::NotificationSource,QVariant)), this,
SLOT(SqlNotification(QString,QSqlDriver::NotificationSource,QVariant)));
You may need to unsubscribe in the destructor(since you don't want to receive the notification any more):
QSqlDatabase::database().driver()->unsubscribeFromNotification("notification_name");
and your slot implementation:
void Handler::SqlNotification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload){
switch(source){
case QSqlDriver::UnknownSource:
qDebug() << "unkown source, name: " << name << "payload:" << payload.toString();
break;
case QSqlDriver::SelfSource:
qDebug() << "self source, name: " << name << "payload:" << payload.toString();
break;
case QSqlDriver::OtherSource:
qDebug() << "other source, name: " << name << "payload:" << payload.toString();
break;
}
}
Code posted by me and in anserw were more-or-less correct, but what need to be done is to recreate whoel project in newer version of qt creator so it will resolve issiues with missing functions and namespaces itself. Just create new project and paste all files there.

QXMPP extensions not calling

I'm making one xmpp client and I have a lot doubts in extensions ..
I did need get a list of old messages with one user, so .. I'm using the QXmppArchiveManager class for that. So I make one class like that:
...
class QXmppArchiveManager;
class MessageController : public QXmppClient
{
...
private:
QNetworkAccessManager *nam_;
QXmppClient *xmppClient_;
QXmppArchiveManager *archiveMng_;
QDateTime m_startDate;
QDateTime m_endDate;
protected slots:
virtual void onConnected();
virtual void onMessageReceived(const QXmppMessage &);
virtual void archiveListReceived(const QList<QXmppArchiveChat> &chats, const QXmppResultSetReply &rsmReply);
}
And implements
...
void MessageController::onConnected() //before client connects listener...
{
QXmppResultSetQuery rsmQuery;
rsmQuery.setMax(0);
m_startDate = QDateTime::currentDateTime().addDays(-201);
m_endDate = QDateTime::currentDateTime();
archiveMng_->listCollections("", m_startDate, m_endDate, rsmQuery);
}
void MessageController::connect()
{
xmppClient_ = new QXmppClient();
QObject::connect( xmppClient_, SIGNAL( connected() ), this, SLOT( onConnected() ) );
QObject::connect( xmppClient_, SIGNAL( messageReceived( QXmppMessage ) ), this, SLOT( onMessageReceived( QXmppMessage ) ) );
archiveMng_ = new QXmppArchiveManager;
xmppClient_->addExtension(archiveMng_);
QObject::connect(archiveMng_, SIGNAL(archiveChatReceived(QXmppArchiveChat, QXmppResultSetReply)),
SLOT(archiveChatReceived(QXmppArchiveChat, QXmppResultSetReply)));
QObject::connect(archiveMng_, SIGNAL(archiveListReceived(QList<QXmppArchiveChat>, QXmppResultSetReply)),
SLOT(archiveListReceived(QList<QXmppArchiveChat>, QXmppResultSetReply)));
xmppClient_->logger()->setLoggingType( QXmppLogger::StdoutLogging );
QXmppConfiguration config;
config.setDomain("(censored)");
config.setHost("(censored)");
config.setPort(5222);
config.setUser((censored));
config.setPassword((censored));
config.setResource("Android-Client");
xmppClient_->connectToServer( config );
}
void MessageController::archiveChatReceived(const QXmppArchiveChat &chat, const QXmppResultSetReply &rsmReply)
{
qDebug() << "archiveChatReceived";
}
void MessageController::archiveListReceived(const QList<QXmppArchiveChat> &chats, const QXmppResultSetReply &rsmReply)
{
qDebug() << "archiveListReceived";
}
The problem is ... this code not called this listeners, in this case not call "archiveListReceived".
How I can fix that ?
Thanks
I found the problem, in this case my openfire xmpp server not working for archive, so ... I'm install the open-archive plugin for it!

How to pass a parameter using QSignalMapper, incompatible sender/receiver arguments

Implementation:
void Test::addProcessToList(const QString &command, const QString &id, const BasicInfo &basicInfo) {
QProcess *console = new QProcess();
QSignalMapper* signalMapper = new QSignalMapper (this) ;
connect (console, SIGNAL(readyRead()), signalMapper, SLOT(map())) ;
connect (console, SIGNAL(finished(int)), signalMapper, SLOT(processFinished(int))) ;
signalMapper->setMapping (console, id) ;
connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(pidOut(QString))) ;
console->start(command);
}
void Test::registerProcess(QString id) {
QProcess *console = qobject_cast<QProcess*>(QObject::sender());
QByteArray processOutput = console->readAll();
int mainPID = parsePID(processOutput);
BasicInfo basicInfo;
qDebug() << "Registering id: " + id + " mainPID: " + mainPID;
if(mainPID != 0) {
Main::getInstance()->addProcessToList(mainPID, packageId, basicInfo);
} else {
qWarning() << "pidOut Error fetching mainPID";
}
}
void Test::processFinished(int exitCode) {
QProcess *console = qobject_cast<QProcess*>(QObject::sender());
QByteArray processOutput = console->readAll() + QString("Finished with code %1").arg(exitCode).toLatin1();
qDebug() << " processFinished: " + processOutput;
}
prototypes:
private
void addProcessToList(const QString &command, const QString &id, const BasicInfo &basicInfo);
private slots:
void registerProcess(QString);
void processFinished(int);
I get this errors when I call connect, which tells me I'm doing it wrong:
"QObject::connect: Incompatible sender/receiver arguments
QSignalMapper::mapped(int) --> Test::registerProcess(QString)"
I'm not understanding where I'm suppose to specify my parameter (QString id) so that registerProcess will receive it when it's called? I'm assuming I'm doing this part wrong, cut from above:
signalMapper->setMapping (console, id) ;
connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(pidOut(QString))) ;
QSignalMapper can emit either mapped(const QString & text) or mapped(int i) signals. The type is defined by setMapping(QObject * sender, int id) or setMapping(QObject * sender, const QString & text).
That led to confusion probably by autocompletion in
connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(pidOut(QString)));
The types of signal and slot must be the same for connection.
You set string mapping (QString &id), so the signal in the connection should be QString:
connect (signalMapper, SIGNAL(mapped(QString)), this, SLOT(pidOut(QString)));
Update
After deeper review of the code flow I suspect that you wanted to connect mapper to registerProcess() slot instead of pidOut(). In that slot you can have as an argument QString id that was passed to signalMapper in setMapping() call. That is the purpose of using QSignalMapper.
However, beside that id it is not possible to extract console pointer, since in that case sender() is signalMapper object. If it is the case, QSignalMapper cannot help you here. You should use direct connection of console and this on readReady (of course with slot of this with void argument as readReady()). To get the string id in that slot it is possible to use simple QMap<QProces*, QString> map stored as a Test class member.
// addProcessToList(...):
map[console] = id;
//registerProcess():
QString id = map[console];
//processFinished(...):
map.remove(console);
By the way, it is not needed to created a new instance of QSignalMapper for each map item.

Memory leak with post requests and QNetworkAccessManager

I'm making a program that uses lots of timer and, at intervals of 4 seconds, does an online post to a php script.
I'm coding in QtCreator 5.1. I use classes just like the ones below.
The one below just populates a task list, but throughout the course of 8 to 12 hours, the memory that the program takes up just keep rising and rising gradually.
What am I doing wrong while using this class?
I have to be able to keep posting online like I already am, about every 4 to 8 seconds.
Here's a simple class for taking care of one of my processes:
Header file: tasklistprocess.h
#ifndef TASKLISTPROCESS_H
#define TASKLISTPROCESS_H
#include <QThread>
#include <QtCore>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QListWidget>
#include <QTabWidget>
#include "globalhelper.h"
#include "securityinfo.h"
class TaskListProcess : public QThread
{
Q_OBJECT
public:
explicit TaskListProcess(QListWidget *obj_main, QTabWidget *tabs_main, QString user, QObject *parent = 0);
signals:
void upTaskStorage(int key,QHash<QString,QString> item);
private:
GlobalHelper gh;
Securityinfo sci;
QNetworkAccessManager *nam;
QNetworkRequest request;
QByteArray data;
// this is the disposable params for reusage through out the class
QUrlQuery params;
QString post_data;
QString user_name;
QTimer *tasklist_tmr;
bool get_task_list;
QListWidget *obj;
QTabWidget *tabs;
private slots:
void setTaskList();
void replyFinished(QNetworkReply *reply);
void sendPost(QString file_name, QUrlQuery params);
};
#endif // TASKLISTPROCESS_H`
Source file: tasklistprocess.cpp
#include "tasklistprocess.h"
TaskListProcess::TaskListProcess(QListWidget *obj_main, QTabWidget *tabs_main, QString user, QObject *parent) :
QThread(parent)
{
user_name = user;
get_task_list = false;
obj = obj_main;
tabs = tabs_main;
tasklist_tmr = new QTimer(this);
connect(this,SIGNAL(started()),this,SLOT(setTaskList()));
connect(tasklist_tmr,SIGNAL(timeout()),this,SLOT(setTaskList()));
nam = new QNetworkAccessManager(this);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
request.setRawHeader( "User-Agent" , "Mozilla Firefox" );
// here we connect up the data stream and data reply signals
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}
void TaskListProcess::setTaskList()
{
qDebug() << "Your task list was set";
bool in = false;
if(!(tasklist_tmr->isActive()))
{
tasklist_tmr->start(10000);
in = true;
}
if(!(get_task_list))
{
params.clear();
params.addQueryItem("user_name", user_name);
params.addQueryItem("logged_in", "1");
sendPost("getTaskList.php",params);
get_task_list = true;
}
else
{
if(post_data.contains("|*|"))
{
//here i retrieve a piece of information from a php script which is stored in a custom string format
// here we clear the list for the new data to be put in
if(obj->count()>0)
{
obj->clear();
}
int key = 0;
foreach(QString inner_task,post_data.split("|*|"))
{
QHash<QString,QString> task_cont;
//qDebug() << " ";
if(inner_task.contains("*,*"))
{
foreach(QString task_val,inner_task.split("*,*"))
{
if(task_val.contains("*=*"))
{
QStringList key_pairs = task_val.split("*=*");
task_cont.insert(key_pairs[0],key_pairs[1]);
if(key_pairs[0] == "tt")
{
QString val_in;
if(key_pairs[1].length()>10)
{
// this sets the title to the shortened version
// if the string length is too long
val_in = key_pairs[1].left(10) + "....";
}
else
{
val_in = key_pairs[1];
}
obj->addItem("Task :" + QString::fromUtf8(key_pairs[1].toStdString().c_str()));
}
}
}
}
//task_storage.insert(key,task_cont);
emit upTaskStorage(key,task_cont);
key ++;
}
}
get_task_list = false;
}
// here we're checking to see if they are looking at the task tab so it doesn't keep changing
// back and forth between the tabs
bool change = true;
if(tabs->currentIndex() != 0)
{
change = false;
}
if(change)
{
tabs->setCurrentIndex(0);
}else if(in)
{
tabs->setCurrentIndex(0);
}
}
void TaskListProcess::replyFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Error in" << reply->url() << ":" << reply->errorString();
return;
}
QString data = reply->readAll().trimmed();
post_data = data;
if(get_task_list)
{
setTaskList();
}
}
void TaskListProcess::sendPost(QString file_name, QUrlQuery params)
{
post_data = "";
QUrl url(sci.getHost() + file_name);
url.setQuery(params);
data.clear();
data.append(params.toString().toUtf8());
request.setUrl(url);
nam->post(request, data);
}
From the Qt docs http://qt-project.org/doc/qt-5.1/qtnetwork/qnetworkaccessmanager.html
Note: After the request has finished, it is the responsibility of the
user to delete the QNetworkReply object at an appropriate time. Do not
directly delete it inside the slot connected to finished(). You can
use the deleteLater() function.
I would suggest calling reply->deleteLater() in your replyFinished() method.
You should call deleteLater() for an QNetworkReply object after use.
Note: After the request has finished, it is the responsibility of the user to delete the QNetworkReply object at an appropriate time. Do not directly delete it inside the slot connected to finished(). You can use the deleteLater() function.
More information here: http://harmattan-dev.nokia.com/docs/library/html/qt4/qnetworkaccessmanager.html
Thank you everyone for the hel.
It was very simply the "deleteLater()" on the reply in the
void replyFinished(QNetworkReply *reply)
{
}
and it should have looked like this
void replyFinished(QNetworkReply *reply)
{
// after all of your processing
reply->deleteLater();
}
it was such a small problem but one that drove me crazy for a long time so i hope this helps