I need to get the data from an internet radio stream that I play with Qt and its QMediaplayer Class like so :
player->setMedia(QMediaContent(QUrl("http://rfm-live-mp3-64.scdn.arkena.com/rfm.mp3")),
but I cannot figure out how to access the stream data and record it to a buffer or a file. I tried QAUdioRecorder but the audioIn available seems only to be the mic.
Does anyone know if this is possible with Qt?
Thanks!
Edit----------------------
Here is the code with the suggestion of eyllanesc :
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFile file(R"(D:\\Mes_Projets_Qt_Creator\\build-TestQtDesignWidget-
Desktop_Qt_5_11_0_MinGW_32bit-Debug\\ML.wav)");
file.open(QIODevice::ReadOnly);
QByteArray arr = file.readAll();
QBuffer *buffer = new QBuffer(player);
buffer->setData(arr);
buffer->open(QIODevice::ReadOnly);
QFile autreFile("hello.wav");
autreFile.open(QIODevice::WriteOnly);
QDataStream out(&autreFile);
out << arr;
QAudioFormat format;
format.setSampleRate(22050);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning() << "Raw audio format not supported by backend, cannot play
audio.";
return;
}
QAudioOutput* audioOutput = new QAudioOutput(format, this);
audioOutput->start(buffer);
foreach (const QAudioDeviceInfo &deviceInfo,
QAudioDeviceInfo::availableDevices(QAudio::AudioOutput))
qDebug() << "Device name: " << deviceInfo.deviceName();
QNetworkAccessManager nam;
QNetworkRequest request(QUrl("http://rfm-live-mp3-
64.scdn.arkena.com/rfm.mp3"));
QString downloadDir =
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
QFile file2(QDir(downloadDir).absoluteFilePath("test.mp3"));
QDataStream ds(&file2);
if(!file2.open(QFile::WriteOnly))
//return -1;
QNetworkReply *reply = nam.get(request);
QObject::connect(reply, &QNetworkReply::downloadProgress, [reply, &ds]
(qint64 bytesReceived, qint64 bytesTotal){
ds << reply->readAll();
qDebug()<<bytesReceived<<bytesTotal;
});
qDebug()<<reply;
For this case you can use QNetworkAccessManager to download the file as I show below:
#include <QCoreApplication>
#include <QDataStream>
#include <QDir>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QStandardPaths>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QNetworkAccessManager nam;
QNetworkRequest request(QUrl("http://rfm-live-mp3-64.scdn.arkena.com/rfm.mp3"));
QString downloadDir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
QFile file(QDir(downloadDir).absoluteFilePath("test.mp3"));
QDataStream ds(&file);
if(!file.open(QFile::WriteOnly))
return -1;
QNetworkReply *reply = nam.get(request);
QObject::connect(reply, &QNetworkReply::downloadProgress, [reply, &ds](qint64 bytesReceived, qint64 bytesTotal){
ds << reply->readAll();
qDebug()<<bytesReceived<<bytesTotal;
});
qDebug()<<reply;
return a.exec();
}
Update:
In the following example I show how to implement my solution in a GUI, for this I have built the following interface using Qt Designer:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QFile>
#include <QMainWindow>
#include <QNetworkAccessManager>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void on_selectButton_clicked();
void on_startButton_clicked();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QNetworkAccessManager mNam;
QFile mFile;
QDataStream mDs;
QNetworkReply *reply;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QFile>
#include <QApplication>
#include <QNetworkReply>
#include <QFileDialog>
#include <QLineEdit>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->leUrl->setText("http://rfm-live-mp3-64.scdn.arkena.com/rfm.mp3");
ui->leOutput->setText(QDir(qApp->applicationDirPath()).absoluteFilePath("test.mp3"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
mDs << reply->readAll();
qDebug()<<bytesReceived<< bytesTotal;
}
void MainWindow::on_selectButton_clicked()
{
QString filename =QFileDialog::getSaveFileName(this, "Select ", qApp->applicationDirPath());
ui->leOutput->setText(filename);
}
void MainWindow::on_startButton_clicked()
{
mFile.setFileName(ui->leOutput->text());
mDs.setDevice(&mFile);
if(!mFile.open(QFile::WriteOnly))
return;
QNetworkRequest request(QUrl(ui->leUrl->text()));
reply = mNam.get(request);
connect(reply, &QNetworkReply::downloadProgress, this, &MainWindow::onDownloadProgress);
}
void MainWindow::on_pushButton_clicked()
{
if(reply){
reply->disconnect(SIGNAL(downloadProgress(qint64,qint64)));
reply->abort();
mFile.close();
reply->deleteLater();
}
}
The complete example can be found in the following link.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a problem with accessing progressBar from another class.
Here's the method that does not work.
I have progress bar in UI(mainwindow.ui) with name progressBar.
void QtDownload::downloadProgress(qint64 recieved, qint64 total) {
ui->progressBar->setMaximum(total);
ui->progressBar->setValue(recieved);
}
Here are all parts of the code:
downloader.pro
#-------------------------------------------------
#
# Project created by QtCreator 2017-01-12T15:22:17
#
#-------------------------------------------------
QT += core gui
QT += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = downloader
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QString>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
class QtDownload : public QObject {
Q_OBJECT
public:
explicit QtDownload();
QNetworkAccessManager manager;
QString target;
void setTarget(const QString& t);
private:
signals:
void done();
public slots:
void download();
void downloadFinished(QNetworkReply* data);
void downloadProgress(qint64 recieved, qint64 total);
};
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QtCore>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QUrl>
#include <QtNetwork/QNetworkRequest>
#include <QFile>
#include <QDebug>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkReply>
#include <QByteArray>
#include <QObject>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// QCoreApplication app(argc, argv);
QtDownload *dl = new QtDownload();
dl->setTarget( "http://media09.vbox7.com/s/21/21bbc2dca3r3634e3389.mp4");
dl->download();
//quit when the download is done.
// QObject::connect(&dl, SIGNAL(done()), &app, SLOT(quit()));
}
MainWindow::~MainWindow()
{
delete ui;
}
QtDownload::QtDownload() : QObject(0) {
QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*)));
}
void QtDownload::setTarget(const QString &t) {
this->target = t;
}
void QtDownload::downloadFinished(QNetworkReply *data) {
QFile localFile("C:/downloadedfile.mp4");
if (!localFile.open(QIODevice::WriteOnly))
return;
const QByteArray sdata = data->readAll();
localFile.write(sdata);
qDebug() << sdata;
localFile.close();
emit done();
}
void QtDownload::download() {
QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit());
QNetworkRequest request(url);
QObject::connect(manager.get(request), SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
}
void QtDownload::downloadProgress(qint64 recieved, qint64 total) {
ui->progressBar->setMaximum(total); // DOES NOT WORK
ui->MainWindow.progressBar->setValue(recieved); // DOES NOT WORK
}
That's because your slot shouldn't be inside the QtDownload, it should be inside the MainWindow.
You should pass the MainWindow inside its constructor (just as a parent widget), and reuse this MainWindow in your connect, instead of uthing this.
Edits in your QtDownload :
Header
QtDownload(QObject* parent = 0); //Don't forget to make it in the source file
signals:
void done();
void downloadProgress(qint64 recieved, qint64 total);
public slots:
void download();
void downloadFinished(QNetworkReply* data);
private:
MainWindow* parent; //Set it in the new constructor
Source
QtDownload::QtDownload(QObject *parent) : QObject(parent)
{
//The code that was initially inside QtDownload::QtDownload()
}
void QtDownload::download() {
QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit());
QNetworkRequest request(url);
QObject::connect(manager.get(request), SIGNAL(downloadProgress(qint64,qint64)), parent, SLOT(downloadProgress(qint64,qint64)));
}
Edits in your MainWindow
Header
public slots:
void downloadProgress(qint64 recieved, qint64 total);
Source
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// QCoreApplication app(argc, argv); (Remove this line, it should be in the main.cpp
QtDownload *dl = new QtDownload(this); //Pass this as parameter
dl->setTarget( "http://media09.vbox7.com/s/21/21bbc2dca3r3634e3389.mp4");
dl->download();
//quit when the download is done.
// QObject::connect(&dl, SIGNAL(done()), &app, SLOT(quit()));
}
void MainWindow::downloadProgress(qint64 recieved, qint64 total) {
ui->progressBar->setMaximum(total);
ui->progressBar->setValue(recieved);
}
I am trying to make the output of an http get connection stream to an lcd screen (a future http stock ticker), once connected. My code errors with “C:\Qt5\Tools\QtCreator\bin\httpGET\mainwindow.cpp:16: error: no matching function for call to ‘QLCDNumber::display() ui->lcdNumber->display()” I am unsure how to update display() properly
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
nam = new QNetworkAccessManager();
ui->lcdNumber->display(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::connect()
{
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
//ui->lcdNumber->display(10);
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(on_pushButton_clicked()));
}
void MainWindow::requestPage(){
QUrl url("http://www.google.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void MainWindow::finishedSlot(QNetworkReply* reply){
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
QImage pic = imageReader.read();
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
}
else
{
}
}
void MainWindow::on_pushButton_clicked()
{
connect();
requestPage();
}
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QNetworkAccessManager>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
public slots:
void connect();
void requestPage();
void finishedSlot(QNetworkReply* reply);
void on_pushButton_clicked();
private slots:
private:
QNetworkAccessManager* nam;
};
#endif // MAINWINDOW_H
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow mConnect;
mConnect.show();
return a.exec();
}
moving display() fixed the lcd output issue.
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
QImage pic = imageReader.read();
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
ui->lcdNumber->display(string);
}
My code compiles error free but the output to a little lcd panel I have should read 22. It reads the number 44 which is the initial value set in the constuctor. It is failing to update to a new value.
It appears MainWindow::finishedSlot(QNetworkReply* reply) is not being accessed and ui->lcdNumber->display(22) does not update the object as expected.
I can confirm that the connection does establish, I have wireshark running and I can see the software try and reach google, but nothing about that LCD I can get working because I cannot access the constructor object.
The purpose of the LCD is to reflect connection information, but right now I am just trying to reach the constructor.
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
#include <QLCDNumber>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
nam = new QNetworkAccessManager();
ui->lcdNumber->display(44);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::connect()
{
qDebug() << "connect";
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(on_pushButton_clicked()));
}
void MainWindow::requestPage(){
QUrl url("http://www.google.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void MainWindow::finishedSlot(QNetworkReply* reply){
qDebug() << "finishedSlot";
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
ui->lcdNumber->display(22);
// if (reply->error() == QNetworkReply::NoError)
// {
// QImageReader imageReader(reply);
// QImage pic = imageReader.read();
// QByteArray bytes = reply->readAll(); // bytes
// QString string(bytes); // string
// ui->lcdNumber->display(22);
//qDebug()<<string;
// }
// else
// {
// }
}
void MainWindow::on_pushButton_clicked()
{
requestPage();
}
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QNetworkAccessManager>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
public slots:
void connect();
void requestPage();
void finishedSlot(QNetworkReply* reply);
void on_pushButton_clicked();
private slots:
private:
QNetworkAccessManager* nam;
};
#endif // MAINWINDOW_H
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow mConnect;
mConnect.show();
return a.exec();
}
Maybe it's me, but it seems that there's no connection between button clicked signal and on_pushButton_clicked slot.
Final working solution
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
#include <QLCDNumber>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
nam = new QNetworkAccessManager();
//connect2();
//on_pushButton_clicked();
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(on_pushButton_clicked()));
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));
ui->lcdNumber->display(66);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::connect2()
{
qDebug() << "connect";
//QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
//this, SLOT(finishedSlot(QNetworkReply*)));
//QObject::connect(nam, SIGNAL(clicked()), this, SLOT(finishedSlot(QNetworkReply* reply)));
//;
}
void MainWindow::requestPage(){
QUrl url("http://www.google.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void MainWindow::finishedSlot(QNetworkReply* reply){
qDebug() << "finishedSlot";
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
ui->lcdNumber->display(11);
qDebug()<<string;
// if (reply->error() == QNetworkReply::NoError)
// {
// QImageReader imageReader(reply);
// QImage pic = imageReader.read();
// QByteArray bytes = reply->readAll(); // bytes
// QString string(bytes); // string
// ui->lcdNumber->display(22);
//qDebug()<<string;
// }
// else
// {
// }
}
void MainWindow::on_pushButton_clicked()
{
requestPage();
//connect();
}
I am getting the error ~mainwindow.cpp:9: error: redefinition of 'MainWindow::MainWindow(QWidget*)' MainWindow::MainWindow(QWidget *parent) : and I am pretty sure it is complaining about the wrong derived class name. The base class is MainWindow but I do not see what the derived class would be.
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void coreEng::requestPage(){
QUrl url("http://www.nyctelecomm.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void coreEng::finishedSlot(QNetworkReply* reply){
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
QImage pic = imageReader.read();
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
}
else
{
}
// delete reply();
}
void MainWindow::on_lcdNumber_overflow()
{
QByteArray replyData = netReply->readAll();
}
void MainWindow::on_pushButton_clicked()
{
QObject::on_pushButton_clicked(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
}
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <QNetworkAccessManager>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0):
QMainWindow(parent)
{
nam = new QNetworkAccessManager();
}
~MainWindow();
private:
Ui::MainWindow *ui;
public slots:
//void connect();
void on_pushButton_clicked();
void requestPage();
void finishedSlot(QNetworkReply* reply);
private slots:
void on_lcdNumber_overflow();
private:
QNetworkAccessManager* nam;
};
#endif // MAINWINDOW_H
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow mConnect;
mConnect.on_pushButton_clicked();
mConnect.requestPage();
MainWindow w;
w.show();
return a.exec();
}
You have defined MainWindow::MainWindow two times. First in header file and second in source file. That is said in error message.
explicit MainWindow(QWidget *parent = 0):
QMainWindow(parent)
{
nam = new QNetworkAccessManager();
}
//
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
I don't know what the problem is...The compiler (Qt) runs program without errors, but the file is not downloaded...
Can you tell me please tell what is wrong?
I made by example "download", which is located in the qt folder. The only difference is that they have is a console, and I have windows application.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtNetwork>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
class DownloadManager: public QObject
{
Q_OBJECT
QNetworkAccessManager manager;
QList<QNetworkReply *> currentDownloads;
public:
DownloadManager();
void doDownload(const QUrl &url);
QString saveFileName(const QUrl &url);
bool saveToDisk(const QString &filename, QIODevice *data);
public slots:
void execute();
void downloadFinished(QNetworkReply *reply);
};
#endif // MAINWINDOW_H
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QStringList>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QStringList>
#include <QTimer>
#include <QUrl>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
#if defined(Q_WS_S60)
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}
DownloadManager::DownloadManager()
{
connect(&manager, SIGNAL(finished(QNetworkReply*)),
SLOT(downloadFinished(QNetworkReply*)));
}
void DownloadManager::doDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
currentDownloads.append(reply);
}
QString DownloadManager::saveFileName(const QUrl &url)
{
QString path = url.path();
QString basename = QFileInfo(path).fileName();
if (basename.isEmpty())
basename = "download";
if (QFile::exists(basename)) {
// already exists, don't overwrite
int i = 0;
basename += '.';
while (QFile::exists(basename + QString::number(i)))
++i;
basename += QString::number(i);
}
return basename;
}
bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Could not open %s for writing: %s\n",
qPrintable(filename),
qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void DownloadManager::execute()
{
QStringList args = QCoreApplication::instance()->arguments();
args[0]="http://www.google.ru/images/srpr/logo3w.png";
QString arg=args[0];
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit());
doDownload(url);
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error()) {
fprintf(stderr, "Download of %s failed: %s\n",
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
printf("Download of %s succeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}
currentDownloads.removeAll(reply);
reply->deleteLater();
if (currentDownloads.isEmpty())
// all downloads finished
QCoreApplication::instance()->quit();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
QTimer::singleShot(0, &manager, SLOT(execute()));
}
The problem is at that point of your code:
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
}
QNetworkAccessManager is asynchronous, so it needs an event loop to do any downloading. But when the function on_pushButton_clicked() returns and gives the control back to the event loop, the QNetworkAccessManager is already destroyed, and didn't have the time to do anything.
When you add a QMessageBox in DownloadManager::execute, you are in fact running another event loop withing the slot on_pushButton_clicked(), and it gives the opportunity to the QNetworkAccessManager to do its work.
The correct solution would be to allocate DownloadManager dynamically, and eventually to make it destroy itself when it has finished all downloads.
void MainWindow::on_pushButton_clicked()
{
DownloadManager *manager = new DownloadManager(this);
manager->execute();
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
...
if (currentDownloads.isEmpty())
this->deleteLater();
}