C++/Qt/QNetworkAccessManager

Материал из C\C++ эксперт
Перейти к: навигация, поиск

Download from URL

<source lang="cpp"> /****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. include <QCoreApplication>
  2. include <QFile>
  3. include <QFileInfo>
  4. include <QList>
  5. include <QNetworkAccessManager>
  6. include <QNetworkRequest>
  7. include <QNetworkReply>
  8. include <QStringList>
  9. include <QTimer>
  10. include <QUrl>
  11. include <stdio.h>

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

}; 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.takeFirst();           // skip the first argument, which is the program"s name
   if (args.isEmpty()) {
       printf("Qt Download example - downloads all URLs in parallel\n"
              "Usage: download url1 [url2... urlN]\n"
              "\n"
              "Downloads the URLs passed in the command-line to the local directory\n"
              "If the target file already exists, a .0, .1, .2, etc. is appended to\n"
              "differentiate.\n");
       QCoreApplication::instance()->quit();
       return;
   }
   foreach (QString arg, args) {
       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();

} int main(int argc, char **argv) {

   QCoreApplication app(argc, argv);
   DownloadManager manager;
   QTimer::singleShot(0, &manager, SLOT(execute()));
   app.exec();

}

  1. include "main.moc"


 </source>


Download manager

<source lang="cpp"> /****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. ifndef TEXTPROGRESSBAR_H
  2. define TEXTPROGRESSBAR_H
  3. include <QString>

class TextProgressBar { public:

   TextProgressBar();
   void clear();
   void update();
   void setMessage(const QString &message);
   void setStatus(qint64 value, qint64 maximum);

private:

   QString message;
   qint64 value;
   qint64 maximum;
   int iteration;

};

  1. endif


  1. include "textprogressbar.h"
  2. include <QByteArray>
  3. include <stdio.h>

TextProgressBar::TextProgressBar()

   : value(0), maximum(-1), iteration(0)

{ } void TextProgressBar::clear() {

   printf("\n");
   fflush(stdout);
   iteration = 0;
   value = 0;
   maximum = -1;

} void TextProgressBar::update() {

   ++iteration;
   if (maximum > 0) {
       // we know the maximum
       // draw a progress bar
       int percent = value * 100 / maximum;
       int hashes = percent / 2;
       QByteArray progressbar(hashes, "#");
       if (percent % 2)
           progressbar += ">";
       printf("\r[%-50s] %3d%% %s     ",
              progressbar.constData(),
              percent,
              qPrintable(message));
   } else {
       // we don"t know the maximum, so we can"t draw a progress bar
       int center = (iteration % 48) + 1; // 50 spaces, minus 2
       QByteArray before(qMax(center - 2, 0), " ");
       QByteArray after(qMin(center + 2, 50), " ");
       printf("\r[%s###%s]      %s      ",
              before.constData(), after.constData(), qPrintable(message));
   }

} void TextProgressBar::setMessage(const QString &m) {

   message = m;

} void TextProgressBar::setStatus(qint64 val, qint64 max) {

   value = val;
   maximum = max;

}


  1. ifndef DOWNLOADMANAGER_H
  2. define DOWNLOADMANAGER_H
  3. include <QFile>
  4. include <QObject>
  5. include <QQueue>
  6. include <QTime>
  7. include <QUrl>
  8. include <QNetworkAccessManager>
  9. include "textprogressbar.h"

class DownloadManager: public QObject {

   Q_OBJECT

public:

   DownloadManager(QObject *parent = 0);
   void append(const QUrl &url);
   void append(const QStringList &urlList);
   QString saveFileName(const QUrl &url);

signals:

   void finished();

private slots:

   void startNextDownload();
   void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
   void downloadFinished();
   void downloadReadyRead();

private:

   QNetworkAccessManager manager;
   QQueue<QUrl> downloadQueue;
   QNetworkReply *currentDownload;
   QFile output;
   QTime downloadTime;
   TextProgressBar progressBar;
   int downloadedCount;
   int totalCount;

};

  1. endif


  1. include "downloadmanager.h"
  2. include <QFileInfo>
  3. include <QNetworkRequest>
  4. include <QNetworkReply>
  5. include <QString>
  6. include <QStringList>
  7. include <QTimer>
  8. include <stdio.h>

DownloadManager::DownloadManager(QObject *parent)

   : QObject(parent), downloadedCount(0), totalCount(0)

{ } void DownloadManager::append(const QStringList &urlList) {

   foreach (QString url, urlList)
       append(QUrl::fromEncoded(url.toLocal8Bit()));
   if (downloadQueue.isEmpty())
       QTimer::singleShot(0, this, SIGNAL(finished()));

} void DownloadManager::append(const QUrl &url) {

   if (downloadQueue.isEmpty())
       QTimer::singleShot(0, this, SLOT(startNextDownload()));
   downloadQueue.enqueue(url);
   ++totalCount;

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

} void DownloadManager::startNextDownload() {

   if (downloadQueue.isEmpty()) {
       printf("%d/%d files downloaded successfully\n", downloadedCount, totalCount);
       emit finished();
       return;
   }
   QUrl url = downloadQueue.dequeue();
   QString filename = saveFileName(url);
   output.setFileName(filename);
   if (!output.open(QIODevice::WriteOnly)) {
       fprintf(stderr, "Problem opening save file "%s" for download "%s": %s\n",
               qPrintable(filename), url.toEncoded().constData(),
               qPrintable(output.errorString()));
       startNextDownload();
       return;                 // skip this download
   }
   QNetworkRequest request(url);
   currentDownload = manager.get(request);
   connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)),
           SLOT(downloadProgress(qint64,qint64)));
   connect(currentDownload, SIGNAL(finished()),
           SLOT(downloadFinished()));
   connect(currentDownload, SIGNAL(readyRead()),
           SLOT(downloadReadyRead()));
   // prepare the output
   printf("Downloading %s...\n", url.toEncoded().constData());
   downloadTime.start();

} void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {

   progressBar.setStatus(bytesReceived, bytesTotal);
   // calculate the download speed
   double speed = bytesReceived * 1000.0 / downloadTime.elapsed();
   QString unit;
   if (speed < 1024) {
       unit = "bytes/sec";
   } else if (speed < 1024*1024) {
       speed /= 1024;
       unit = "kB/s";
   } else {
       speed /= 1024*1024;
       unit = "MB/s";
   }
   progressBar.setMessage(QString::fromLatin1("%1 %2")
                          .arg(speed, 3, "f", 1).arg(unit));
   progressBar.update();

} void DownloadManager::downloadFinished() {

   progressBar.clear();
   output.close();
   if (currentDownload->error()) {
       // download failed
       fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString()));
   } else {
       printf("Succeeded.\n");
       ++downloadedCount;
   }
   currentDownload->deleteLater();
   startNextDownload();

} void DownloadManager::downloadReadyRead() {

   output.write(currentDownload->readAll());

}


  1. include <QCoreApplication>
  2. include <QStringList>
  3. include "downloadmanager.h"
  4. include <stdio.h>

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

   QCoreApplication app(argc, argv);
   QStringList arguments = app.arguments();
   arguments.takeFirst();      // remove the first argument, which is the program"s name
   if (arguments.isEmpty()) {
       printf("Qt Download example\n"
              "Usage: downloadmanager url1 [url2... urlN]\n"
              "\n"
              "Downloads the URLs passed in the command-line to the local directory\n"
              "If the target file already exists, a .0, .1, .2, etc. is appended to\n"
              "differentiate.\n");
       return 0;
   }
   DownloadManager manager;
   manager.append(arguments);
   QObject::connect(&manager, SIGNAL(finished()), &app, SLOT(quit()));
   app.exec();

}


 </source>


QNetworkAccessManager based google suggest

<source lang="cpp"> /****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. ifndef GOOGLESUGGEST_H
  2. define GOOGLESUGGEST_H
  3. include <QObject>
  4. include <QNetworkAccessManager>

QT_BEGIN_NAMESPACE class QLineEdit; class QNetworkReply; class QTimer; class QTreeWidget; QT_END_NAMESPACE class GSuggestCompletion : public QObject {

   Q_OBJECT

public:

   GSuggestCompletion(QLineEdit *parent = 0);
   ~GSuggestCompletion();
   bool eventFilter(QObject *obj, QEvent *ev);
   void showCompletion(const QStringList &choices, const QStringList &hits);

public slots:

   void doneCompletion();
   void preventSuggest();
   void autoSuggest();
   void handleNetworkData(QNetworkReply *networkReply);

private:

   QLineEdit *editor;
   QTreeWidget *popup;
   QTimer *timer;
   QNetworkAccessManager networkManager;

};

  1. endif // GOOGLESUGGEST_H


  1. include <QtCore>
  2. include <QtGui>
  3. include <QtNetwork>
  4. include "googlesuggest.h"
  5. define GSUGGEST_URL "http://google.com/complete/search?output=toolbar&q=%1"

GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), editor(parent) {

   popup = new QTreeWidget;
   popup->setColumnCount(2);
   popup->setUniformRowHeights(true);
   popup->setRootIsDecorated(false);
   popup->setEditTriggers(QTreeWidget::NoEditTriggers);
   popup->setSelectionBehavior(QTreeWidget::SelectRows);
   popup->setFrameStyle(QFrame::Box | QFrame::Plain);
   popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
   popup->header()->hide();
   popup->installEventFilter(this);
   popup->setMouseTracking(true);
   connect(popup, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
           SLOT(doneCompletion()));
   popup->setWindowFlags(Qt::Popup);
   popup->setFocusPolicy(Qt::NoFocus);
   popup->setFocusProxy(parent);
   timer = new QTimer(this);
   timer->setSingleShot(true);
   timer->setInterval(500);
   connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
   connect(editor, SIGNAL(textEdited(QString)), timer, SLOT(start()));
   connect(&networkManager, SIGNAL(finished(QNetworkReply*)),
           this, SLOT(handleNetworkData(QNetworkReply*)));

} GSuggestCompletion::~GSuggestCompletion() {

   delete popup;

} bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) {

   if (obj != popup)
       return false;
   if (ev->type() == QEvent::MouseButtonPress) {
       popup->hide();
       editor->setFocus();
       return true;
   }
   if (ev->type() == QEvent::KeyPress) {
       bool consumed = false;
       int key = static_cast<QKeyEvent*>(ev)->key();
       switch (key) {
       case Qt::Key_Enter:
       case Qt::Key_Return:
           doneCompletion();
           consumed = true;
       case Qt::Key_Escape:
           editor->setFocus();
           popup->hide();
           consumed = true;
       case Qt::Key_Up:
       case Qt::Key_Down:
       case Qt::Key_Home:
       case Qt::Key_End:
       case Qt::Key_PageUp:
       case Qt::Key_PageDown:
           break;
       default:
           editor->setFocus();
           editor->event(ev);
           popup->hide();
           break;
       }
       return consumed;
   }
   return false;

} void GSuggestCompletion::showCompletion(const QStringList &choices, const QStringList &hits) {

   if (choices.isEmpty() || choices.count() != hits.count())
       return;
   const QPalette &pal = editor->palette();
   QColor color = pal.color(QPalette::Disabled, QPalette::WindowText);
   popup->setUpdatesEnabled(false);
   popup->clear();
   for (int i = 0; i < choices.count(); ++i) {
       QTreeWidgetItem * item;
       item = new QTreeWidgetItem(popup);
       item->setText(0, choices[i]);
       item->setText(1, hits[i]);
       item->setTextAlignment(1, Qt::AlignRight);
       item->setTextColor(1, color);
   }
   popup->setCurrentItem(popup->topLevelItem(0));
   popup->resizeColumnToContents(0);
   popup->resizeColumnToContents(1);
   popup->adjustSize();
   popup->setUpdatesEnabled(true);
   int h = popup->sizeHintForRow(0) * qMin(7, choices.count()) + 3;
   popup->resize(popup->width(), h);
   popup->move(editor->mapToGlobal(QPoint(0, editor->height())));
   popup->setFocus();
   popup->show();

} void GSuggestCompletion::doneCompletion() {

   timer->stop();
   popup->hide();
   editor->setFocus();
   QTreeWidgetItem *item = popup->currentItem();
   if (item) {
       editor->setText(item->text(0));
       QKeyEvent *e;
       e = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
       QApplication::postEvent(editor, e);
       e = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);
       QApplication::postEvent(editor, e);
   }

} void GSuggestCompletion::preventSuggest() {

   timer->stop();

} void GSuggestCompletion::autoSuggest() {

   QString str = editor->text();
   QString url = QString(GSUGGEST_URL).arg(str);
   networkManager.get(QNetworkRequest(QString(url)));

} void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply) {

   QUrl url = networkReply->url();
   if (!networkReply->error()) {
       QStringList choices;
       QStringList hits;
       QString response(networkReply->readAll());
       QXmlStreamReader xml(response);
       while (!xml.atEnd()) {
           xml.readNext();
           if (xml.tokenType() == QXmlStreamReader::StartElement)
               if (xml.name() == "suggestion") {
                   QStringRef str = xml.attributes().value("data");
                   choices << str.toString();
               }
           if (xml.tokenType() == QXmlStreamReader::StartElement)
               if (xml.name() == "num_queries") {
                   QStringRef str = xml.attributes().value("int");
                   hits << str.toString();
               }
       }
       showCompletion(choices, hits);
   }
   networkReply->deleteLater();

}


  1. ifndef SEARCHBOX_H
  2. define SEARCHBOX_H
  3. include <QLineEdit>

class GSuggestCompletion; class SearchBox: public QLineEdit {

   Q_OBJECT

public:

   SearchBox(QWidget *parent = 0);

protected slots:

   void doSearch();

private:

   GSuggestCompletion *completer;

};

  1. endif // SEARCHBOX_H


  1. include <QDesktopServices>
  2. include <QUrl>
  3. include "searchbox.h"
  4. include "googlesuggest.h"
  5. define GSEARCH_URL "http://www.google.com/search?q=%1"

SearchBox::SearchBox(QWidget *parent): QLineEdit(parent) {

   completer = new GSuggestCompletion(this);
   connect(this, SIGNAL(returnPressed()), SLOT(doSearch()));
   setWindowTitle("Search with Google");
   adjustSize();
   resize(400, height());
   setFocus();

} void SearchBox::doSearch() {

   completer->preventSuggest();
   QString url = QString(GSEARCH_URL).arg(text());
   QDesktopServices::openUrl(QUrl(url));

}


  1. include <QApplication>
  2. include "searchbox.h"

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

   QApplication app(argc, argv);
   SearchBox *searchEdit = new SearchBox;
   searchEdit->show();
   return app.exec();

}


 </source>