Connecting to QNetworkReply::error signal - qt

I am using the new connect syntax for Qt5. QNetworkReply has a signal called error and also a function called error. This causes problems when attempting to connect to the signal:
connect(reply, &QNetworkReply::error, this, &MyClass::error);
error C2664: 'QMetaObject::Connection QObject::connect(const QObject *,const char *,const QObject *,const char *,Qt::ConnectionType)' : cannot convert parameter 2 from 'overloaded-function' to 'const char *'
Context does not allow for disambiguation of overloaded function
How do I tell the compiler (MSVC) that I want to connect to the signal rather than the function?

You need manually to cast the function pointer to address the correct function:
connect(reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), this, &MyClass::error);
This is the noted consequence of using new syntax for overloaded functions:
cons:
Very complicated syntax in cases of overloads?
P.S. You can find similar example on the above link:
QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [socket] (QAbstractSocket::SocketError) {
qDebug()<< "ERROR " << socket->errorString();
socket->deleteLater();
});

Start from Qt 5.15 QNetworkReply::error is not a signal any more. You can connect to &QNetworkReply::errorOccurred instead, fortunately, without type casting:
connect(reply, &QNetworkReply::errorOccurred, this,
[reply](QNetworkReply::NetworkError) {
qCDebug() << "Error " << reply->errorString();
});

Related

I can't quit properly my apps if I use mysql connection

If I do not use connection I can properly exit.
In Pdv.h file
namespace Pdv {
...
extern QSqlDatabase db;
...
}
In LoginDialog.cpp file
QSqlDatabase Pdv::db;
...
Pdv::db= QSqlDatabase::addDatabase("QMYSQL3");
Pdv::db.setHostName(Pdv::DB_URL);
Pdv::db.setUserName(Pdv::DB_USER);
Pdv::db.setPassword(Pdv::DB_PASS);
Pdv::db.setDatabaseName(Pdv::DB_DB);
if(!Pdv::db.open()) {
...
// Checking user login/password and retrieve many variables
...
In mainwindow.cpp file
...
void MainWindow::closeEvent(QCloseEvent *event) {
...
if(Pdv::db.isOpen()) {
qDebug() << "Opened 1";
Pdv::db.close();
qDebug() << Pdv::db.lastError();
if(Pdv::db.isOpen())
qDebug() << "Opened 2";
}
Pdv::app->quit(); // or QApplication::quit();
}
I got this error in QTCreator console
Opened 1
QSqlError("", "", "")
Le programme s'est terminé subitement.
/home/cosmic/src/build-Pdv-Desktop-Debug/Pdv crashed.
A idea?
To make proper exit with usage of QSqlDatabase, you need preferably:
remove all instances of QSqlDatabase objects (because as you copy them, they will keep connection open).
As second condition, you need to use QSqlDatabe::removeDatabase() call. (also this call will make qDebug message if database is still in use occasionally - some QSqlDatabase object is left somewhere - it will help to identify a problem).
If you close and delete your MainWindow, and your program then crashes, then other parts of the program must be trying to use the MainWindow pointer even though it is destroyed.
I think the problem is the line of code Pdv::app->quit(); Try with QApplication::quit(); instead or review the code in Pdv::app->quit();.

QtDBus Simply Example With PowerManager

I'm trying to use QtDbus to communicate with interface provided by PowerManager in my system. My goal is very simple. I will be writing code which causes my system to hibernate using DBus interface.
So, I installed d-feet application to see what interfaces DBus is available on my system, and what I saw:
As we see, I have a few interfaces and methods from which I can choose something. My choice is Hibernate(), from interface org.freedesktop.PowerManagment
In this goal I prepared some extremely simple code to only understand mechanism. I of course used Qt library:
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QtDBus>
#include <QDBusInterface>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
if (!QDBusConnection::sessionBus().isConnected()) {
fprintf(stderr, "Cannot connect to the D-Bus session bus.\n"
"To start it, run:\n"
"\teval `dbus-launch --auto-syntax`\n");
return 1;
}
QDBusInterface iface("org.freedesktop.PowerManagement" ,"/" , "" , QDBusConnection::sessionBus());
if(iface.isValid())
{
qDebug() << "Is good";
QDBusReply<QString> reply = iface.call("Methods" , "Hibernate");
if(reply.isValid())
{
qDebug() << "Hibernate by by " << qPrintable(reply.value());
}
qDebug() << "some error " << qPrintable(reply.error().message());
}
return 0;
}
Unfortunately I get error in my terminal:
Is good
some error Method "Methods" with signature "s" on interface "(null)" doesn't exist
So please tell me what's wrong with this code? I am sure that I forgot some arguments in function QDBusInterface::call() but what ?
When creating interface you have to specify correct interface, path, service. So that's why your iface object should be created like this:
QDBusInterface iface("org.freedesktop.PowerManagement", // from list on left
"/org/freedesktop/PowerManagement", // from first line of screenshot
"org.freedesktop.PowerManagement", // from above Methods
QDBusConnection::sessionBus());
Moreover, when calling a method you need to use it's name and arguments (if any):
iface.call("Hibernate");
And Hibernate() doesn't have an output argument, so you have to use QDBusReply<void> and you can't check for .value()
QDBusReply<void> reply = iface.call("Hibernate");
if(reply.isValid())
{
// reply.value() is not valid here
}

Error while connecting lambda function to QProcess::error

In following code I want to connect lambda function to QProcess::error signal:
void Updater::start() {
QProcess process;
QObject::connect(&process, &QProcess::error, [=] (QProcess::ProcessError error) {
qWarning() << "error " << error;
});
process.start("MyProgram");
process.waitForFinished();
}
But I get strange error:
error: no matching function for call to 'Updater::connect(QProcess*
[unresolved overloaded function type],
Updater::start()::)' });
What I do wrong here? The code executes inside method of class derived from QObject. The project configured to work with c++11.
I use Qt 5.3.1 on Linux x32 with gcc 4.9.2
Problem is that the QProcess has another error() method, so compiler just doesn't know which method use. If you want to deal with overloaded methods, you should use next:
QProcess process;
connect(&process, static_cast<void (QProcess::*)(QProcess::ProcessError)>
(&QProcess::error), [=](QProcess::ProcessError pError) {
qWarning() << "error " << pError;
});
process.start("MyProgram");
process.waitForFinished();
Yes, it looks ugly, but there is no another way (only old syntax?).
This special line tells compiler that you want to use void QProcess::error(QProcess::ProcessError error), so now there is no any ambiguity
More information you can find here.
For those who are using Qt 5.6 or later, the QProcess::error signal is deprecated. You can use the QProcess::errorOccurred signal instead to avoid the naming ambiguity and complicated casting.
QProcess process;
connect(&process, &QProcess::errorOccurred, [=](QProcess::ProcessError error) {
qWarning() << error;
});
process.start("MyProgram");
process.waitForFinished();

qdbus - can't connect to dbus signal with struct argument

I'm trying to connect to amarok d-bus signal StatusChange (reference: https://xmms2.org/wiki/MPRIS#StatusChange). Interface and struct is ok because I can connect to simple signal CapsChange(int) in same interface and can get status by GetStatus dbus method, so this marshall struct is ok:
struct AmarokStatus {
int st1;
int st2;
int st3;
int st4;
};
Q_DECLARE_METATYPE(AmarokStatus)
qDBusRegisterMetaType<AmarokStatus>();
But when call:
mInf = new QDBusInterface("org.mpris.MediaPlayer2.amarok", "/Player",
"org.freedesktop.MediaPlayer", QDBusConnection::sessionBus(),this);
connect(mInf, SIGNAL(StatusChange(AmarokStatus)), this, SLOT(statusChanged(AmarokStatus)));
connect(mInf, SIGNAL(CapsChange(int)), this, SLOT(capsChange(int)));
I got message:
Object::connect: No such signal
org::freedesktop::MediaPlayer::StatusChange(AmarokStatus)
I have tried with SIGNAL(StatusChange(struct)) and SIGNAL(StatusChange(QDbusargument)) and other types but same message
D-Feet is saying that definition of StatusChange is: StatusChange(Struct of (Int32, Int32, Int32, Int32)), same with dbus-monitor. And same problem with signal TrackChange(array of struct). So I'm definitely messing something with connect() method.
There are two options:
Ensure the emitter which implements QDBusAbstractInterface defines the signal you are connecting to. This solution is a bit cleaner.
or
Use QDBusConnection::connect to connect to an anonymous signal. This solution works in a pinch but in my experience can be particularly error-prone:
if (!QDBusConnection::systemBus().connect("org.mpris.MediaPlayer2.amarok", "/Player", "org.freedesktop.MediaPlayer", "StatusChange", this, SLOT(statusChanged(AmarokStatus)))) {
qWarning() << "Failed to connect";
}

downloadProgress not emitted from QNetworkReply

I'm trying to build a module which downloads a binary file in Qt, using QNetworkAccessManager. I use the same approach detailed in the documentation (see below), but while I do get readyRead signals, downloadProgress never arrives.
Everything happens on the same thread (the project is big so I cannot paste it all).
Any ideas?
QNetworkRequest request;
request.setUrl("http://XXX.s3.amazonaws.com/XXX.exe");
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
QNetworkAccessManager * m_manager = new QNetworkAccessManager( this );
m_reply = m_manager->get(request);
m_reply->setParent(this);
connect(m_reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(m_reply, SIGNAL(downloadProgress(qint64 bytesReceived, qint64 bytesTotal)),
this, SLOT(replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)));
ok found it
wow what a simple mistake.
the answer is syntactic:
connect(m_reply, SIGNAL(downloadProgress(qint64 bytesReceived, qint64 bytesTotal)),
this, SLOT(replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)));
is an error
it should be:
connect(m_reply, SIGNAL(downloadProgress(qint64 , qint64 )),
this, SLOT(replyDownloadProgress(qint64 , qint64 ));
once i changed it, i got the signal.
QT DOES NOT CHECK SYNTAX ERRORS IN ITS PREPROCESSOR (note to self)
I've patched my Qt to use a qFatal() instead of qWarning(), so the app asserts instead of printing error messages (that cannot be seen when linking against a release-build Qt). YMMV.

Resources