开发者

Qt Download Files from QThread Based On Qt Example Doesn't work

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>
#inc开发者_如何转开发lude "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(clicked()),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.toLocal8Bit()));
    }
 }

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(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 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();
 }


Despite you call "networkMgr->get(request)" in your code, your thread probably exits before the actual download starts. Try to put "exec()" call at the very bottom of your "QThread::run()" method to enter the event loop in your thread that QNetworkAccessManager requires to be able to work. Also that would prevent the thread from finishing its execution too early. Your code would look like this:

void PhotosDownloadWorker::run()
{
  QStringList m_urlList;

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

  exec();
}


I think it wouldn't even connect the signal to the slot if the parameter lists are mismatched. See the debugger output for a warning about that at runtime (application output tab).

So, instead of

connect(networkMgr, SIGNAL(readyRead()), this, SLOT(downloadFinished(QNetworkReply*)));

do

connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));

Handling errors is done via QNetworkReply's error signal. Right after you get you can connect to the signal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜