Added queued versions of mapfetcher.
authorJussi Laitinen <jussi.laitinen@ixonos.com>
Mon, 29 Mar 2010 12:56:58 +0000 (15:56 +0300)
committerJussi Laitinen <jupe@l3l7588.ixonos.local>
Mon, 29 Mar 2010 12:56:58 +0000 (15:56 +0300)
Situare.pro
src/map/mapfetcherqueue.cpp [new file with mode: 0644]
src/map/mapfetcherqueue.h [new file with mode: 0644]
tests/testMap/testmapfetcher.cpp

index b638568..a6ae45b 100644 (file)
@@ -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 (file)
index 0000000..180ce05
--- /dev/null
@@ -0,0 +1,105 @@
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QUrl>
+#include <QDebug>
+#include <QPixmap>
+#include <QNetworkDiskCache>
+#include <QDesktopServices>
+#include <QTimer>
+#include <QMutex>
+
+#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 (file)
index 0000000..9b33d65
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef MAPFETCHERQUEUE_H
+#define MAPFETCHERQUEUE_H
+
+#include <QtCore>
+#include <QNetworkAccessManager>
+
+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<QUrl> downloadQueue;
+    QNetworkReply *currentDownload;
+    QTime downloadTime;
+    QMutex mutex;
+
+    int downloadCount;
+};
+
+#endif
index bd226df..4ed9ac7 100644 (file)
@@ -2,7 +2,7 @@
 #include <QUrl>
 #include <QImage>
 
-#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<QVariant> 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);