PDA

View Full Version : Qt Download Files from QThread Based On Qt Example Doesn't work



umen
13th April 2011, 08:45
Hi i build simple example striped all irrelevant code and only the problematic code remains in general i have application that execute thread and inside this thread worker , i placed download code that supposed to download more then 30 files , this based on the Download Example Qt gives , the problem is that the QNetworkAccessManager Slot never invokes .
can you please tell me what im doing wrong here ?



class MainWindowContainer : public QMainWindow
{
Q_OBJECT

public:
MainWindowContainer(QWidget *parent = 0);


public slots:
void InvokeDownloadThread();

private:
QPushButton *pushButtonInvokeThread;
PhotosDownloadWorker* pm_hotosDownloadWorker;
};

#include <QtGui>
#include "MainWindowContainer.h"

MainWindowContainer::MainWindowContainer(QWidget* parent) :
QMainWindow(parent)
{
pushButtonInvokeThread = new QPushButton(this);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(pushButtonInvokeThread);
setLayout(layout);
QObject::connect(pushButtonInvokeThread,SIGNAL(cli cked()),this, SLOT(InvokeDownloadThread()));

}
void MainWindowContainer::InvokeDownloadThread()
{
pm_hotosDownloadWorker = new PhotosDownloadWorker(this);
pm_hotosDownloadWorker->Execute();
}

class PhotosDownloadWorker : public QThread
{
Q_OBJECT

public :
PhotosDownloadWorker(QObject *parent);
~PhotosDownloadWorker();
void Execute();
void append(const QStringList &urlList);
bool saveToDisk(const QString &filename, QIODevice *data);
QString saveFileName(const QUrl &url);

protected:
void run();

private:
bool m_abort;
QList<QNetworkReply *> currentDownloads;
QFile output;
QNetworkAccessManager* networkMgr ;

public slots:
void downloadFinished(QNetworkReply *reply);
void startNextDownload(const QUrl &url);



};

#include "PhotosDownloadWorker.h"
PhotosDownloadWorker::PhotosDownloadWorker(QObject *parent)
: QThread(parent)
{
m_abort = false;
networkMgr = new QNetworkAccessManager(this);
connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
}

PhotosDownloadWorker::~PhotosDownloadWorker()
{
m_abort = true;
wait();
}

void PhotosDownloadWorker::Execute()
{
m_abort = false;
start();
}
void PhotosDownloadWorker::run()
{
QStringList m_urlList;

m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");

// x 30
append(m_urlList);
}


void PhotosDownloadWorker::append(const QStringList &urlList)
{
foreach (QString url, urlList)
{
startNextDownload(QUrl::fromEncoded(url.toLocal8Bi t()));
}
}




void PhotosDownloadWorker::startNextDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = networkMgr->get(request);
currentDownloads.append(reply);
}
bool PhotosDownloadWorker::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 PhotosDownloadWorker::downloadFinished(QNetworkRep ly *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 succeeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}

reply->deleteLater();
currentDownloads.removeAll(reply);
if (currentDownloads.isEmpty())
{

this->exit();
}

}
QString PhotosDownloadWorker::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;
}

//main

#include "MainWindowContainer.h"

int main(int argc, char *argv[])
{

QApplication app(argc, argv);
MainWindowContainer mainWindowContainer;
mainWindowContainer.show();
return app.exec();
}

high_flyer
14th April 2011, 09:58
With out doweling too much on your code, the first thing which is wrong is that you are allocating you QNetworkAccessManager in the thread's constructor, which means its thread affinity is the main thread and NOT your thread, at the same time your QNetworkRequest which you pass to your 'networkMgr' is in your new thread.
So with out looking much at the functionality you have a salad of mixed thread affinities.
Be sure to read QThread docs and how thread affinity is determined.
Fix your code acourdingly, and see if the problem is solved.
Post again, with the corrected code if you still have a probelm.