diff --git a/src/map/mapsforge/rastertile.cpp b/src/map/mapsforge/rastertile.cpp index 58deccb4..1db5b347 100644 --- a/src/map/mapsforge/rastertile.cpp +++ b/src/map/mapsforge/rastertile.cpp @@ -344,4 +344,6 @@ void RasterTile::render() //painter.drawRect(QRect(_rect.topLeft(), _pixmap.size())); qDeleteAll(textItems); + + _valid = true; } diff --git a/src/map/mapsforge/rastertile.h b/src/map/mapsforge/rastertile.h index b41603a0..e9185f85 100644 --- a/src/map/mapsforge/rastertile.h +++ b/src/map/mapsforge/rastertile.h @@ -16,15 +16,16 @@ class RasterTile { public: RasterTile(const Projection &proj, const Transform &transform, int zoom, - const QRect &rect, qreal ratio, const QString &key, - const QList &paths, const QList &points) - : _proj(proj), _transform(transform), _zoom(zoom), _rect(rect), - _ratio(ratio), _key(key), _pixmap(rect.width() * ratio, - rect.height() * ratio), _paths(paths), _points(points) {} + const QRect &rect, qreal ratio, const QList &paths, + const QList &points) : _proj(proj), _transform(transform), + _zoom(zoom), _rect(rect), _ratio(ratio), + _pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths), + _points(points), _valid(false) {} - const QString &key() const {return _key;} + int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} const QPixmap &pixmap() const {return _pixmap;} + bool isValid() const {return _valid;} void render(); @@ -84,10 +85,10 @@ private: int _zoom; QRect _rect; qreal _ratio; - QString _key; QPixmap _pixmap; QList _paths; QList _points; + bool _valid; }; inline HASH_T qHash(const RasterTile::Key &key) diff --git a/src/map/mapsforgemap.cpp b/src/map/mapsforgemap.cpp index 146f4aaf..783ca47d 100644 --- a/src/map/mapsforgemap.cpp +++ b/src/map/mapsforgemap.cpp @@ -60,6 +60,8 @@ int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect) int MapsforgeMap::zoomIn() { + cancelJobs(); + _zoom = qMin(_zoom + 1, _data.zooms().max()); updateTransform(); return _zoom; @@ -67,6 +69,8 @@ int MapsforgeMap::zoomIn() int MapsforgeMap::zoomOut() { + cancelJobs(); + _zoom = qMax(_zoom - 1, _data.zooms().min()); updateTransform(); return _zoom; @@ -101,29 +105,59 @@ void MapsforgeMap::updateTransform() _bounds.adjust(0.5, 0, -0.5, 0); } -bool MapsforgeMap::isRunning(const QString &key) const +bool MapsforgeMap::isRunning(int zoom, const QPoint &xy) const { - return _running.contains(key); + for (int i = 0; i < _jobs.size(); i++) { + const QList &tiles = _jobs.at(i)->tiles(); + for (int j = 0; j < tiles.size(); j++) { + const Mapsforge::RasterTile &mt = tiles.at(j); + if (mt.zoom() == zoom && mt.xy() == xy) + return true; + } + } + + return false; } -void MapsforgeMap::addRunning(const QList &tiles) +void MapsforgeMap::runJob(MapsforgeMapJob *job) { - for (int i = 0; i < tiles.size(); i++) - _running.insert(tiles.at(i).key()); + _jobs.append(job); + + connect(job, &MapsforgeMapJob::finished, this, &MapsforgeMap::jobFinished); + job->run(); } -void MapsforgeMap::removeRunning(const QList &tiles) +void MapsforgeMap::removeJob(MapsforgeMapJob *job) { - for (int i = 0; i < tiles.size(); i++) - _running.remove(tiles.at(i).key()); + _jobs.removeOne(job); + job->deleteLater(); } -void MapsforgeMap::jobFinished(const QList &tiles) +void MapsforgeMap::jobFinished(MapsforgeMapJob *job) { - removeRunning(tiles); + const QList &tiles = job->tiles(); + + for (int i = 0; i < tiles.size(); i++) { + const Mapsforge::RasterTile &mt = tiles.at(i); + if (!mt.isValid()) + continue; + + QString key = path() + "-" + QString::number(mt.zoom()) + "_" + + QString::number(mt.xy().x()) + "_" + QString::number(mt.xy().y()); + QPixmapCache::insert(key, mt.pixmap()); + } + + removeJob(job); + emit tilesLoaded(); } +void MapsforgeMap::cancelJobs() +{ + for (int i = 0; i < _jobs.size(); i++) + _jobs.at(i)->cancel(); +} + void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) { Q_UNUSED(flags); @@ -138,15 +172,15 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - QPixmap pm; QPoint ttl(tl.x() + i * _data.tileSize(), tl.y() + j * _data.tileSize()); + if (isRunning(_zoom, ttl)) + continue; + + QPixmap pm; QString key = path() + "-" + QString::number(_zoom) + "_" + QString::number(ttl.x()) + "_" + QString::number(ttl.y()); - if (isRunning(key)) - continue; - if (QPixmapCache::find(key, &pm)) painter->drawPixmap(ttl, pm); else { @@ -175,18 +209,13 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) tiles.append(RasterTile(_projection, _transform, _zoom, QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), - _tileRatio, key, paths, points)); + _tileRatio, paths, points)); } } } - if (!tiles.isEmpty()) { - MapsforgeMapJob *job = new MapsforgeMapJob(tiles); - connect(job, &MapsforgeMapJob::finished, this, - &MapsforgeMap::jobFinished); - addRunning(tiles); - job->run(); - } + if (!tiles.isEmpty()) + runJob(new MapsforgeMapJob(tiles)); } void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) diff --git a/src/map/mapsforgemap.h b/src/map/mapsforgemap.h index 62fa037b..bfe98339 100644 --- a/src/map/mapsforgemap.h +++ b/src/map/mapsforgemap.h @@ -26,26 +26,14 @@ public: _future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render); _watcher.setFuture(_future); } + void cancel() {_future.cancel();} + const QList &tiles() const {return _tiles;} signals: - void finished(const QList &); + void finished(MapsforgeMapJob *job); private slots: - void handleFinished() - { - for (int i = 0; i < _tiles.size(); i++) { - Mapsforge::RasterTile &mt = _tiles[i]; - const QPixmap &pm = mt.pixmap(); - if (pm.isNull()) - continue; - - QPixmapCache::insert(mt.key(), pm); - } - - emit finished(_tiles); - - deleteLater(); - } + void handleFinished() {emit finished(this);} private: QFutureWatcher _watcher; @@ -85,14 +73,15 @@ public: QString errorString() const {return _data.errorString();} private slots: - void jobFinished(const QList &tiles); + void jobFinished(MapsforgeMapJob *job); private: Transform transform(int zoom) const; void updateTransform(); - bool isRunning(const QString &key) const; - void addRunning(const QList &tiles); - void removeRunning(const QList &tiles); + bool isRunning(int zoom, const QPoint &xy) const; + void runJob(MapsforgeMapJob *job); + void removeJob(MapsforgeMapJob *job); + void cancelJobs(); Mapsforge::MapData _data; int _zoom; @@ -102,7 +91,7 @@ private: QRectF _bounds; qreal _tileRatio; - QSet _running; + QList _jobs; }; #endif // MAPSFORGEMAP_H