diff --git a/src/map/ENC/rastertile.cpp b/src/map/ENC/rastertile.cpp index f2ba630b..fc04d942 100644 --- a/src/map/ENC/rastertile.cpp +++ b/src/map/ENC/rastertile.cpp @@ -200,4 +200,6 @@ void RasterTile::render() //painter.setPen(Qt::red); //painter.setBrush(Qt::NoBrush); //painter.drawRect(QRect(_rect.topLeft(), _pixmap.size())); + + _valid = true; } diff --git a/src/map/ENC/rastertile.h b/src/map/ENC/rastertile.h index b99abf40..d47d9593 100644 --- a/src/map/ENC/rastertile.h +++ b/src/map/ENC/rastertile.h @@ -18,11 +18,12 @@ public: const QList &polygons, const QList &points) : _proj(proj), _transform(transform), _zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio, rect.height() * ratio), - _lines(lines), _polygons(polygons), _points(points) {} + _lines(lines), _polygons(polygons), _points(points), _valid(false) {} int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} const QPixmap &pixmap() const {return _pixmap;} + bool isValid() const {return _valid;} void render(); @@ -48,6 +49,7 @@ private: QList _lines; QList _polygons; QList _points; + bool _valid; }; } diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index 26d15431..6372f819 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -1,9 +1,7 @@ #include #include -#include #include "common/range.h" #include "common/wgs84.h" -#include "ENC/rastertile.h" #include "rectd.h" #include "pcs.h" #include "encmap.h" @@ -58,6 +56,8 @@ int ENCMap::zoomFit(const QSize &size, const RectC &rect) int ENCMap::zoomIn() { + cancelJobs(); + _zoom = qMin(_zoom + 1, ZOOMS.max()); updateTransform(); return _zoom; @@ -65,6 +65,8 @@ int ENCMap::zoomIn() int ENCMap::zoomOut() { + cancelJobs(); + _zoom = qMax(_zoom - 1, ZOOMS.min()); updateTransform(); return _zoom; @@ -96,6 +98,55 @@ void ENCMap::updateTransform() _transform.proj2img(prect.bottomRight())); } +bool ENCMap::isRunning(int zoom, const QPoint &xy) const +{ + for (int i = 0; i < _jobs.size(); i++) { + const QList &tiles = _jobs.at(i)->tiles(); + for (int j = 0; j < tiles.size(); j++) { + const ENC::RasterTile &mt = tiles.at(j); + if (mt.zoom() == zoom && mt.xy() == xy) + return true; + } + } + + return false; +} + +void ENCMap::runJob(ENCMapJob *job) +{ + _jobs.append(job); + + connect(job, &ENCMapJob::finished, this, &ENCMap::jobFinished); + job->run(); +} + +void ENCMap::removeJob(ENCMapJob *job) +{ + _jobs.removeOne(job); + job->deleteLater(); +} + +void ENCMap::jobFinished(ENCMapJob *job) +{ + const QList &tiles = job->tiles(); + + for (int i = 0; i < tiles.size(); i++) { + const ENC::RasterTile &mt = tiles.at(i); + if (mt.isValid()) + QPixmapCache::insert(key(mt.zoom(), mt.xy()), mt.pixmap()); + } + + removeJob(job); + + emit tilesLoaded(); +} + +void ENCMap::cancelJobs() +{ + for (int i = 0; i < _jobs.size(); i++) + _jobs.at(i)->cancel(); +} + QString ENCMap::key(int zoom, const QPoint &xy) const { return path() + "-" + QString::number(zoom) + "_" @@ -116,6 +167,8 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags) for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE); + if (isRunning(_zoom, ttl)) + continue; QPixmap pm; if (QPixmapCache::find(key(_zoom, ttl), &pm)) @@ -149,14 +202,19 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } - QFuture future = QtConcurrent::map(tiles, &RasterTile::render); - future.waitForFinished(); + if (!tiles.isEmpty()) { + if (flags & Map::Block) { + QFuture future = QtConcurrent::map(tiles, &RasterTile::render); + future.waitForFinished(); - for (int i = 0; i < tiles.size(); i++) { - const RasterTile &mt = tiles.at(i); - const QPixmap &pm = mt.pixmap(); - painter->drawPixmap(mt.xy(), pm); - QPixmapCache::insert(key(mt.zoom(), mt.xy()), pm); + for (int i = 0; i < tiles.size(); i++) { + const RasterTile &mt = tiles.at(i); + const QPixmap &pm = mt.pixmap(); + painter->drawPixmap(mt.xy(), pm); + QPixmapCache::insert(key(mt.zoom(), mt.xy()), pm); + } + } else + runJob(new ENCMapJob(tiles)); } } diff --git a/src/map/encmap.h b/src/map/encmap.h index adfc3703..3341477e 100644 --- a/src/map/encmap.h +++ b/src/map/encmap.h @@ -1,12 +1,42 @@ #ifndef ENCMAP_H #define ENCMAP_H +#include #include "map.h" #include "projection.h" #include "transform.h" #include "ENC/mapdata.h" +#include "ENC/rastertile.h" -class QFile; +class ENCMapJob : public QObject +{ + Q_OBJECT + +public: + ENCMapJob(const QList &tiles) + : _tiles(tiles) {} + + void run() + { + connect(&_watcher, &QFutureWatcher::finished, this, + &ENCMapJob::handleFinished); + _future = QtConcurrent::map(_tiles, &ENC::RasterTile::render); + _watcher.setFuture(_future); + } + void cancel() {_future.cancel();} + const QList &tiles() const {return _tiles;} + +signals: + void finished(ENCMapJob *job); + +private slots: + void handleFinished() {emit finished(this);} + +private: + QFutureWatcher _watcher; + QFuture _future; + QList _tiles; +}; class ENCMap : public Map { @@ -43,9 +73,16 @@ public: static Map *create(const QString &path, const Projection &, bool *isMap); +private slots: + void jobFinished(ENCMapJob *job); + private: Transform transform(int zoom) const; void updateTransform(); + bool isRunning(int zoom, const QPoint &xy) const; + void runJob(ENCMapJob *job); + void removeJob(ENCMapJob *job); + void cancelJobs(); QString key(int zoom, const QPoint &xy) const; ENC::MapData _data; @@ -56,6 +93,8 @@ private: QRectF _bounds; int _zoom; + QList _jobs; + bool _valid; QString _errorString; };