Multiple get/post calls using a wrapper class with Qt - c++

I am working on a Qt project with a team. I have two functions — one retrives the numerical coordinates of a place, the other downloads the map of the place — that I want to merge in one wrapper class, so that my teammates can call it easily.
#include <QCoreApplication>
#include <QFile>
#include <QHttpMultiPart>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <iostream>
class OpenStreetMapWrapper: public QObject{
Q_OBJECT
public:
OpenStreetMapWrapper(QObject *parent=nullptr):QObject(parent){
connect(&manager, &QNetworkAccessManager::finished, this, &OpenStreetMapWrapper::handle_finished);
}
void download(const std::string &region, const std::string &department, const QFile& outfile){
QNetworkRequest request;
QUrl url = QUrl(QString::fromStdString("https://download.openstreetmap.fr/extracts/europe/france/" + region + "/" + department + ".osm.pbf"));
request.setUrl(url);
request.setAttribute(QNetworkRequest::User, outfile.fileName());
manager.get(request);
}
void searchCSV(QFile& file, QFile& outfile){
QNetworkRequest request(QUrl("https://api-adresse.data.gouv.fr/search/csv/")); // Free API provided by the French government
request.setAttribute(QNetworkRequest::User, outfile.fileName());
QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart postpart;
postpart.setHeader(QNetworkRequest::ContentDispositionHeader,
QString("form-data; name=%1; filename=%2")
.arg("data", file.fileName()));
postpart.setBodyDevice(&file);
multipart->append(postpart);
file.setParent(multipart);
manager.post(request, multipart);
}
private:
QNetworkAccessManager manager;
void handle_finished(QNetworkReply *reply){
if(reply->error() == QNetworkReply::NoError){
QByteArray read = reply->readAll();
std::cout << read.toStdString() << std::endl; // For debugging
QString filename = reply->request().attribute(QNetworkRequest::User).toString();
QFile out(filename);
if(out.open(QIODevice::WriteOnly)){
out.write(read);
out.close();
}
}
else{
qDebug() << reply->error() << reply->errorString();
}
reply->deleteLater();
// QCoreApplication::quit(); This is done somewhere else?
}
};
#include <main.moc>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
OpenStreetMapWrapper A;
QFile file("./search.csv");
file.open(QIODevice::ReadWrite);
QFile outfile("./output.csv");
outfile.open(QIODevice::ReadWrite);
// Search
A.searchCSV(file, outfile); // 1st call works
A.searchCSV(file, outfile); // 2nd call -> makes both calls fail.
// Downloader
std::string region = "corse";
std::string department = "haute_corse";
return a.exec();
}
The problem with the code above, is that when for example searchCSV is called it displays the output as needed, but if it is called twice in the code, there is no output at all. After some debugging I think the problem is that the manager and handle_finished are not connected properly, because the execution never reaches there. Is there a simple way to solve this issue? Ideally, there is just one class instant, and any method can be called any number of times.

I don't know much about Qt, but it looks like you're trying to read from file twice and my guess is that when it reaches the end of the file after the first call to A.searchCSV it is done and you can't read from it anymore - unless you reposition the QFile to the beginning of the file.
Possible solution:
A.searchCSV(file, outfile);
file.unsetError(); // possibly needed
file.seek(0); // rewind to the start of the file
A.searchCSV(file, outfile);

The two QFile (input, output) are shared between two asynchronous calls (searchCSV) that might give an undefined behavior. The input file (stream) contents will be load and push only after the connection was made (like curl does).
You should:
Make searchCSV a blocking function (wait until handle_finished() done), input file pointer should be reinitialized before an other call.
OR: Use separated input/output QFile instances

Related

The Logs are not showing in QT Application Window

i am making a Tail Log application. It is executing perfectly but the output window is not showing any results.
Below is the code:
LogTail.cpp
#include "logtail.h"
#include <QApplication>
#include <QTextEdit>
#include<QDebug>
//start id=constructor
LogTail::LogTail(QString fn) {
//if (fn == QString()) {
// fn = "C:/Users/arpit.k/OneDrive - Accord Software & Systems Pvt. Ltd/Documents/QT/LogTail3/sample.log";
// }
connect (this, SIGNAL(readyReadStandardOutput()),
this, SLOT(logOutput())); /* When there is input ready, call this slot.*/
QStringList argv;
argv << "-f" << fn; /* tail -f filename */
start("tail", argv); /* Returns immediately, and now there is a child process running, "attached"
to this process. When this process exits, the child tail process will also terminate. */
}
LogTail::~LogTail() {
terminate(); /* Attempts to terminate this process. */
}
//end
//start id=logOutput
// tail sends its output to stdout.
void LogTail::logOutput() { /* Slot called whenever there is input to read. */
QByteArray bytes = readAllStandardOutput();
QStringList lines = QString(bytes).split("\n");
foreach (QString line, lines) {
//qDebug() << line;
emit logString(line);
}
}
//end
main.cpp
#include "logtail.h"
#include <QTextEdit>
#include <QApplication>
int main (int argc, char* argv[]) {
QApplication app(argc, argv);
QStringList al = app.arguments();
QTextEdit textEdit;
textEdit.setWindowTitle("Debug");
textEdit.setWindowTitle("logtail demo");
QString filename = "sample.log";
if (al.size() > 1) filename = al[1];
LogTail tail(filename); /* Create object, starts process too. */
tail.connect (&tail, SIGNAL(logString(const QString&)),
&textEdit, SLOT(append(const QString&)));
textEdit.show();
return app.exec();
}
Note: sample.log file contains some log data
Output window doesn't show any logs:
(https://i.stack.imgur.com/ENhqs.png)
I need it to display recent 10 Log lines!
Assuming you are subclassing from QProcess (you should post a complete minimal example in order to get an accurate answer).
You are starting the process in the constructor of LogTail, 'tail' will probably output some data or some events that will trigger readyReadStandardOutput before you have the chance to connect the signal in the main function.
readyReadStandardOutput will be triggered only once as you never cleared the input buffer (you never had the chance to read the available data).
So in order to make your example work you should call logOutput after you start the process.
Anyway I will suggest you to implement differently, I would call start from outside or at least outside the constructor, that way your object will be more scalable.

Capture stdout in a Qt Application

I am trying to capture output of my Qt application but without success.
(I am calling an external lib that outputs to console, and I want to show this in my UI. Its NOT a QProcess, its a calss instance in my own process).
The problem: my lambda slot when writing to std::cout never gets called.
Here is my code distilled to a small testable application.
This is my latest attempt, and so far I am getting the "furthest" with it meaning, that the std::cout output is successfully redirected to the QFile.
What I don't understand however, is why the QTextStream connected to this file is not being triggered?
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <iostream>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QFile file("output.txt");
file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate);
// Redirect stdout to the QFile
std::freopen(file.fileName().toStdString().c_str(), "w", stdout);
QTextStream stream(&file);
std::string output; //to spy on in debugger
//this lambda never gets called!?
QObject::connect(&file, &QFile::readyRead, [&stream,&output] {
// Read from the QTextStream whenever new data is available
output += stream.readLine().toStdString();
qApp->quit();
});
//This succefully writes to the QFile on disk
QTimer::singleShot(100, [] {
std::cout << "This will be written to output.txt" << std::endl<<std::flush;
});
app.exec();
// Close the stream
std::fclose(stdout);
file.close();
}
My previous attempts are listed below, and are still not answered, so if you know how to fix any of the approaches, I will be really thankful!
Note at the end of the code, I am outputting directly to std::cout and to the QTextStream.
All of these outputs are seen on the console, including the output to stream - which means, that QTextStream object is correctly initialized with stdout.
Any ideas why the lambda slot is not getting called?
(I am aware of the recursion that will happen in the lambda due to outputting to stdout in it. But as this is just a test code its ok - the problem is that the lambda is not getting called at all)
#include <QCoreApplication>
#include <iostream>
#include <QTextStream>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QTextStream stream(stdout);
QObject::connect(stream.device(), &QIODevice::bytesWritten, [&stream](qint64 bytes) {
// This lambda function is called when new data is available to be read
std::cout<<"in lambda"<<std::endl;
});
QTimer::singleShot(100, [&stream]{
std::cout << "Hello, world!" << std::endl<<std::flush;
std::cout << "This is some output." << std::endl<<std::flush;
stream<< "Stream output\n";
stream.flush();
});
return app.exec();
}
After some more thought, it occurred to me to try listening on stdout with QSocketNotifier.
With this approach, the notifier slot gets triggered, however, two things:
The notifier slot gets called before the QTimer slot - repeatedly like in an endless loop.
I get nothing from the stream which is really confusing me - I am being notified when stdout is being written to (even though nothing is writing to it, yet) and am I getting nothing when trying to read that data? (the fact that I get nothing is not that surprising since I didn't write anything (yet) to stdout it's more the fact it is being triggered all the time)
Anyone knows how to explain this?
Here is the code:
#include <QCoreApplication>
#include <iostream>
#include <QTextStream>
#include <QTimer>
#include <QSocketNotifier>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QTextStream stream(stdout);
int stdoutFd = fileno(stdout);
std::string output; //allows me to spy the content in the debuger
QSocketNotifier notifier(stdoutFd, QSocketNotifier::Write );
QObject::connect(&notifier, &QSocketNotifier::activated, [&stream, &output] {
auto s = stream.readAll();
output += s.toStdString();
});
QTimer::singleShot(100, [&stream]{
std::cout << "This is some output." << std::endl<<std::flush;
stream << "Stream output\n";
});
return app.exec();
}
Many thanks in advance!
I have managed to achieve what I wanted, not very elegant, but it works.
I am putting my solution here for others that might also encounter this problem.
On one hand I like this solution since its basically pure C++ and does not require Qt.
On the other, it requires polling, which is quite "clunky".
Thus, I am leaving my OP open, with the hope that a more elegant solution will be offered, and I am curious as to why my Qt solutions didn't work.
This solution uses std::stringstream and std::streambuf.
I am putting here in a simple example main(), you can then adapt it to what ever application you have as it is really simple.
https://onlinegdb.com/AixVsxUyy
#include <sstream>
#include <iostream>
int main(int argc, char *argv[]) {
//Redirect stdout to streambuf - this "grabs" the stdout
std::stringstream buffer;
std::streambuf *streamBuff = std::cout.rdbuf(buffer.rdbuf());
std::cout << "this is redirected to streambuf" << std::endl;
//Read our buffer
std::string text = buffer.str();
// Release stdout back to original buffer
std::cout.rdbuf(streamBuff);
std::cout << "Grabbed text:" << text << std::endl;
std::exit(0);
}
Since this is synchronous, I resorted to polling buffer.str().
If anyone knows how can I be notified when streambuff has new data, please share.
Note:
When polling, if between the calls no new data was written to stdout, the same string will be read again as the buffer is still intact.
If you want to clear the buffer when you read it call:
buffer.clear();
buffer.str("");
I hope this helps someone!

How do you run a function in the background of your program (Specifically an autosave function)? QT / C++

In my code I would like to integrate an auto-save function that runs every couple seconds or so. I would like this to run in the background because I have other stuff that I am going to be running at the same time. So how would I do this?
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
#include <QFile>
#include <QDebug>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
// Setup code
ui->textEdit->setReadOnly(true);
ui->textEdit->append("Select one of the buttons on the left to pick a log");
}
MainWindow::~MainWindow() {
delete ui;
}
string lastSavedText[] = {
" ",
" "
};
QString qLastSavedTextHome, qLastSavedTextWork;
This is my first button
void MainWindow::on_homeButton_clicked() {
// Preparing text edit
ui->textEdit->setReadOnly(false);
ui->textEdit->clear();
ui->textEdit->setOverwriteMode(true);
// Loading previously saved text
QFile file { "home.apl" };
if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
qDebug() << "Could not open file!";
return;
}
const auto& lastSavedText = file.readAll();
file.close();
ui->textEdit->setPlainText( lastSavedText );
}
This is my second one
void MainWindow::on_workButton_clicked() {
// Preparing text edit
ui->textEdit->setReadOnly(false);
ui->textEdit->clear();
ui->textEdit->setOverwriteMode(true);
// Loading previously saved text
QFile file2 { "work.apl" };
if ( !file2.open(QIODevice::ReadOnly | QIODevice::Text) ) {
qDebug() << "Could not open file!";
return;
}
const auto& lastSavedText = file2.readAll();
file2.close();
ui->textEdit->setPlainText( lastSavedText );
}
This is the save button I hope to eliminate with an autosave
void MainWindow::on_saveButton_clicked() {
// Converts textEdit to string
QString textEditText = ui->textEdit->toPlainText();
lastSavedText[0] = textEditText.toStdString();
// Saving files
ofstream home;
home.open("home.apl");
home << lastSavedText[0];
home.close();
ofstream work;
work.open("work.apl");
work << lastSavedText[1];
work.close();
}
There is 2 solutions.
Easy one
Use simply a timer that will execute the code of your save button. You can set the timer to execute any period of time.
QTimer
But this might cause the software to freeze if this operation takes too much time. In which case, you can put the function that saves inside a thread.
Threads
You can use threads to do that.
Thread, is basically a process that will detach from your main process and can be run at the same time, each thread doing its own work.
Note that to communicate between thread, the safest method is to use signals.
Qt Threads Documentation
Example
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
You can use a QTimer with QtConcurrent::run, and then you get the simplicity with the benefit of running the saving on a different thread you don't need to manage.
Practically, try
QTimer::singleShot(time, this, Qt::TimerType::CoarseTime, QtConcurrent::run(this,&MainWindow::on_saveButton_clicked));
Here's a first approximation using a background thread (for the sake of brevity, it inherits QThread - for your real application, consider decoupling the QThread base-class from this worker thread object. That will also make it possible to give a father-object for t).
class Thread: public QThread {
Q_OBJECT
public:
Thread(QTextEdit *textEdit):textEdit(textEdit) {
QTimer *t = new QTimer;
connect(t, SIGNAL(timeout()), SLOT(saveOnce()));
t->moveToThread(this);
t->start(2000);
}
protected:
QTextEdit *textEdit;
std::string lastSavedText[2];
private slots:
QString text() const { return textEdit->toPlainText(); }
void saveOnce() {
QString textEditText;
QMetaObject::invokeMethod(this,
"text", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString,textEditText));
lastSavedText[0] = textEditText.toStdString();
// Saving files
ofstream home;
home.open("home.apl");
home << lastSavedText[0];
home.close();
ofstream work;
work.open("work.apl");
work << lastSavedText[1];
work.close();
}
};
Care must be taken, when taking this approach with BlockingQueuedConnection, that the thread does not call invokeMethod while the main thread is waiting for it to exit - then a deadlock happens because the main-thread cannot process the text() queued call anymore.

Looping through QNetworkAccessManager get() routines, retrieve order on finish

I have a QNetworkAccessManager as a member of my class. I connect the finished signal from this manager to the replyFinished function I have written.
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
In a separate routine, I loop through a get call from the manager
for (int si = 0; si<numLines; si++)
{
QString line = lines[si];
manager->get(QNetworkRequest(QUrl(line)));
}
In my replyFinished slot routine, I know I may not receive the signals in the order they were performed in the loop, but is there any way I can obtain that information? That is, is there a clever way I can obtain "si" in my replyFinished routine? Thanks for the help!
QNetworkAccessManager::get() returns a pointer to the QNetworkReply object. This pointer is the same one that is passed your replyFinished() slot. You can use a QMap to store pairings of QNetworkReply* pointers and integers (si in your code).
Here is a working example;
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QMap>
#include <QtDebug>
QNetworkAccessManager am;
void finished(QNetworkReply* reply);
QMap<QNetworkReply*, int> requests;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QObject::connect(&am, &QNetworkAccessManager::finished, finished);
QStringList links;
links << "http://google.com";
links << "http://taobao.com";
links << "http://stackoverflow.com";
links << "http://stackexchange.com";
links << "http://bing.com";
for (int i=0; i < links.size(); i++)
{
requests.insert(am.get(QNetworkRequest(QUrl(links[i]))), i);
}
return a.exec();
}
void finished(QNetworkReply* reply)
{
qDebug() << requests[reply];
}
The slot replyFinished(QNetworkReply*) receives pointer to the related reply object. This reply object contains all information about that reply (error code, headers, downloaded data, the URL of the content) and also it contains initial request (QNetworkReply::request()). So, it is possible to check the URL of the request or the URL of actual downloaded content. Note that those URLs may be different.
QNetworkReply::url():
Returns the URL of the content downloaded or uploaded. Note that the
URL may be different from that of the original request.
QNetworkReply::request():
Returns the request that was posted for this reply. In special, note
that the URL for the request may be different than that of the reply.
void MainWindow::replyFinished(QNetworkReply* reply)
{
qDebug() << reply->url();
qDebug() << reply->request().url();
}

Signal-Slot makes a mess

I am trying to create a image-saving application using Qt. Now the stub
class ImageSaver:public QObject
{
int index;
QWebPage * main_Page;
QNetworkAccessManager * manager;
QNetworkReply * reply;
QString file_Name;
QSet<QString> image_Addresses;
QString web_Address;
Q_OBJECT
signals:
void image_Saved();
public slots:
void request_Image();
void on_Finished(bool status);
void got_Reply(QNetworkReply * reply);
public:
ImageSaver();
void start();
};
ImageSaver::ImageSaver()
{
index = 0;
manager = new QNetworkAccessManager;
reply = NULL;
connect(main_Page,SIGNAL(loadFinished(bool)),this,SLOT(on_Finished(bool)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(got_Reply(QNetworkReply*)));
connect(this,SIGNAL(image_Saved()),this,SLOT(request_Image()));
}
void ImageSaver::start()
{
//loads the url
// In the end of the loading it will emit load_Finished(bool)
// So that signal will execute on_Finished(bool)
}
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
//makes a request to the server to give the image "temp_Address"
//When the server gives the reply signal finished(QNetworkReply*) will be emitted
// this in turn will call the got_Reply(QNetworkReply*)
}
void ImageSaver::on_Finished(bool status)
{
//collects all the images's url addresses, and pushes them in the list
//"image_Addresses"
//Then emits image_Saved();
//This signal will wake up the function request_Image()
}
void ImageSaver::got_Reply(QNetworkReply * reply)
{
//Image is extracted from the reply and got saved in the same name as in the page
//index got increased;
//emits the signal image_Saved();
//This signal will activate the function request_Image()
}
int main(int argc,char * argv[])
{
QApplication app(argc,argv);
ImageSaver a;
a.start();
return app.exec();
}
#include "main.moc"
In short First call is to "start".That calls "on_Finished" and there is no problem untill this. So all the image files's addresses got pushed in the list. Next is one by one request for image[i] made, and the reply image got saved. This thing is happening repeatedly. Here only I am getting problem. Crashes are appearing in this operation especially in saving the image.
My assumption is "signal-slot" is not like function call, thy are more or less like thread but operates on the same function( pointer). So when one signal requests for painter, which is already rendering something then the crash will appear.
Can anybody say the fact behind the crash and how to save all the images without crash?
EDIT:
Hi, This is the full code. Run this one, and click the message boxes contineously
#include <QApplication>
#include <QDir>
#include <QImage>
#include <QObject>
#include <QMessageBox>
#include <QPainter>
#include <QPixmap>
#include <QSet>
#include <QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <QtWebKit/QWebElement>
#include <QtWebKit/QWebFrame>
#include <QtWebKit/QWebPage>
#include <QUrl>
class ImageSaver:public QObject
{
int index;
QWebPage * main_Page;
QNetworkAccessManager * manager;
QNetworkReply * reply;
QString file_Name;
QSet<QString> image_Addresses;
QString web_Address;
Q_OBJECT
signals:
void image_Saved();
public slots:
void request_Image();
void on_Finished(bool status);
void got_Reply(QNetworkReply * reply);
public:
ImageSaver();
void start();
protected:
//void show_Frame(QWebFrame * frame);
};
ImageSaver::ImageSaver()
{
index = 0;
this->main_Page = new QWebPage;
manager = new QNetworkAccessManager;
reply = NULL;
connect(main_Page,SIGNAL(loadFinished(bool)),this,SLOT(on_Finished(bool)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(got_Reply(QNetworkReply*)));
connect(this,SIGNAL(image_Saved()),this,SLOT(request_Image()));
}
void ImageSaver::start()
{
web_Address = "yahoo.com";
QDir dir;
dir.mkdir(web_Address);
QUrl url = QUrl::fromUserInput(web_Address);
main_Page->mainFrame()->load(url);
}
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
int a = temp_Address.lastIndexOf("/");
file_Name = temp_Address.mid(a+1);
//Without the below message box, the program closes shortly
//This message box is slowing down that effect
QMessageBox hh;
hh.setText(file_Name);
hh.exec();
QNetworkRequest request= QNetworkRequest(QUrl(temp_Address));
request.setRawHeader("img","src");
manager->get(request);
}
void ImageSaver::on_Finished(bool status)
{
if(status)
{
QMessageBox mm;
mm.setText("Finished");
mm.exec();
QWebElementCollection temp_Collection= main_Page->mainFrame()->findAllElements("*");
for(int i=0;i<temp_Collection.count();++i)
{
QWebElement temp_Element = temp_Collection[i];
if(temp_Element.tagName().contains("img",Qt::CaseInsensitive) && temp_Element.attributeNames().contains("src",Qt::CaseInsensitive))
{
QString image_Web_Address = temp_Element.attribute("src");
if(!image_Addresses.contains(image_Web_Address))
image_Addresses.insert(image_Web_Address);
}
}
emit image_Saved();
QMessageBox kk;
kk.setText("Image is going to be saved");
kk.exec();
}
else
{
QMessageBox mm;
mm.setText("Not ready");
mm.exec();
}
QMessageBox mm;
mm.setText("Getting out of finished");
mm.exec();
}
void ImageSaver::got_Reply(QNetworkReply * reply)
{
QImage image;
if(image.load(static_cast<QIODevice *>(reply),0))
image.save(web_Address+QDir::separator()+file_Name,0);
++index;
emit image_Saved();
}
/*
void ImageSaver::show_Frame(QWebFrame * temp_Frame)
{
QImage image(temp_Frame->contentsSize(),QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setRenderHint(QPainter::TextAntialiasing,true);
painter.setRenderHint(QPainter::SmoothPixmapTransform,true);
temp_Frame->documentElement().render(&painter);
painter.end();
foreach(QWebFrame * temp_Frame0,temp_Frame->childFrames())
show_Frame(temp_Frame0);
}
*/
int main(int argc,char * argv[])
{
QApplication app(argc,argv);
ImageSaver a;
a.start();
return app.exec();
}
#include "main.moc"
This is the pro file
QT += webkit network
SOURCES += \
main.cpp
Your code crashes because you read beyond the boundaries of the image_Addresses set.
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
...
You increment index after every image received, but there isn't any check anywhere in the code whether index is still less than image_Addresses.size(), so it crashes once dereferencing image_Addresses.begin()+index for index == image_Addresses.size().
There may be many solutions to this problem. I think that you should have a look at The State Machine Framework. In easy situations you can just use boolean variable to check if you can go on. You should also think what to do when you're busy processing the image. You can queue request or just reject them. Also you can implement threading, so that new requests are served by new threads.
P.S. Signals are more like events than threads to me.
What's the error and why do you have a #include at the end?
FYI there is a QImage class you can use instead which includes saving and loading from a QIODevice* such as QNetworkReply for example. It's extremely rare to need to reinvent the wheel in the massive framework that is Qt.