From a88d54ee9c74aca5fa106afccbc570c61e2d3b39 Mon Sep 17 00:00:00 2001 From: Jussi Laitinen Date: Mon, 29 Mar 2010 15:56:58 +0300 Subject: [PATCH] Added queued versions of mapfetcher. --- Situare.pro | 12 +++-- src/map/mapfetcherqueue.cpp | 105 ++++++++++++++++++++++++++++++++++++++ src/map/mapfetcherqueue.h | 90 ++++++++++++++++++++++++++++++++ tests/testMap/testmapfetcher.cpp | 19 ++++--- 4 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 src/map/mapfetcherqueue.cpp create mode 100644 src/map/mapfetcherqueue.h diff --git a/Situare.pro b/Situare.pro index b638568..a6ae45b 100644 --- a/Situare.pro +++ b/Situare.pro @@ -3,16 +3,18 @@ # ------------------------------------------------- TARGET = Situare TEMPLATE = app -QT += network testlib +QT += network \ + testlib INCLUDEPATH += . \ src/tests/testMap/ \ src/map/ SOURCES += src/ui/mainwindow.cpp \ - src/map/mapfetcher.cpp \ + src/map/mapfetcherqueue.cpp \ src/map/mapengine.cpp \ tests/testMap/testmapfetcher.cpp -# tests/testMap/testmapengine.cpp -# src/main.cpp \ + +# tests/testMap/testmapengine.cpp +# src/main.cpp \ HEADERS += src/ui/mainwindow.h \ - src/map/mapfetcher.h \ + src/map/mapfetcherqueue.h \ src/map/mapengine.h diff --git a/src/map/mapfetcherqueue.cpp b/src/map/mapfetcherqueue.cpp new file mode 100644 index 0000000..180ce05 --- /dev/null +++ b/src/map/mapfetcherqueue.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mapfetcherqueue.h" + +static int MAX_QUEUE = 10; + +MapFetcherQueue::MapFetcherQueue(QObject *parent) + : QObject(parent) + , downloadCount(0) +{ + QNetworkDiskCache *diskCache = new QNetworkDiskCache(this); + diskCache->setCacheDirectory(QDesktopServices::storageLocation( + QDesktopServices::CacheLocation)); + m_manager.setCache(diskCache); +} + +void MapFetcherQueue::fetchMapImage(const QUrl &url) +{ + if (url.isEmpty()) + return; + + if (downloadQueue.isEmpty()) + QTimer::singleShot(0, this, SLOT(startNextDownload())); + + if (downloadQueue.length() >= MAX_QUEUE) { + qDebug() << "removed from queue"; + deleteCurrent(); + downloadQueue.dequeue(); + } + + downloadQueue.enqueue(url); + qDebug() << "fetchMapImage() " << url.path(); +} + +void MapFetcherQueue::startNextDownload() +{ + if (downloadQueue.isEmpty()) + return; + + QUrl url = downloadQueue.dequeue(); + + QNetworkRequest request(url); + request.setRawHeader("User-Agent", "Map Test"); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, + QNetworkRequest::PreferCache); + + currentDownload = m_manager.get(request); + connect(currentDownload, SIGNAL(finished()), this, SLOT(downloadFinished())); + connect(currentDownload, SIGNAL(readyRead()), this, SLOT(downloadReadyRead())); + connect(currentDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError())); +} + +void MapFetcherQueue::downloadFinished() +{ + static int counter = 0; + qDebug() << "downloadFinished(): " << counter++; + + deleteCurrent(); + startNextDownload(); +} + +void MapFetcherQueue::deleteCurrent() +{ + mutex.lock(); + if (currentDownload != NULL) + currentDownload->deleteLater(); + mutex.unlock(); +} + +void MapFetcherQueue::downloadReadyRead() +{ + qDebug() << "downloadReadyRead()" << currentDownload->url().path(); + + if (currentDownload->error()) { + qDebug() << "ERROR"; + emit error(currentDownload->errorString()); + } + else { + QImage image; + QUrl url = currentDownload->url(); + if (!image.load(currentDownload, 0)) + image = QImage(); + + emit mapImageReceived(url, QPixmap::fromImage(image)); + } +} + +void MapFetcherQueue::networkError() +{ + emit error(currentDownload->errorString()); +} + +MapFetcherQueue::~MapFetcherQueue() +{ + +} diff --git a/src/map/mapfetcherqueue.h b/src/map/mapfetcherqueue.h new file mode 100644 index 0000000..9b33d65 --- /dev/null +++ b/src/map/mapfetcherqueue.h @@ -0,0 +1,90 @@ +#ifndef MAPFETCHERQUEUE_H +#define MAPFETCHERQUEUE_H + +#include +#include + +class QNetworkReply; +class QUrl; +class QMutex; + +#include "mapfetcher.h" + +/** +* @brief MapFetcher handles requests to get map tiles. +* +* +* +* @class MapFetcher mapfetcher.h "map/mapfetcher.h" +*/ +class MapFetcherQueue : public QObject +{ + Q_OBJECT + +public: + /** + * @brief Constructor for MapFetcher. + * + * @fn MapFetcher + * @param parent parent object + */ + MapFetcherQueue(QObject *parent = 0); + + ~MapFetcherQueue(); + + /** + * @brief Fetch image from given URL. + * + * @fn fetchMapImage + * @param url URL to image + */ + void fetchMapImage(const QUrl &url); + + void deleteCurrent(); + +signals: + /** + * @brief Signal which is emitted when a map tile + * is received from the server and loaded to pixmap. + * + * @fn mapImageReceived + * @param url URL to image + * @param image image pixmap + */ + void mapImageReceived(const QUrl &url, const QPixmap &image); + + /** + * @brief Signal which is emitted when there is error + * in network reply. + * + * @fn error + * @param message error message + */ + void error(const QString &message); + +private slots: + /** + * @brief This slot is called when network manager has finished + * the download. + * + * @fn downloadFinished + * @param reply + */ + void downloadFinished(); + + void startNextDownload(); + void downloadReadyRead(); + void networkError(); + + +private: + QNetworkAccessManager m_manager; + QQueue downloadQueue; + QNetworkReply *currentDownload; + QTime downloadTime; + QMutex mutex; + + int downloadCount; +}; + +#endif diff --git a/tests/testMap/testmapfetcher.cpp b/tests/testMap/testmapfetcher.cpp index bd226df..4ed9ac7 100644 --- a/tests/testMap/testmapfetcher.cpp +++ b/tests/testMap/testmapfetcher.cpp @@ -2,7 +2,7 @@ #include #include -#include "../map/mapfetcher.h" +#include "mapfetcherqueue.h" class TestMapFetcher : public QObject { @@ -16,12 +16,12 @@ private slots: private: - MapFetcher *mapFetcher; + MapFetcherQueue *mapFetcher; }; TestMapFetcher::TestMapFetcher() { - mapFetcher = new MapFetcher(); + mapFetcher = new MapFetcherQueue(); } void TestMapFetcher::testFetchImage() @@ -39,7 +39,7 @@ void TestMapFetcher::testSignals() QVERIFY(imageReceivedSpy.isValid()); //Incorrect URL - QUrl url1("http://tile.openstreetmap.org/7/63/22.gi"); + /*QUrl url1("http://tile.openstreetmap.org/7/63/22.gi"); mapFetcher->fetchMapImage(url1); QTest::qWait(1000); QCOMPARE(imageReceivedErrorSpy.count(), 1); @@ -52,12 +52,15 @@ void TestMapFetcher::testSignals() QTest::qWait(1000); QCOMPARE(imageReceivedSpy.count(), 1); QList signalArgs2 = imageReceivedSpy.takeFirst(); - QCOMPARE(url2, signalArgs2.at(0).toUrl()); + QCOMPARE(url2, signalArgs2.at(0).toUrl());*/ - //10 requests - qDebug() << "Start:" << QTime::currentTime().toString("hh:mm:ss:zzz"); + //20 requests immediately for (int i = 0; i < 10; ++i) { - QUrl url(QString("http://tile.openstreetmap.org/7/63/4%1.png").arg(i)); + QUrl url(QString("http://tile.openstreetmap.org/7/63/2%1.png").arg(i)); + mapFetcher->fetchMapImage(url); + } + for (int i = 0; i < 10; ++i) { + QUrl url(QString("http://tile.openstreetmap.org/7/63/3%1.png").arg(i)); mapFetcher->fetchMapImage(url); } QTest::qWait(2000); -- 1.7.9.5