Qt4 QNetworkManager Hangs - c++

I'm trying to write an application using QNetworkManager. I have simplified the code down to the problem. The following code hangs, and I have no idea why:
main.cpp:
#include <QApplication>
#include "post.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
post("http://google.com/search", "q=test");
return app.exec();
}
post.h:
#ifndef _H_POST
#define _H_POST
#include <QNetworkAccessManager>
#include <QNetworkRequest>
class post : public QObject {
Q_OBJECT
public:
post(QString URL, QString data);
public slots:
void postFinished(QNetworkReply* reply);
protected:
QNetworkAccessManager *connection;
};
#endif
post.cpp:
#include <QApplication>
#include <QUrl>
#include "post.h"
post::post(QString URL, QString data) {
connection = new QNetworkAccessManager(this);
connect(connection, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished(QNetworkReply*)));
connection->post(QNetworkRequest(QUrl(URL)), data.toAscii());
}
void post::postFinished(QNetworkReply*) {
qApp->exit(0);
}
Some Googling shows it may be because I have everything on one thread, but I have no idea how to change that in Qt... none of the network examples show this.

I just tried it with the same results. The problem is that you are creating the post object by only calling the constructor. Since you are not specifying an object it is getting destroyed right away (to check this create a destructor and see when it gets called.)
try:
post p("http://google.com/search","q=test");
Then your slot gets called.

Related

QTimer doesn't trigger

I'm trying to get the QTimer running, but it never triggers.
I found some other questions about the timer, but the problem was always the timer being out of scope. This is not the case in my small example:
I create the timer in a custom QMainWindow, this is the .h file:
#include <iostream>
#include <QtWidgets/QMainWindow>
#include <QTimer>
class MyMainWindow : public QMainWindow {
Q_OBJECT;
private:
QTimer *mainTimer;
public slots:
void timerUpdate();
public:
MyMainWindow();
};
This is the .cpp file:
#include "MyMainWindow.h"
MyMainWindow::MyMainWindow() {
QMainWindow();
mainTimer = new QTimer(this);
connect(mainTimer, SIGNAL(timeout()), this, SLOT(update()));
mainTimer->start(1000);
std::cout << "Timer created.\n";
}
void MyMainWindow::timerUpdate() {
std::cout << "test";
}
Finally, this is my main.cpp:
#include <QtWidgets/QApplication>
#include "MyMainWindow.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
MyMainWindow mmw;
mmw.show();
return app.exec();
}
When I execute this code, I only get "Timer created." and never "test".
Any suggestions?
You're connecting to SLOT(update()), but your function is called timerUpdate.
Using more modern Qt 5 signal-slot connection syntax, that would never have happened and you'd get an error at compile-time. You should prefer using that.

When trying to get a webpage using Qt QNetworkAccessManager, It always returns ""

I'm trying to get a web page using Qt and print it on the screen.The problem is it always prints "". It won't make it to the done SLOT. I don't know if there's something wrong with the connect(). The code gets compiled with no errors.
Trying not to use event loops yet.
Here's the code:
net.h
#ifndef NET_H
#define NET_H
#include <QObject>
#include <QtNetwork>
#include <QString>
#include <QDebug>
class net : public QObject
{
Q_OBJECT
public:
explicit net(QObject *parent = 0);
void get_site(QString url);
QString data;
signals:
public slots:
void err(QNetworkReply *);
void done(QNetworkReply *);
private:
};
#endif // NET_H
net.cpp:
#include "net.h"
net::net(QObject *parent) :
QObject(parent)
{
}
void net::get_site(QString url) {
QNetworkAccessManager man;
QNetworkRequest request;
request.setUrl (QUrl(url));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(err(QNetworkReply *)));
man.get (QNetworkRequest(QUrl(url)));
}
void net::done(QNetworkReply * reply) {
data = QString(reply->readAll ());
}
void net::err(QNetworkReply * reply) {
data = QString(reply->errorString ());
}
And main.cpp:
#include <QCoreApplication>
#include "net.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
net netobj;
netobj.get_site("http://stackoverflow.com");
qDebug() << netobj.data;
return a.exec();
}
There are some major problems in your code. First you should have the QNetworkAccessManager as a class member in .h file :
class net : public QObject
{
...
private:
QNetworkAccessManager nam;
};
Also you should not connect the finished signal to two different slots. Your get_site function should be like :
void net::get_site(QString url) {
QNetworkRequest request;
request.setUrl (QUrl(url));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
man.get (QNetworkRequest(QUrl(url)));
}
And you should manage the returned reply in the following way :
void net::done(QNetworkReply * reply) {
if (reply->error() == QNetworkReply::NoError)
{
data = QString(reply->readAll ());
}
else
{
data = QString(reply->errorString ());
}
}
Your QNetworkAccessManager instance goes out of scope at the end of your get_site function. According to Qt docs, one QNetworkAccessManager should be enough for the whole Qt application. Your object should persist outside the scope of that function, since it's likely the response will take longer to receive than it will take for that function to end. Make the QNetworkAccessManager a member of your net class, instead of an automatic variable local to get_site.
Note that you also need to manage the lifetime of the QNetworkReply object, not by using delete, but by using deleteLater() or else you might leak memory.

Qt Console app using QNetworkAccessManager

I'm trying to write a Qt app that calls a web service. This is a console app, and url will be passed in as a command line argument. I searched for example http programs in Qt and found this link:
http://qt-project.org/doc/qt-5/qnetworkaccessmanager.html
Here it has the following code example:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
Now, if I take this and paste it into my console app, in main, I obviously get build errors because this does not exist. I get :
invalid use of 'this' in non-member function
Is there an equivalent QNetworkAccessManager for non-GUI/console type apps?
"this" is the this pointer of an object, so in main.cpp it causes errors, you should write some class where you will work with network and after that use this class in main function
It should be something like this. When you run app, you'll get html code of Qt site
It is just example, in future we can add here constructot, destructor, maybe signals(signals help us communicate with for example other classes if we need this)
*.h
#ifndef NET_H
#define NET_H
#include <QObject>
#include <QtCore>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class Net : public QObject
{
Q_OBJECT
QNetworkAccessManager *manager;
private slots:
void replyFinished(QNetworkReply *);
public:
void CheckSite(QString url);
};
#endif // NET_H
*.cpp
#include "net.h"
void Net::replyFinished(QNetworkReply *reply)
{
qDebug() << reply->readAll();
}
void Net::CheckSite(QString url)
{
QUrl qrl(url);
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(qrl));
}
main
#include "net.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Net handler;
handler.CheckSite("http://qt-project.org");
return a.exec();
}

Open external links from flash player hosted on QWebKit

i have flash player running on QWebkit , and on the flash player there are some web links
that needs to be open in external browser , what i did is :
m_webView->page()->setLinkDelegationPolicy(QWebPage::LinkDelegationPolicy::DelegateAllLinks);
connect(m_webView->page(),SIGNAL(linkClicked(const QUrl&)),
this,
SLOT(linkClickedHandler(const QUrl&)),Qt::DirectConnection);
void WebBroswerDeleget::linkClickedHandler(const QUrl& url)
{
QDesktopServices::openUrl(QUrl(url.toString(), QUrl::TolerantMode));
}
but its never triggered even of i change in the connect from m_webView->page() to m_webView
i overrided the QWebview::createWindow like this:
QWebView* MyAdWebview::createWindow (QWebPage::WebWindowType type)
{
QWebView* p = new QWebView(0);
connect(p->page()->networkAccessManager(), SIGNAL(finished(QNetworkReply*)), this, SLOT(newWindowLoadFinished(QNetworkReply*)), Qt::UniqueConnection);
return p;
}
void MyAdWebview::newWindowLoadFinished(QNetworkReply* reply) {
QDesktopServices::openUrl(reply->url().toString());
}
QDesktopServices::openUrl is a cutom function which opens the default system browser with this url
This is working for me on both 4.7.2 QtEmbedded and 4.8.1 on mac. What I don't understand is this:
m_webView->page()->setLinkDelegationPolicy(QWebPage::LinkDelegationPolicy::DelegateAllLinks);
Just do:
m_webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
Something like this works for me:
#include <QWebPage>
#include <QWebView>
#include <QApplication>
#include "sigrec.h"
int main(int argc, char** argv)
{
QApplication a(argc, argv);
SigRec rec;
QWebView view;
view.page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
QObject::connect(view.page(), SIGNAL(linkClicked(const QUrl&)), &rec, SLOT(onLinkClicked(const QUrl&)),
Qt::DirectConnection);
view.show();
view.setUrl(QUrl("http://www.google.com"));
return a.exec();
}
Where SigRec is something like this:
#ifndef SIGREC_H
#define SIGREC_H
#include <QObject>
#include <QUrl>
class SigRec : public QObject
{
Q_OBJECT
public:
explicit SigRec(QObject *parent = 0);
public slots:
void onLinkClicked(const QUrl &url);
};
#endif // SIGREC_H

C++/Qt Q_OBJECT macro causes an error

I've just started programming in Qt framework. Following is a very simple program:
#include <QtCore/QCoreApplication>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass() {}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass *c = new MyClass();
return a.exec();
}
But I receive following error when I try to compile & run it:
In function MyClass:
undefined reference to vtable for MyClass
But when I remove the QObject macro everything works fine. Please note that the class is defined in the same file as the main function.
I'm using Qt version 4.7, running on Win 7.
What is causing this issue?
Update: I get the same error when I define my class in a separate header file. mytimer.h:
#ifndef MYTIMER_H
#define MYTIMER_H
#include <QtCore>
class MyTimer : public QObject
{
Q_OBJECT
public:
QTimer *timer;
MyTimer();
public slots:
void DisplayMessage();
};
#endif // MYTIMER_H
mytimer.cpp:
#include "mytimer.h"
#include <QtCore>
MyTimer::MyTimer()
{
timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(DisplayMessage()));
timer->start(1000);
}
void MyTimer::DisplayMessage()
{
qDebug() << "timed out";
}
And this is the main.cpp:
#include <QtCore/QCoreApplication>
#include <QDebug>
#include "mytimer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyTimer *mt = new MyTimer();
return a.exec();
}
You need to compile it using qmake, which is going to create mock methods for your custom QObject class. See here about more on generating moc files.
Since your example doesn't contain header files, it is not parsed, and no moc files are generated. You need to declare MyClass in a separate header file, and run moc generation tool.
When you are using QT Creator you should cleanup up your project and execute qmake, in the build menu.
Whenever u apply some changes first clean your project, then run qmake, and the finally build your project...