QAD::Map:
* add MapViewTileProviderBase - base class for tile server provider * migrate OSM to new class * add MapTiler provider * add offlineMode for MapView
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 <QGraphicsPixmapItem>
|
||||
@@ -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,12 +92,30 @@ 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,
|
||||
void MapView::setTileProvider(MapViewTileProviderBase * p) {
|
||||
cache->clearCache();
|
||||
downloader->setTileProvider(p);
|
||||
drawBackground();
|
||||
}
|
||||
|
||||
|
||||
MapViewTileProviderBase * MapView::tileProvider() const {
|
||||
return downloader->tileProvider();
|
||||
}
|
||||
|
||||
|
||||
void collectDownloadIndeces(MapViewTileCache * cache,
|
||||
QQueue<OSM::TileIndex> & indeces,
|
||||
OSM::TileIndex index,
|
||||
int target_zoom_level,
|
||||
@@ -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);
|
||||
|
||||
@@ -28,16 +28,18 @@
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
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,8 +96,8 @@ private:
|
||||
QPointF mapToNorm(QPoint screen) const;
|
||||
QPoint mapFromNorm(QPointF norm) const;
|
||||
|
||||
OSMDownloader * downloader = nullptr;
|
||||
OSMTileCache * cache = nullptr;
|
||||
MapViewTileDownloader * downloader = nullptr;
|
||||
MapViewTileCache * cache = nullptr;
|
||||
MapItemBase * hover = nullptr;
|
||||
QPointF center_ = QPointF(0.5, 0.5);
|
||||
QPointF last_click_coord = center_;
|
||||
@@ -99,7 +106,7 @@ private:
|
||||
QRectF view_rect;
|
||||
QVector<MapItemBase *> 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;
|
||||
|
||||
|
||||
@@ -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<OSM::TileIndex>();
|
||||
qRegisterMetaType<OSM::TilePixmap>();
|
||||
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<QPointF> 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();
|
||||
@@ -17,8 +17,8 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<OSM::TilePixmap> queue;
|
||||
QCache<quint64, OSM::TilePixmap> tile_cache;
|
||||
|
||||
90
libs/map/mapview_tile_downloader.cpp
Normal file
90
libs/map/mapview_tile_downloader.cpp
Normal file
@@ -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<OSM::TileIndex>();
|
||||
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<OSM::TileIndex> 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();
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,10 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <QMutex>
|
||||
@@ -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<OSM::TileIndex> 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<OSM::TileIndex> queue;
|
||||
@@ -59,6 +64,7 @@ private:
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void tileReady(OSM::TileIndex index, QPixmap pm);
|
||||
|
||||
signals:
|
||||
void tileDone();
|
||||
13
libs/map/mapview_tile_provider_base.cpp
Normal file
13
libs/map/mapview_tile_provider_base.cpp
Normal file
@@ -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();
|
||||
}
|
||||
57
libs/map/mapview_tile_provider_base.h
Normal file
57
libs/map/mapview_tile_provider_base.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef mapview_tile_provider_base_h
|
||||
#define mapview_tile_provider_base_h
|
||||
|
||||
#include "osm_types_p.h"
|
||||
#include "qad_map_export.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <pivaluetree.h>
|
||||
|
||||
|
||||
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
|
||||
65
libs/map/mapview_tile_provider_maptiler.cpp
Normal file
65
libs/map/mapview_tile_provider_maptiler.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "mapview_tile_provider_maptiler.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QTimer>
|
||||
#include <piqt.h>
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
48
libs/map/mapview_tile_provider_maptiler.h
Normal file
48
libs/map/mapview_tile_provider_maptiler.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef mapview_tile_provider_maptiler_h
|
||||
#define mapview_tile_provider_maptiler_h
|
||||
|
||||
#include "mapview_tile_provider_base.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
|
||||
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
|
||||
56
libs/map/mapview_tile_provider_osm.cpp
Normal file
56
libs/map/mapview_tile_provider_osm.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "mapview_tile_provider_osm.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <piqt.h>
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
48
libs/map/mapview_tile_provider_osm.h
Normal file
48
libs/map/mapview_tile_provider_osm.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef mapview_tile_provider_osm_h
|
||||
#define mapview_tile_provider_osm_h
|
||||
|
||||
#include "mapview_tile_provider_base.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
|
||||
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
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "mapview.h"
|
||||
#include "osm_downloader_p.h"
|
||||
#include "osm_tile_cache_p.h"
|
||||
|
||||
|
||||
OSMDownloader::OSMDownloader(MapView * p): QThread() {
|
||||
qRegisterMetaType<OSM::TileIndex>();
|
||||
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<OSM::TileIndex> 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user