C++ QNetworkAccessManager (Qt) in conjunction with openGL - c++

I'm really nooby with C++ (as my previous posts mention), however my friend suggested I work with QNetworkAccessManager if I want to send a HTTP GET request to send information.
I am currently working with openGL-es and want to do the following two lines of code to send the get request:
QNetworkAccessManager* netMan = new QNetworkAccessManager(this);
netMan->get(QNetworkRequest(QUrl("something/?userID=1")));
However, it does not like the "this" because it is in the main() method and it does not reference a QObject (I'm guessing QApplication). When I get rid of the "this" my application builds, but just never loads (I put a "printf(1)" at the top which doesn't even run).
Any suggestions or alternatives on how to fix this? Thanks in advance.
-James

The parameter in the QNetworkAccessManager constructor is only needed to specify a QObject based parent which will be responsible for cleaning up (deleting) your object later and isn't necessary if you plan to call delete on it yourself.
I'm not quite sure what you are referring to by "never loads" or where you put a printf but in order to get anything back, you need to actually keep the QNetworkReply pointer that is returned by the call to get().
And to get anything from that, you need an event loop running. If your application is console only (no GUI), you can use a QCoreApplication object.
Try this minimal code:
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QNetworkAccessManager *netMan = new QNetworkAccessManager();
QNetworkReply *reply = netMan->get(QNetworkRequest(QUrl("http://google.com")));
a.connect(reply, SIGNAL(finished()), SLOT(quit()));
a.exec();
qDebug() << reply->readAll();
delete netMan;
}

Related

How to connect two different objects

I have two objects, one will hold the graph, and the other a few buttons. How to use (connect) so that when you press button 1, the inscription is displayed in debag or the schedule is filled with a new one?
For example, I press the button created by the class BtnBox and my graph is displayed. How to use connect()?
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QThread>
#include "btnbox.h"
#include "plot.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
BtnBox *panel = new BtnBox(&a);
Plot *plot = new Plot();
QObject::connect(panel, SIGNAL(clickedBtn1()), plot, SLOT(slotPrinter()));
// panel->show();
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(plot);
mainLayout->addWidget(panel);
QWidget window;
window.setLayout(mainLayout);
window.show();
return a.exec();
}
Maybe you can use the QPushButton::clicked signal and write something like this:
connect(ui->pushButtonObj, &QPushButton::clicked, plot, &Plot::slotPrinter);
But if you want a custom behavior with your class BtnBox you can create on header file of BtnBox a signal.
signals:
void clickedBtn1();
And use: emit clickedBtn1(); whenever you want to emit it, your connect should work.
There is no need for implementation of the signal, you just have to emit it.
The emit keyword is not really necessary, if you want you can simply use clickedBtn();
Ok, I assume you have class BtnBox, and it already has this in the class definition (in .h file usually):
signals:
void clickedBtn1();
Qt moc will generate the implementation of that method, you don't need to do anything more for it here. But you do need to get that signal emitted. In many cases you would add emit clickedBtn1(); in the right places, but in this case you probably want to do something like this in BtnBox::BtnBox constructor:
connect(ui->button1, SIGNAL(clicked()), this, SIGNAL(clickedBtn1()));
Connecting signal to signal will simply do signal forwarding. Replace ui->button1 with the correct pointer to the button, whatever you have in your code.
Note on how to not do it, just to provide a bit of food for thought: Alternative way would be to expose the button 1 from the class, so in your main() you could then do something like this: QObject::connect(panel->getButton1(), SIGNAL(clickedBtn1()), plot, SLOT(slotPrinter()));. But this is generally considered a bit dirty, exposing internals of BtnBox class like that. It's better to expose the signal, and then the code using the class does not need to care how it gets emitted (for example from several different parts of BtnBox), or how internal implementation of BtnBox might change (for example converting it to QML).

Implementing a custom QWebEngineUrlSchemeHandler, cannot reply with a QNetworkReply

Using Qt 5.8, we are setting to implement a custom QWebEngineUrlSchemeHandler. Its behaviour should be to issue a GET query and respond with the returned content.
Our understanding is that the content is returned to the web engine through QWebEngineUrlRequestJob::reply second argument, which should derive from QIODevice. And as QNetworkReply derives from it, we expected an instance of this type to be a valid content provider.
A minimal example (not concerned with freeing dynamically allocated memory) would be:
#include <QBuffer>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QWebEngineUrlRequestJob>
#include <QWebEngineUrlSchemeHandler>
class CustomHandler : public QWebEngineUrlSchemeHandler
{
Q_OBJECT
public:
void requestStarted(QWebEngineUrlRequestJob *aRequestJob) override
{
QUrl requestedUrl("http://stackoverflow.com/");
QNetworkRequest *request = new QNetworkRequest(requestedUrl);
QNetworkReply *reply = mManager.get(*request);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
// Reply segment
aRequestJob->reply("text/html", reply);
}
public slots:
void slotError(QNetworkReply::NetworkError aError)
{
std::cout << "Error: " << aError << std::endl;
}
private:
QNetworkAccessManager mManager;
};
When executed, this outputs:
Error: 5
The code thus fails by calling the error slot CustomHandler::slotError with QNetworkReply::NetworkError, which corresponds to a canceled operation.
Is there a way to reply with a QNetworkReply, or is it mandatory to wait for the request to complete and then extract its reply content into a QBuffer first?
Theoretically it should work the way you coded it, but in practice it worked reliably for me only when aRequestJob->reply("text/html", reply); was called from the QNetworkReply::finished signal. You can also try to use readyRead signal, then you have to call reply every time you receive the signal, but as far as I remember it wasn't very reliable, so I decided to stick with the finished signal.
You can also move the data to QBuffer upon finished, but for any reason you have to close() the buffer before replying with it, otherwise it is not get read and appears as an empty response.
I reported this QTBUG-106461 5 days ago. The fixes are already merged into Qt dev branch and cherry-picked into several release branches. The example code in this question description should work in Qt WebEngine 6.4.1 or later.
It is unfortunate that developers choose to discuss bugs on StackOverflow and forums, apply workarounds and forget, instead of reporting them upstream. This bug could have been fixed long ago.
to avoid this error you have to insert
reply.deleteLater()
But in my case I don't see any result displayed. Don't know what to do get this working with QNetworkReply

Qt must construct QApplication before a QWidget

Qt recently started crashing without having a reason for it. The most recent one which is currently grinding my nerves down to a pulp is crashing due to starting another form programmatically. The "must construct QApplication before a QWidget" apparently is a common issue with Qt 5.7.* versions and the solutions I have found so far in StackOverflow haven't helped me.
This is a screenshot of the error message I got after the application crashed:
And here is the bit of the code that I remove which allows me to restart the application without any noticeable problems:
#include "operations.h"
Operations o;
void mainWindow::on_thisButton_clicked()
{
o.show();
this->hide();
}
----
The main.cpp as requested :)
#include "mainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mainWindow w;
w.show();
return a.exec();
}
Try this:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations *o = new Operations();
o->show();
this->hide();
}
You might want to declare Operations *o as a member of mainWindow and initialize it the the constructor if you don't want to create a new one each time the button is clicked.
"must construct QApplication before a QWidget" is the standard type of error you get with Qt applications, when linking something incompatible ( like mixing debug/release ).
So in most use cases this indicates a build problem and has nothing to with the code itself.
Don't create Operations object as a global variable, as it will be created as a static BEFORE running main(), therefore the error message is simply correct and relevant. This is a C++ issue, not a Qt one.
All other suggestions work because you now create the object at the right time, after the QApplication...
Okay, I have managed to find a solution, however, it is borderline idiotic as it does not make any sense why it does not work in its prior state. Technically, all you need to do in order to have the error not appearing is to stick the declaration of the form class you are referring within the function itself(ie Operations o;).
Here is the code solution itself:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations o;
o.show();
this->hide();
}
Bare in mind that this is not the end of all problems as I currently have the problem of the new form closing in the very same 1 second period it opens. If I manage to solve it I will update my solution.

QtWebKit c++ connect: cannot convert QWebView to SOCKET

Recently started doing some programming for Windows and I simply can't get my program to work. I am trying to achieve an environment in which I mainly can use HTML for the frontend and control the backend with Javascript. On Linux I've managed to add functions and stuff to the "JavaScriptCore" but Windows haven't been to kind with me.
Currently I'm trying to catch the URL change event, allowing for special URLs to execute commands, however I get the following error:
error: C2664: 'connect' : cannot convert parameter 1 from 'QWebView *' to 'SOCKET'
There is no context in which this conversion is possible
I didn't manage to find a single search result concerning "QWebView to SOCKET" so I have no clue what to do but to ask you guys.
Here is my code. I'm not too good with programming to please be gentle ;)
#include <QtGui>
#include <QtWebKit>
#include <QApplication>
#include <QWebView>
#include <iostream>
using namespace std;
void test()
{
cout << "Hello world";
}
int main(int argc, char** argv) {
QApplication app(argc, argv);
QWebView view;
view.setWindowFlags(Qt::CustomizeWindowHint);
view.setWindowFlags(Qt::FramelessWindowHint);
view.setFixedSize(1000,600);
view.setStyleSheet("background:transparent;");
view.setAttribute(Qt::WA_TranslucentBackground);
view.setUrl(QUrl("http://google.com"));
view.setWindowTitle("test v0.1");
connect(view, SIGNAL(urlChanged(QUrl)), SLOT(test()));
view.show();
return app.exec();
}
Try this instead:
QObject::connect(&view, &QWebView::urlChanged, test);
You are using the old connection syntax which works only with QObjects and slots, test is not a slot and it is not a function of a QObject derived class, it is a free funciton, so you have to use the new syntax, available since Qt 5.
When you are not inside a QObject you don't have access to connect(), that is why my example uses the QObject namespace to invoke it in main(). In your case as DNT noted it is just some other function that happens to be named "connect".
Another mistake you made is you passed the view, but connect() works with pointers, so you have to use the & operator to get a pointer to the view.

Problems Receiving QSerialPort Signals

I'm trying to write a simple program to test out the serial port, but am having trouble getting QSerialPort to work. I never receive signals from the QSerialPort object. I get 3 runtime warnings/errors that I think probably have something to do with it.
The errors are:
QApplication::qAppName: Please instantiate the Qapplication object first
QSocketNotifier: Can only be used with threads started with QThread
QSocketNotifier: Can only be used with threads started with QThread
The code snippet below is the smallest sample I can give to recreate the errors, it doesn't show me connecting signals but I think these errors are why I don't see them. If I don't call the open function none of the errors occur.
#include <QtGui/QApplication>
#include <QSerialPort>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PowerBoardGUI w;
w.show();
QSerialPort* serial = new QSerialPort();
serial->setPortName("/dev/ttyS1");
serial->setBaudRate(QSerialPort::Baud9600);
bool isOpen = serial->open(QIODevice::ReadWrite);
serial->close();
delete serial;
return a.exec();
}
The test system is Redhat 5.6. A static version of QT 4.7.4. And the latest version of QSerialPort (built from GIT today).