Browse Source

Dealing with lack of Internet connectivity.

QGC4.4
Gus Grubba 8 years ago
parent
commit
23cb5e1b95
  1. 18
      src/QtLocationPlugin/QGCMapEngine.cpp
  2. 4
      src/QtLocationPlugin/QGCMapEngine.h
  3. 13
      src/QtLocationPlugin/QGCMapEngineData.h
  4. 11
      src/QtLocationPlugin/QGCMapTileSet.cpp
  5. 39
      src/QtLocationPlugin/QGCTileCacheWorker.cpp
  6. 2
      src/QtLocationPlugin/QGCTileCacheWorker.h
  7. 105
      src/QtLocationPlugin/QGeoMapReplyQGC.cpp
  8. 9
      src/QtLocationPlugin/QGeoMapReplyQGC.h
  9. 13
      src/QtLocationPlugin/QGeoTileFetcherQGC.cpp
  10. 4
      src/QtLocationPlugin/QGeoTileFetcherQGC.h

18
src/QtLocationPlugin/QGCMapEngine.cpp

@ -130,11 +130,13 @@ QGCMapEngine::QGCMapEngine() @@ -130,11 +130,13 @@ QGCMapEngine::QGCMapEngine()
, _maxMemCache(0)
, _prunning(false)
, _cacheWasReset(false)
, _isInternetActive(false)
{
qRegisterMetaType<QGCMapTask::TaskType>();
qRegisterMetaType<QGCTile>();
qRegisterMetaType<QList<QGCTile*>>();
connect(&_worker, &QGCCacheWorker::updateTotals, this, &QGCMapEngine::_updateTotals);
connect(&_worker, &QGCCacheWorker::updateTotals, this, &QGCMapEngine::_updateTotals);
connect(&_worker, &QGCCacheWorker::internetStatus, this, &QGCMapEngine::_internetStatus);
}
//-----------------------------------------------------------------------------
@ -483,5 +485,19 @@ QGCCreateTileSetTask::~QGCCreateTileSetTask() @@ -483,5 +485,19 @@ QGCCreateTileSetTask::~QGCCreateTileSetTask()
delete _tileSet;
}
//-----------------------------------------------------------------------------
void
QGCMapEngine::testInternet()
{
getQGCMapEngine()->addTask(new QGCTestInternetTask());
}
//-----------------------------------------------------------------------------
void
QGCMapEngine::_internetStatus(bool active)
{
_isInternetActive = active;
}
// Resolution math: https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale

4
src/QtLocationPlugin/QGCMapEngine.h

@ -86,7 +86,9 @@ public: @@ -86,7 +86,9 @@ public:
void setMaxMemCache (quint32 size);
const QString getCachePath () { return _cachePath; }
const QString getCacheFilename () { return _cacheFile; }
void testInternet ();
bool wasCacheReset () { return _cacheWasReset; }
bool isInternetActive () { return _isInternetActive; }
UrlFactory* urlFactory () { return _urlFactory; }
@ -103,6 +105,7 @@ public: @@ -103,6 +105,7 @@ public:
private slots:
void _updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
void _pruned ();
void _internetStatus (bool active);
signals:
void updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
@ -123,6 +126,7 @@ private: @@ -123,6 +126,7 @@ private:
quint32 _maxMemCache;
bool _prunning;
bool _cacheWasReset;
bool _isInternetActive;
};
extern QGCMapEngine* getQGCMapEngine();

13
src/QtLocationPlugin/QGCMapEngineData.h

@ -110,6 +110,7 @@ public: @@ -110,6 +110,7 @@ public:
enum TaskType {
taskInit,
taskTestInternet,
taskCacheTile,
taskFetchTile,
taskFetchTileSets,
@ -129,7 +130,7 @@ public: @@ -129,7 +130,7 @@ public:
virtual TaskType type () { return _type; }
void setError(QString errorString)
void setError(QString errorString = QString())
{
emit error(_type, errorString);
}
@ -142,6 +143,16 @@ private: @@ -142,6 +143,16 @@ private:
};
//-----------------------------------------------------------------------------
class QGCTestInternetTask : public QGCMapTask
{
Q_OBJECT
public:
QGCTestInternetTask()
: QGCMapTask(QGCMapTask::taskTestInternet)
{}
};
//-----------------------------------------------------------------------------
class QGCFetchTileSetTask : public QGCMapTask
{
Q_OBJECT

11
src/QtLocationPlugin/QGCMapTileSet.cpp

@ -232,11 +232,20 @@ void QGCCachedTileSet::_prepareDownload() @@ -232,11 +232,20 @@ void QGCCachedTileSet::_prepareDownload()
_tilesToDownload.removeFirst();
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(tile->type(), tile->x(), tile->y(), tile->z(), _networkManager);
request.setAttribute(QNetworkRequest::User, tile->hash());
#if !defined(__mobile__)
QNetworkProxy proxy = _networkManager->proxy();
QNetworkProxy tProxy;
tProxy.setType(QNetworkProxy::DefaultProxy);
_networkManager->setProxy(tProxy);
#endif
QNetworkReply* reply = _networkManager->get(request);
reply->setParent(0);
connect(reply, &QNetworkReply::finished, this, &QGCCachedTileSet::_networkReplyFinished);
connect(reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), this, &QGCCachedTileSet::_networkReplyError);
_replies.insert(tile->hash(), reply);
#if !defined(__mobile__)
_networkManager->setProxy(proxy);
#endif
delete tile;
//-- Refill queue if running low
if(!_batchRequested && !_noMoreTiles && _tilesToDownload.count() < (QGCMapEngine::concurrentDownloads(_type) * 10)) {
@ -309,7 +318,7 @@ QGCCachedTileSet::_networkReplyError(QNetworkReply::NetworkError error) @@ -309,7 +318,7 @@ QGCCachedTileSet::_networkReplyError(QNetworkReply::NetworkError error)
if (!reply) {
return;
}
//-- Upodate error count
//-- Update error count
_errorCount++;
emit errorCountChanged();
//-- Get tile hash

39
src/QtLocationPlugin/QGCTileCacheWorker.cpp

@ -93,20 +93,15 @@ QGCCacheWorker::enqueueTask(QGCMapTask* task) @@ -93,20 +93,15 @@ QGCCacheWorker::enqueueTask(QGCMapTask* task)
task->deleteLater();
return false;
}
if(!_taskQueue.contains(task))
{
_mutex.lock();
_taskQueue.enqueue(task);
_mutex.unlock();
if(this->isRunning()) {
_waitc.wakeAll();
} else {
this->start(QThread::NormalPriority);
}
return true;
_mutex.lock();
_taskQueue.enqueue(task);
_mutex.unlock();
if(this->isRunning()) {
_waitc.wakeAll();
} else {
this->start(QThread::HighPriority);
}
//-- Should never happen
return false;
return true;
}
//-----------------------------------------------------------------------------
@ -158,6 +153,9 @@ QGCCacheWorker::run() @@ -158,6 +153,9 @@ QGCCacheWorker::run()
case QGCMapTask::taskReset:
_resetCacheDatabase(task);
break;
case QGCMapTask::taskTestInternet:
_testInternet();
break;
}
task->deleteLater();
//-- Check for update timeout
@ -662,6 +660,7 @@ QGCCacheWorker::_init() @@ -662,6 +660,7 @@ QGCCacheWorker::_init()
qCritical() << "Could not find suitable cache directory.";
_failed = true;
}
_testInternet();
return _failed;
}
@ -749,3 +748,17 @@ QGCCacheWorker::_createDB() @@ -749,3 +748,17 @@ QGCCacheWorker::_createDB()
}
_failed = !_valid;
}
//-----------------------------------------------------------------------------
void
QGCCacheWorker::_testInternet()
{
QTcpSocket socket;
socket.connectToHost("8.8.8.8", 53);
if (socket.waitForConnected(2500)) {
emit internetStatus(true);
return;
}
qWarning() << "No Internet Access";
emit internetStatus(false);
}

2
src/QtLocationPlugin/QGCTileCacheWorker.h

@ -59,6 +59,7 @@ private: @@ -59,6 +59,7 @@ private:
void _deleteTileSet (QGCMapTask* mtask);
void _resetCacheDatabase (QGCMapTask* mtask);
void _pruneCache (QGCMapTask* mtask);
void _testInternet ();
quint64 _findTile (const QString hash);
bool _findTileSetID (const QString name, quint64& setID);
@ -70,6 +71,7 @@ private: @@ -70,6 +71,7 @@ private:
signals:
void updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
void internetStatus (bool active);
private:
QQueue<QGCMapTask*> _taskQueue;

105
src/QtLocationPlugin/QGeoMapReplyQGC.cpp

@ -46,11 +46,14 @@ @@ -46,11 +46,14 @@
#include "QGCMapEngine.h"
#include "QGeoMapReplyQGC.h"
#include "QGeoTileFetcherQGC.h"
#include <QtLocation/private/qgeotilespec_p.h>
#include <QtNetwork/QNetworkAccessManager>
#include <QFile>
int QGeoTiledMapReplyQGC::_requestCount = 0;
//-----------------------------------------------------------------------------
QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager, const QNetworkRequest &request, const QGeoTileSpec &spec, QObject *parent)
: QGeoTiledMapReply(spec, parent)
@ -59,15 +62,7 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager @@ -59,15 +62,7 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager
, _networkManager(networkManager)
{
if(_request.url().isEmpty()) {
if(!_badMapBox.size()) {
QFile b(":/res/notile.png");
if(b.open(QFile::ReadOnly))
_badMapBox = b.readAll();
}
setMapImageData(_badMapBox);
setMapImageFormat("png");
setFinished(true);
setCached(false);
_returnBadTile();
} else {
QGCFetchTileTask* task = getQGCMapEngine()->createFetchTileTask((UrlFactory::MapType)spec.mapId(), spec.x(), spec.y(), spec.zoom());
connect(task, &QGCFetchTileTask::tileFetched, this, &QGeoTiledMapReplyQGC::cacheReply);
@ -79,30 +74,48 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager @@ -79,30 +74,48 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager
//-----------------------------------------------------------------------------
QGeoTiledMapReplyQGC::~QGeoTiledMapReplyQGC()
{
_clearReply();
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::_clearReply()
{
if (_reply) {
_reply->deleteLater();
_reply = 0;
_requestCount--;
}
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::abort()
QGeoTiledMapReplyQGC::_returnBadTile()
{
if (_reply)
_reply->abort();
if(!_badMapBox.size()) {
QFile b(":/res/notile.png");
if(b.open(QFile::ReadOnly))
_badMapBox = b.readAll();
}
setMapImageData(_badMapBox);
setMapImageFormat("png");
setFinished(true);
setCached(false);
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::replyDestroyed()
QGeoTiledMapReplyQGC::abort()
{
_reply = 0;
if (_reply)
_reply->abort();
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::networkReplyFinished()
{
_timer.stop();
if (!_reply) {
return;
}
@ -117,51 +130,54 @@ QGeoTiledMapReplyQGC::networkReplyFinished() @@ -117,51 +130,54 @@ QGeoTiledMapReplyQGC::networkReplyFinished()
getQGCMapEngine()->cacheTile((UrlFactory::MapType)tileSpec().mapId(), tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format);
}
setFinished(true);
_reply->deleteLater();
_reply = 0;
_clearReply();
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::networkReplyError(QNetworkReply::NetworkError error)
{
_timer.stop();
if (!_reply) {
return;
}
if (error != QNetworkReply::OperationCanceledError) {
qWarning() << "Fetch tile error:" << _reply->errorString();
}
_reply->deleteLater();
_reply = 0;
if(!_badTile.size()) {
QFile b(":/res/notile.png");
if(b.open(QFile::ReadOnly))
_badTile = b.readAll();
}
setMapImageData(_badTile);
setMapImageFormat("png");
setFinished(true);
setCached(false);
_returnBadTile();
_clearReply();
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::cacheError(QGCMapTask::TaskType type, QString /*errorString*/)
{
if(type != QGCMapTask::taskFetchTile) {
qWarning() << "QGeoTiledMapReplyQGC::cacheError() for wrong task";
if(_networkManager->networkAccessible() < QNetworkAccessManager::Accessible || !getQGCMapEngine()->isInternetActive()) {
_returnBadTile();
} else {
if(type != QGCMapTask::taskFetchTile) {
qWarning() << "QGeoTiledMapReplyQGC::cacheError() for wrong task";
}
//-- Tile not in cache. Get it off the Internet.
#if !defined(__mobile__)
QNetworkProxy proxy = _networkManager->proxy();
QNetworkProxy tProxy;
tProxy.setType(QNetworkProxy::DefaultProxy);
_networkManager->setProxy(tProxy);
#endif
_reply = _networkManager->get(_request);
_reply->setParent(0);
connect(_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
#if !defined(__mobile__)
_networkManager->setProxy(proxy);
#endif
//- Wait for an answer up to 10 seconds
connect(&_timer, &QTimer::timeout, this, &QGeoTiledMapReplyQGC::timeout);
_timer.setSingleShot(true);
_timer.start(10000);
_requestCount++;
}
//-- Tile not in cache. Get it off the Internet.
QNetworkProxy proxy = _networkManager->proxy();
QNetworkProxy tProxy;
tProxy.setType(QNetworkProxy::DefaultProxy);
_networkManager->setProxy(tProxy);
_reply = _networkManager->get(_request);
_reply->setParent(0);
connect(_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
connect(_reply, SIGNAL(destroyed()), this, SLOT(replyDestroyed()));
_networkManager->setProxy(proxy);
}
//-----------------------------------------------------------------------------
@ -174,3 +190,12 @@ QGeoTiledMapReplyQGC::cacheReply(QGCCacheTile* tile) @@ -174,3 +190,12 @@ QGeoTiledMapReplyQGC::cacheReply(QGCCacheTile* tile)
setCached(true);
tile->deleteLater();
}
//-----------------------------------------------------------------------------
void
QGeoTiledMapReplyQGC::timeout()
{
if(_reply) {
_reply->abort();
}
}

9
src/QtLocationPlugin/QGeoMapReplyQGC.h

@ -49,6 +49,7 @@ @@ -49,6 +49,7 @@
#include <QtNetwork/QNetworkReply>
#include <QtLocation/private/qgeotiledmapreply_p.h>
#include <QTimer>
#include "QGCMapEngineData.h"
@ -61,11 +62,15 @@ public: @@ -61,11 +62,15 @@ public:
void abort();
private slots:
void replyDestroyed ();
void networkReplyFinished ();
void networkReplyError (QNetworkReply::NetworkError error);
void cacheReply (QGCCacheTile* tile);
void cacheError (QGCMapTask::TaskType type, QString errorString);
void timeout ();
private:
void _clearReply ();
void _returnBadTile ();
private:
QNetworkReply* _reply;
@ -73,6 +78,8 @@ private: @@ -73,6 +78,8 @@ private:
QNetworkAccessManager* _networkManager;
QByteArray _badMapBox;
QByteArray _badTile;
QTimer _timer;
static int _requestCount;
};
#endif // QGEOMAPREPLYQGC_H

13
src/QtLocationPlugin/QGeoTileFetcherQGC.cpp

@ -57,6 +57,10 @@ QGeoTileFetcherQGC::QGeoTileFetcherQGC(QGeoTiledMappingManagerEngine *parent) @@ -57,6 +57,10 @@ QGeoTileFetcherQGC::QGeoTileFetcherQGC(QGeoTiledMappingManagerEngine *parent)
: QGeoTileFetcher(parent)
, _networkManager(new QNetworkAccessManager(this))
{
//-- Check internet status every 30 seconds or so
connect(&_timer, &QTimer::timeout, this, &QGeoTileFetcherQGC::timeout);
_timer.setSingleShot(false);
_timer.start(30000);
}
//-----------------------------------------------------------------------------
@ -73,3 +77,12 @@ QGeoTileFetcherQGC::getTileImage(const QGeoTileSpec &spec) @@ -73,3 +77,12 @@ QGeoTileFetcherQGC::getTileImage(const QGeoTileSpec &spec)
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL((UrlFactory::MapType)spec.mapId(), spec.x(), spec.y(), spec.zoom(), _networkManager);
return new QGeoTiledMapReplyQGC(_networkManager, request, spec);
}
//-----------------------------------------------------------------------------
void
QGeoTileFetcherQGC::timeout()
{
if(!getQGCMapEngine()->isInternetActive()) {
getQGCMapEngine()->testInternet();
}
}

4
src/QtLocationPlugin/QGeoTileFetcherQGC.h

@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
#define QGEOTILEFETCHERQGC_H
#include <QtLocation/private/qgeotilefetcher_p.h>
#include <QTimer>
#include "QGCMapUrlEngine.h"
class QGeoTiledMappingManagerEngine;
@ -59,10 +60,13 @@ class QGeoTileFetcherQGC : public QGeoTileFetcher @@ -59,10 +60,13 @@ class QGeoTileFetcherQGC : public QGeoTileFetcher
public:
explicit QGeoTileFetcherQGC (QGeoTiledMappingManagerEngine *parent = 0);
~QGeoTileFetcherQGC();
public slots:
void timeout ();
private:
QGeoTiledMapReply* getTileImage (const QGeoTileSpec &spec);
private:
QNetworkAccessManager* _networkManager;
QTimer _timer;
};
#endif // QGEOTILEFETCHERQGC_H

Loading…
Cancel
Save