diff --git a/CMakeLists.txt b/CMakeLists.txt index 7740c65..0991b69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default project(QAD) set(QAD_MAJOR 2) set(QAD_MINOR 32) -set(QAD_REVISION 0) +set(QAD_REVISION 1) set(QAD_SUFFIX ) set(QAD_COMPANY SHS) set(QAD_DOMAIN org.SHS) diff --git a/libs/map/mapview.cpp b/libs/map/mapview.cpp index 2406ddb..d07a0e9 100644 --- a/libs/map/mapview.cpp +++ b/libs/map/mapview.cpp @@ -1,8 +1,8 @@ #include "mapview.h" -#include "osm_downloader_p.h" +#include "mapview_tile_cache_p.h" +#include "mapview_tile_downloader_p.h" #include "osm_math_p.h" -#include "osm_tile_cache_p.h" #include "qad_types.h" #include @@ -18,10 +18,10 @@ const int tileSize = 256; MapView::MapView(QWidget * parent): QWidget(parent) { - downloader = new OSMDownloader(this); - cache = new OSMTileCache(this); + downloader = new MapViewTileDownloader(this); + cache = new MapViewTileCache(this); setMouseTracking(true); - connect(cache, &OSMTileCache::tileReady, this, [this]() { + connect(cache, &MapViewTileCache::tileReady, this, [this]() { if (!is_downloading) drawBackground(); }); int size = 16; @@ -92,16 +92,34 @@ void MapView::setCachePath(const QString & p) { } +void MapView::setOfflineMode(bool yes) { + is_offline = yes; + cache->setOfflineMode(yes); +} + + void MapView::setTileObsoleteTime(int secs) { cache->setTileObsoleteTime(secs); } -void collectDownloadIndeces(OSMTileCache * cache, - QQueue & indeces, - OSM::TileIndex index, - int target_zoom_level, - bool only_new) { +void MapView::setTileProvider(MapViewTileProviderBase * p) { + cache->clearCache(); + downloader->setTileProvider(p); + drawBackground(); +} + + +MapViewTileProviderBase * MapView::tileProvider() const { + return downloader->tileProvider(); +} + + +void collectDownloadIndeces(MapViewTileCache * cache, + QQueue & indeces, + OSM::TileIndex index, + int target_zoom_level, + bool only_new) { if (only_new) { if (!cache->isTileFileExists(index)) indeces << index; } else @@ -118,7 +136,7 @@ void collectDownloadIndeces(OSMTileCache * cache, } -void MapView::downloadCurrentView(int target_zoom_level, bool only_new) { +void MapView::downloadCurrentView(int target_zoom_level, bool only_new, int parallel) { int sx = qMax(0, (int)floor(view_rect.left() * tiles_side)); int sy = qMax(0, (int)floor(view_rect.top() * tiles_side)); int ex = qMin(tiles_side, (int)ceil(view_rect.right() * tiles_side)); @@ -141,7 +159,7 @@ void MapView::downloadCurrentView(int target_zoom_level, bool only_new) { std::atomic_int value(0); auto conn = connect( downloader, - &OSMDownloader::tileDone, + &MapViewTileDownloader::tileDone, this, [this, &dialog, &indeces, &value]() { // qDebug() << "done"; @@ -160,8 +178,10 @@ void MapView::downloadCurrentView(int target_zoom_level, bool only_new) { downloader->clearQueue(); }); is_downloading = true; - for (int i = 0; i < 1; ++i) + for (int i = 0; i < parallel; ++i) { + if (indeces.isEmpty()) break; downloader->queueTile(indeces.dequeue()); + } // dialog.exec(); dialog.setModal(true); dialog.show(); @@ -264,11 +284,13 @@ void MapView::drawBackground() { QPointF offset = view_rect.topLeft() * mins * scale_; p.setRenderHint(QPainter::SmoothPixmapTransform); p.setPen(Qt::white); + QSizeF tile_size(tileSize, tileSize); + if (downloader->tileProvider()) tile_size = downloader->tileProvider()->tileSize(); for (int ix = sx; ix < ex; ++ix) { for (int iy = sy; iy < ey; ++iy) { QRectF r((ix)*ts, (iy)*ts, ts, ts); r.translate(-offset); - QRectF px_rct(QPointF(), QSizeF(tileSize, tileSize)); + QRectF px_rct(QPointF(), tile_size /*QSizeF(tileSize, tileSize)*/); auto tile = cache->getTile((OSM::TileIndex){zoom_level, ix, iy}, px_rct); if (!tile.isEmpty()) { p.drawPixmap(r, tile.pixmap, px_rct); diff --git a/libs/map/mapview.h b/libs/map/mapview.h index b2c28d7..86071cf 100644 --- a/libs/map/mapview.h +++ b/libs/map/mapview.h @@ -1,7 +1,7 @@ /* QAD - Qt ADvanced - Ivan Pelipenko peri4ko@yandex.ru + Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -28,16 +28,18 @@ #include -class OSMDownloader; -class OSMTileCache; +class MapViewTileDownloader; +class MapViewTileProviderBase; +class MapViewTileCache; class QAD_MAP_EXPORT MapView: public QWidget { Q_OBJECT Q_PROPERTY(QPointF center READ center WRITE setCenter) Q_PROPERTY(double zoom READ getZoom WRITE setZoom) + Q_PROPERTY(bool offlineMode READ isOfflineMode WRITE setOfflineMode) - friend class OSMDownloader; - friend class OSMTileCache; + friend class MapViewTileDownloader; + friend class MapViewTileCache; friend class MapItemBase; public: @@ -61,9 +63,14 @@ public: QString cachePath() const; void setCachePath(const QString & p); - void setTileObsoleteTime(int secs); + bool isOfflineMode() const { return is_offline; } + void setOfflineMode(bool yes); - void downloadCurrentView(int target_zoom_level = 17, bool only_new = true); + void setTileObsoleteTime(int secs); + void setTileProvider(MapViewTileProviderBase * p); + MapViewTileProviderBase * tileProvider() const; + + void downloadCurrentView(int target_zoom_level = 17, bool only_new = true, int parallel = 1); protected: QSize sizeHint() const override { return QSize(200, 200); } @@ -89,17 +96,17 @@ private: QPointF mapToNorm(QPoint screen) const; QPoint mapFromNorm(QPointF norm) const; - OSMDownloader * downloader = nullptr; - OSMTileCache * cache = nullptr; - MapItemBase * hover = nullptr; - QPointF center_ = QPointF(0.5, 0.5); - QPointF last_click_coord = center_; + MapViewTileDownloader * downloader = nullptr; + MapViewTileCache * cache = nullptr; + MapItemBase * hover = nullptr; + QPointF center_ = QPointF(0.5, 0.5); + QPointF last_click_coord = center_; QPoint press_point, zoom_anchor; QPixmap background; QRectF view_rect; QVector items_; QBrush brush_tr; - bool is_pan = false, is_downloading = false; + bool is_pan = false, is_downloading = false, is_offline = false; double zoom_ = 1., scale_ = 1., px2m = 1.; int zoom_level = 0, tiles_side = 1, max_level = 19; diff --git a/libs/map/osm_tile_cache.cpp b/libs/map/mapview_tile_cache.cpp similarity index 68% rename from libs/map/osm_tile_cache.cpp rename to libs/map/mapview_tile_cache.cpp index 1cfa18c..f40a44f 100644 --- a/libs/map/osm_tile_cache.cpp +++ b/libs/map/mapview_tile_cache.cpp @@ -1,27 +1,27 @@ #include "mapview.h" -#include "osm_downloader_p.h" -#include "osm_tile_cache_p.h" +#include "mapview_tile_cache_p.h" +#include "mapview_tile_downloader_p.h" #include "qad_locations.h" -OSMTileCache::OSMTileCache(MapView * p): QThread() { +MapViewTileCache::MapViewTileCache(MapView * p): QThread() { qRegisterMetaType(); qRegisterMetaType(); parent = p; - setCacheRoot(QAD::userPath(QAD::ltCache, "map_osm") + "/"); + setCacheRoot(QAD::userPath(QAD::ltCache, "mapview") + "/"); setAdditionalCacheSize(64); start(); } -OSMTileCache::~OSMTileCache() { +MapViewTileCache::~MapViewTileCache() { requestInterruption(); cond.wakeAll(); wait(); } -void OSMTileCache::tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap) { +void MapViewTileCache::tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap) { auto * tile = new OSM::TilePixmap(); tile->index = index; tile->pixmap = pixmap; @@ -29,10 +29,10 @@ void OSMTileCache::tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap) } -OSM::TilePixmap OSMTileCache::getTile(OSM::TileIndex index, QRectF & rect_src) { +OSM::TilePixmap MapViewTileCache::getTile(OSM::TileIndex index, QRectF & rect_src) { OSM::TilePixmap ret = getTileFromCache(index); if (ret.isEmpty() || ret.obsolete) { - parent->downloader->queueTile(index); + if (!is_offline) parent->downloader->queueTile(index); } if (ret.isEmpty()) { QVector offsets; @@ -56,7 +56,12 @@ OSM::TilePixmap OSMTileCache::getTile(OSM::TileIndex index, QRectF & rect_src) { } -bool OSMTileCache::isTileFileExists(OSM::TileIndex index) const { +void MapViewTileCache::clearCache() { + tile_cache.clear(); +} + + +bool MapViewTileCache::isTileFileExists(OSM::TileIndex index) const { QString hashdir = index.cacheDir(); if (!cache_dir.exists(hashdir)) return false; QString hashname = hashdir + "/" + index.hashName(); @@ -64,15 +69,29 @@ bool OSMTileCache::isTileFileExists(OSM::TileIndex index) const { } -void OSMTileCache::setCacheRoot(const QString & p) { +void MapViewTileCache::setCacheRoot(const QString & p) { cache_root = p; + tileProviderChanged(); +} + + +void MapViewTileCache::tileProviderChanged() { cache_dir.setPath(cache_root); - qDebug() << "[OSMTileCache] Cache dir" << cache_root; + auto * provider = parent->downloader->provider; + if (provider) { + cache_dir.setPath(cache_root + "/" + provider->name()); + } + qDebug() << "[MapViewTileCache] Cache dir" << cache_dir.absolutePath(); if (!cache_dir.exists()) cache_dir.mkpath("."); } -OSM::TilePixmap OSMTileCache::getTileFromCache(OSM::TileIndex index) { +void MapViewTileCache::setOfflineMode(bool yes) { + is_offline = yes; +} + + +OSM::TilePixmap MapViewTileCache::getTileFromCache(OSM::TileIndex index) { OSM::TilePixmap ret; ret.index = index; auto * tile = tile_cache[index.hash()]; @@ -101,12 +120,12 @@ OSM::TilePixmap OSMTileCache::getTileFromCache(OSM::TileIndex index) { } -void OSMTileCache::updateCacheSize() { +void MapViewTileCache::updateCacheSize() { tile_cache.setMaxCost(fixed_size_b + add_size_b); } -void OSMTileCache::saveTile(OSM::TilePixmap * tile) { +void MapViewTileCache::saveTile(OSM::TilePixmap * tile) { tile_cache.insert(tile->index.hash(), tile, tile->pixmapBytes()); emit tileReady(*tile); cond_mutex.lock(); @@ -118,7 +137,7 @@ void OSMTileCache::saveTile(OSM::TilePixmap * tile) { } -void OSMTileCache::writeToDisk(const OSM::TilePixmap & tile) { +void MapViewTileCache::writeToDisk(const OSM::TilePixmap & tile) { QString hashdir = tile.index.cacheDir(); if (!cache_dir.exists(hashdir)) cache_dir.mkdir(hashdir); QFile f(cache_dir.absoluteFilePath(hashdir + "/" + tile.index.hashName())); @@ -128,7 +147,7 @@ void OSMTileCache::writeToDisk(const OSM::TilePixmap & tile) { } -void OSMTileCache::run() { +void MapViewTileCache::run() { while (!isInterruptionRequested()) { OSM::TilePixmap tile; cond_mutex.lock(); diff --git a/libs/map/osm_tile_cache_p.h b/libs/map/mapview_tile_cache_p.h similarity index 86% rename from libs/map/osm_tile_cache_p.h rename to libs/map/mapview_tile_cache_p.h index ab38841..88e9107 100644 --- a/libs/map/osm_tile_cache_p.h +++ b/libs/map/mapview_tile_cache_p.h @@ -1,7 +1,7 @@ /* QAD - Qt ADvanced - Ivan Pelipenko peri4ko@yandex.ru + Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef osm_tile_cache_h -#define osm_tile_cache_h +#ifndef mapview_tile_cache_h +#define mapview_tile_cache_h #include "osm_types_p.h" @@ -31,12 +31,12 @@ class MapView; -class OSMTileCache: public QThread { +class MapViewTileCache: public QThread { Q_OBJECT public: - explicit OSMTileCache(MapView * p); - ~OSMTileCache(); + explicit MapViewTileCache(MapView * p); + ~MapViewTileCache(); void setMinimumCacheSize(int bytes) { fixed_size_b = bytes; @@ -50,12 +50,16 @@ public: void tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap); OSM::TilePixmap getTile(OSM::TileIndex index, QRectF & rect_src); + void clearCache(); bool isTileFileExists(OSM::TileIndex index) const; QString cacheRoot() const { return cache_root; } void setCacheRoot(const QString & p); + void tileProviderChanged(); + void setOfflineMode(bool yes); + private: OSM::TilePixmap getTileFromCache(OSM::TileIndex index); void updateCacheSize(); @@ -70,6 +74,7 @@ private: QMutex cond_mutex; int secs_obsolete = -1; int fixed_size_b = 0, add_size_b = 0; + bool is_offline = false; QQueue queue; QCache tile_cache; diff --git a/libs/map/mapview_tile_downloader.cpp b/libs/map/mapview_tile_downloader.cpp new file mode 100644 index 0000000..bc60e71 --- /dev/null +++ b/libs/map/mapview_tile_downloader.cpp @@ -0,0 +1,90 @@ +#include "mapview.h" +#include "mapview_tile_cache_p.h" +#include "mapview_tile_downloader_p.h" + + +MapViewTileDownloader::MapViewTileDownloader(MapView * p): QThread() { + qRegisterMetaType(); + parent = p; + start(); +} + + +MapViewTileDownloader::~MapViewTileDownloader() { + requestInterruption(); + cond.wakeAll(); + wait(); + if (provider) provider->deleteLater(); +} + + +bool MapViewTileDownloader::queueTile(OSM::TileIndex index, bool force) { + // auto hash = tile.hash(); + bool ret = false; + cond_mutex.lock(); + if ((!queue.contains(index) && !in_progress.contains(index.hash())) || force) { + queue.enqueue(index); + cond.wakeOne(); + ret = true; + } + cond_mutex.unlock(); + return ret; +} + + +void MapViewTileDownloader::queueTiles(QList indeces) { + cond_mutex.lock(); + queue << indeces; + cond.wakeOne(); + cond_mutex.unlock(); +} + + +void MapViewTileDownloader::clearQueue() { + cond_mutex.lock(); + queue.clear(); + cond_mutex.unlock(); +} + + +void MapViewTileDownloader::setTileProvider(MapViewTileProviderBase * p) { + if (provider) { + disconnect(provider, &MapViewTileProviderBase::tileReady, this, &MapViewTileDownloader::tileReady); + provider->deleteLater(); + } + provider = p; + if (provider) { + connect(provider, &MapViewTileProviderBase::tileReady, this, &MapViewTileDownloader::tileReady); + } + parent->cache->tileProviderChanged(); +} + + +void MapViewTileDownloader::requestTile(OSM::TileIndex index) { + if (!provider) return; + provider->requestTile(index); +} + + +void MapViewTileDownloader::tileReady(OSM::TileIndex index, QPixmap pm) { + if (!pm.isNull()) parent->cache->tileDownloaded(index, pm); + cond_mutex.lock(); + in_progress.remove(index.hash()); + cond_mutex.unlock(); + emit tileDone(); +} + + +void MapViewTileDownloader::run() { + while (!isInterruptionRequested()) { + cond_mutex.lock(); + if (queue.isEmpty()) + cond.wait(&cond_mutex); + else { + auto t = queue.dequeue(); + in_progress.insert(t.hash()); + QMetaObject::invokeMethod(parent, [this, t]() { requestTile(t); }, Qt::QueuedConnection); + } + cond_mutex.unlock(); + } +} diff --git a/libs/map/osm_downloader_p.h b/libs/map/mapview_tile_downloader_p.h similarity index 72% rename from libs/map/osm_downloader_p.h rename to libs/map/mapview_tile_downloader_p.h index bc9b0bc..0b0b4af 100644 --- a/libs/map/osm_downloader_p.h +++ b/libs/map/mapview_tile_downloader_p.h @@ -1,7 +1,7 @@ /* QAD - Qt ADvanced - Ivan Pelipenko peri4ko@yandex.ru + Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -17,9 +17,10 @@ along with this program. If not, see . */ -#ifndef osm_downloader_h -#define osm_downloader_h +#ifndef mapview_tile_downloader_h +#define mapview_tile_downloader_h +#include "mapview_tile_provider_base.h" #include "osm_types_p.h" #include @@ -33,24 +34,28 @@ class MapView; -class OSMDownloader: public QThread { +class MapViewTileDownloader: public QThread { Q_OBJECT + friend class MapViewTileCache; + public: - explicit OSMDownloader(MapView * p); - ~OSMDownloader(); + explicit MapViewTileDownloader(MapView * p); + ~MapViewTileDownloader(); bool queueTile(OSM::TileIndex index, bool force = false); void queueTiles(QList indeces); void clearQueue(); + void setTileProvider(MapViewTileProviderBase * p); + MapViewTileProviderBase * tileProvider() const { return provider; } + private: void run() override; void requestTile(OSM::TileIndex index); MapView * parent; - QNetworkAccessManager * nam = nullptr; - QString provider; + MapViewTileProviderBase * provider = nullptr; QWaitCondition cond; QMutex cond_mutex; QQueue queue; @@ -59,6 +64,7 @@ private: public slots: private slots: + void tileReady(OSM::TileIndex index, QPixmap pm); signals: void tileDone(); diff --git a/libs/map/mapview_tile_provider_base.cpp b/libs/map/mapview_tile_provider_base.cpp new file mode 100644 index 0000000..51cda86 --- /dev/null +++ b/libs/map/mapview_tile_provider_base.cpp @@ -0,0 +1,13 @@ +#include "mapview_tile_provider_base.h" + + +void MapViewTileProviderBase::setParameters(const PIValueTree & vt) { + parameters.applyValues(vt); + applyParameters(); +} + + +void MapViewTileProviderBase::initParameters(const PIValueTree & vt) { + parameters = vt; + applyParameters(); +} diff --git a/libs/map/mapview_tile_provider_base.h b/libs/map/mapview_tile_provider_base.h new file mode 100644 index 0000000..b0e30f3 --- /dev/null +++ b/libs/map/mapview_tile_provider_base.h @@ -0,0 +1,57 @@ +/* + QAD - Qt ADvanced + + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef mapview_tile_provider_base_h +#define mapview_tile_provider_base_h + +#include "osm_types_p.h" +#include "qad_map_export.h" + +#include +#include + + +class QAD_MAP_EXPORT MapViewTileProviderBase: public QObject { + Q_OBJECT + +public: + MapViewTileProviderBase() {} + virtual ~MapViewTileProviderBase() {} + + const PIValueTree & getParameters() const { return parameters; } + void setParameters(const PIValueTree & vt); + + virtual QString name() const = 0; + virtual bool requestTile(OSM::TileIndex index) = 0; + virtual QSize tileSize() = 0; + +protected: + void initParameters(const PIValueTree & vt); + + virtual void applyParameters() {} + +private: + PIValueTree parameters; + +signals: + void tileReady(OSM::TileIndex index, QPixmap pm); +}; + + +#endif diff --git a/libs/map/mapview_tile_provider_maptiler.cpp b/libs/map/mapview_tile_provider_maptiler.cpp new file mode 100644 index 0000000..e7259bb --- /dev/null +++ b/libs/map/mapview_tile_provider_maptiler.cpp @@ -0,0 +1,65 @@ +#include "mapview_tile_provider_maptiler.h" + +#include +#include +#include +#include + + +MapViewTileProvider_MapTiler::MapViewTileProvider_MapTiler() { + nam = new QNetworkAccessManager(); + PIValueTree p; + p.addChild(PIValueTree("url", "https://api.maptiler.com/maps")); + p.addChild(PIValueTree("key", "")); + p.addChild(PIValueTree("tileset", "")); + initParameters(p); +} + + +MapViewTileProvider_MapTiler::~MapViewTileProvider_MapTiler() { + piDeleteSafety(nam); +} + + +QString MapViewTileProvider_MapTiler::name() const { + static QString ret = "MapTiler"; + return ret; +} + + +bool MapViewTileProvider_MapTiler::requestTile(OSM::TileIndex index) { + QNetworkRequest req(url + QString("/%1/%2/%3/%4.jpg?key=%5").arg(tileset).arg(index.z).arg(index.x).arg(index.y).arg(key)); + req.setHeader(QNetworkRequest::UserAgentHeader, "Qt/5"); + auto * r = nam->get(req); + if (!r) return false; + // qDebug() << "Reqst:" << index.z << index.x << index.y; + connect(r, &QNetworkReply::finished, this, [this, r, index]() { + r->deleteLater(); + QPixmap tim; + if (r->error() != QNetworkReply::NoError) { + qDebug() << "Retry:" << index.z << index.x << index.y << r->error(); + QTimer::singleShot(500, this, [this, index] { requestTile(index); }); + return; + } else { + QByteArray data = r->readAll(); + if (!data.isEmpty()) { + tim.loadFromData(data, "jpg"); + // qDebug() << "Ready:" << index.z << index.x << index.y; + } + } + tileReady(index, tim); + }); + return true; +} + + +QSize MapViewTileProvider_MapTiler::tileSize() { + return {512, 512}; +} + + +void MapViewTileProvider_MapTiler::applyParameters() { + url = PI2QString(getParameters().childValue("url").toString()); + key = PI2QString(getParameters().childValue("key").toString()); + tileset = PI2QString(getParameters().childValue("tileset").toString()); +} diff --git a/libs/map/mapview_tile_provider_maptiler.h b/libs/map/mapview_tile_provider_maptiler.h new file mode 100644 index 0000000..be61854 --- /dev/null +++ b/libs/map/mapview_tile_provider_maptiler.h @@ -0,0 +1,48 @@ +/* + QAD - Qt ADvanced + + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef mapview_tile_provider_maptiler_h +#define mapview_tile_provider_maptiler_h + +#include "mapview_tile_provider_base.h" + +#include + + +class QAD_MAP_EXPORT MapViewTileProvider_MapTiler: public MapViewTileProviderBase { + Q_OBJECT + +public: + MapViewTileProvider_MapTiler(); + ~MapViewTileProvider_MapTiler(); + + QString name() const override; + bool requestTile(OSM::TileIndex index) override; + QSize tileSize() override; + +protected: + void applyParameters() override; + +private: + QNetworkAccessManager * nam = nullptr; + QString url, key, tileset; +}; + + +#endif diff --git a/libs/map/mapview_tile_provider_osm.cpp b/libs/map/mapview_tile_provider_osm.cpp new file mode 100644 index 0000000..bb5c4d2 --- /dev/null +++ b/libs/map/mapview_tile_provider_osm.cpp @@ -0,0 +1,56 @@ +#include "mapview_tile_provider_osm.h" + +#include +#include +#include + + +MapViewTileProvider_OSM::MapViewTileProvider_OSM() { + nam = new QNetworkAccessManager(); + PIValueTree p; + p.addChild(PIValueTree("url", "http://tile.openstreetmap.org")); + initParameters(p); +} + + +MapViewTileProvider_OSM::~MapViewTileProvider_OSM() { + piDeleteSafety(nam); +} + + +QString MapViewTileProvider_OSM::name() const { + static QString ret = "OSM"; + return ret; +} + + +bool MapViewTileProvider_OSM::requestTile(OSM::TileIndex index) { + QNetworkRequest req(url + QString("/%1/%2/%3.png").arg(index.z).arg(index.x).arg(index.y)); + req.setHeader(QNetworkRequest::UserAgentHeader, "Qt/5"); + auto * r = nam->get(req); + if (!r) return false; + connect(r, &QNetworkReply::finished, this, [this, r, index]() { + r->deleteLater(); + QPixmap tim; + if (r->error() != QNetworkReply::NoError) { + qDebug() << "Error:" << r->error(); + } else { + QByteArray data = r->readAll(); + if (!data.isEmpty()) { + tim.loadFromData(data, "png"); + } + } + emit tileReady(index, tim); + }); + return true; +} + + +QSize MapViewTileProvider_OSM::tileSize() { + return {256, 256}; +} + + +void MapViewTileProvider_OSM::applyParameters() { + url = PI2QString(getParameters().childValue("url").toString()); +} diff --git a/libs/map/mapview_tile_provider_osm.h b/libs/map/mapview_tile_provider_osm.h new file mode 100644 index 0000000..9fcd579 --- /dev/null +++ b/libs/map/mapview_tile_provider_osm.h @@ -0,0 +1,48 @@ +/* + QAD - Qt ADvanced + + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef mapview_tile_provider_osm_h +#define mapview_tile_provider_osm_h + +#include "mapview_tile_provider_base.h" + +#include + + +class QAD_MAP_EXPORT MapViewTileProvider_OSM: public MapViewTileProviderBase { + Q_OBJECT + +public: + MapViewTileProvider_OSM(); + ~MapViewTileProvider_OSM(); + + QString name() const override; + bool requestTile(OSM::TileIndex index) override; + QSize tileSize() override; + +protected: + void applyParameters() override; + +private: + QNetworkAccessManager * nam = nullptr; + QString url; +}; + + +#endif diff --git a/libs/map/osm_downloader.cpp b/libs/map/osm_downloader.cpp deleted file mode 100644 index f7fab2b..0000000 --- a/libs/map/osm_downloader.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "mapview.h" -#include "osm_downloader_p.h" -#include "osm_tile_cache_p.h" - - -OSMDownloader::OSMDownloader(MapView * p): QThread() { - qRegisterMetaType(); - nam = new QNetworkAccessManager(); - parent = p; - provider = "http://tile.openstreetmap.org"; - start(); -} - - -OSMDownloader::~OSMDownloader() { - requestInterruption(); - cond.wakeAll(); - wait(); - delete nam; -} - - -bool OSMDownloader::queueTile(OSM::TileIndex index, bool force) { - // auto hash = tile.hash(); - bool ret = false; - cond_mutex.lock(); - if ((!queue.contains(index) && !in_progress.contains(index.hash())) || force) { - queue.enqueue(index); - cond.wakeOne(); - ret = true; - } - cond_mutex.unlock(); - return ret; -} - - -void OSMDownloader::queueTiles(QList indeces) { - cond_mutex.lock(); - queue << indeces; - cond.wakeOne(); - cond_mutex.unlock(); -} - - -void OSMDownloader::clearQueue() { - cond_mutex.lock(); - queue.clear(); - cond_mutex.unlock(); -} - - -void OSMDownloader::requestTile(OSM::TileIndex index) { - QNetworkRequest req(provider + QString("/%1/%2/%3.png").arg(index.z).arg(index.x).arg(index.y)); - req.setHeader(QNetworkRequest::UserAgentHeader, "Qt/5"); - auto * r = nam->get(req); - if (!r) return; - connect(r, &QNetworkReply::finished, this, [this, r, index]() { - r->deleteLater(); - if (r->error() != QNetworkReply::NoError) { - qDebug() << "Error:" << r->error(); - } else { - QByteArray data = r->readAll(); - if (!data.isEmpty()) { - QPixmap tim; - tim.loadFromData(data, "png"); - if (!tim.isNull()) parent->cache->tileDownloaded(index, tim); - } - } - cond_mutex.lock(); - in_progress.remove(index.hash()); - cond_mutex.unlock(); - emit tileDone(); - }); -} - - -void OSMDownloader::run() { - while (!isInterruptionRequested()) { - cond_mutex.lock(); - if (queue.isEmpty()) - cond.wait(&cond_mutex); - else { - auto t = queue.dequeue(); - in_progress.insert(t.hash()); - QMetaObject::invokeMethod( - parent, - [this, t]() { requestTile(t); }, - Qt::QueuedConnection); - } - cond_mutex.unlock(); - } -}