2018-02-20 23:37:19 +01:00
|
|
|
#include <QDir>
|
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QEventLoop>
|
2018-11-10 13:18:54 +01:00
|
|
|
#include <QPixmapCache>
|
2018-11-15 00:38:03 +01:00
|
|
|
#include <QImageReader>
|
2018-11-10 13:18:54 +01:00
|
|
|
#include <QtConcurrent>
|
2018-02-20 23:37:19 +01:00
|
|
|
#include "tileloader.h"
|
|
|
|
|
|
|
|
|
2018-11-10 13:18:54 +01:00
|
|
|
class TileImage
|
2018-02-20 23:37:19 +01:00
|
|
|
{
|
2018-11-10 13:18:54 +01:00
|
|
|
public:
|
2019-05-20 23:23:24 +02:00
|
|
|
TileImage() : _tile(0), _scaledSize(0) {}
|
|
|
|
TileImage(const QString &file, Tile *tile, int scaledSize)
|
|
|
|
: _file(file), _tile(tile), _scaledSize(scaledSize) {}
|
2018-11-10 13:18:54 +01:00
|
|
|
|
|
|
|
void createPixmap()
|
|
|
|
{
|
2018-11-11 18:54:21 +01:00
|
|
|
_tile->pixmap().convertFromImage(_image);
|
2018-11-10 13:18:54 +01:00
|
|
|
}
|
|
|
|
void load()
|
|
|
|
{
|
2018-11-11 18:54:21 +01:00
|
|
|
QByteArray z(_tile->zoom().toString().toLatin1());
|
2018-11-15 00:38:03 +01:00
|
|
|
QImageReader reader(_file, z);
|
2019-05-20 23:23:24 +02:00
|
|
|
if (_scaledSize)
|
|
|
|
reader.setScaledSize(QSize(_scaledSize, _scaledSize));
|
2018-11-15 00:38:03 +01:00
|
|
|
reader.read(&_image);
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
2018-11-10 13:18:54 +01:00
|
|
|
const QString &file() const {return _file;}
|
2018-11-11 18:54:21 +01:00
|
|
|
Tile *tile() {return _tile;}
|
2018-11-10 13:18:54 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
QString _file;
|
2018-11-11 18:54:21 +01:00
|
|
|
Tile *_tile;
|
2019-05-20 23:23:24 +02:00
|
|
|
int _scaledSize;
|
2018-11-10 13:18:54 +01:00
|
|
|
QImage _image;
|
|
|
|
};
|
|
|
|
|
2019-05-20 23:23:24 +02:00
|
|
|
static QString quadKey(const QPoint &xy, int zoom)
|
|
|
|
{
|
|
|
|
QString qk;
|
|
|
|
|
|
|
|
for (int i = zoom; i > 0; i--) {
|
|
|
|
char digit = '0';
|
|
|
|
unsigned mask = 1 << (i - 1);
|
|
|
|
if (xy.x() & mask)
|
|
|
|
digit++;
|
2019-05-21 17:59:46 +02:00
|
|
|
if (xy.y() & mask)
|
|
|
|
digit += 2;
|
2019-05-20 23:23:24 +02:00
|
|
|
qk.append(digit);
|
|
|
|
}
|
|
|
|
|
|
|
|
return qk;
|
|
|
|
}
|
|
|
|
|
2018-09-24 22:49:10 +02:00
|
|
|
TileLoader::TileLoader(const QString &dir, QObject *parent)
|
2019-05-20 23:23:24 +02:00
|
|
|
: QObject(parent), _dir(dir), _scaledSize(0), _quadTiles(false)
|
2018-04-27 19:31:27 +02:00
|
|
|
{
|
2018-09-24 22:49:10 +02:00
|
|
|
if (!QDir().mkpath(_dir))
|
2018-09-24 23:07:11 +02:00
|
|
|
qWarning("%s: %s", qPrintable(_dir), "Error creating tiles directory");
|
2018-09-24 22:49:10 +02:00
|
|
|
|
2018-04-27 19:31:27 +02:00
|
|
|
_downloader = new Downloader(this);
|
|
|
|
connect(_downloader, SIGNAL(finished()), this, SIGNAL(finished()));
|
|
|
|
}
|
2018-02-20 23:37:19 +01:00
|
|
|
|
2018-10-05 07:10:49 +02:00
|
|
|
void TileLoader::loadTilesAsync(QVector<Tile> &list)
|
2018-02-20 23:37:19 +01:00
|
|
|
{
|
|
|
|
QList<Download> dl;
|
2018-11-10 13:18:54 +01:00
|
|
|
QList<TileImage> imgs;
|
2018-02-20 23:37:19 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
|
Tile &t = list[i];
|
2018-09-22 12:42:49 +02:00
|
|
|
QString file(tileFile(t));
|
2018-11-10 13:18:54 +01:00
|
|
|
|
2020-12-22 22:09:09 +01:00
|
|
|
if (QPixmapCache::find(file, &t.pixmap()))
|
2018-11-10 13:18:54 +01:00
|
|
|
continue;
|
|
|
|
|
2018-02-20 23:37:19 +01:00
|
|
|
QFileInfo fi(file);
|
|
|
|
|
2018-10-04 23:02:43 +02:00
|
|
|
if (fi.exists())
|
2019-05-20 23:23:24 +02:00
|
|
|
imgs.append(TileImage(file, &t, _scaledSize));
|
2018-10-04 23:02:43 +02:00
|
|
|
else {
|
|
|
|
QUrl url(tileUrl(t));
|
|
|
|
if (url.isLocalFile())
|
2019-05-20 23:23:24 +02:00
|
|
|
imgs.append(TileImage(url.toLocalFile(), &t, _scaledSize));
|
2018-10-04 23:02:43 +02:00
|
|
|
else
|
|
|
|
dl.append(Download(url, file));
|
|
|
|
}
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!dl.empty())
|
2018-04-01 20:01:25 +02:00
|
|
|
_downloader->get(dl, _authorization);
|
2018-11-10 13:18:54 +01:00
|
|
|
|
2020-07-02 23:51:15 +02:00
|
|
|
QFuture<void> future = QtConcurrent::map(imgs, &TileImage::load);
|
2018-11-10 13:18:54 +01:00
|
|
|
future.waitForFinished();
|
|
|
|
|
|
|
|
for (int i = 0; i < imgs.size(); i++) {
|
|
|
|
TileImage &ti = imgs[i];
|
|
|
|
ti.createPixmap();
|
2018-11-11 18:54:21 +01:00
|
|
|
QPixmapCache::insert(ti.file(), ti.tile()->pixmap());
|
2018-11-10 13:18:54 +01:00
|
|
|
}
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
2018-10-05 07:10:49 +02:00
|
|
|
void TileLoader::loadTilesSync(QVector<Tile> &list)
|
2018-02-20 23:37:19 +01:00
|
|
|
{
|
|
|
|
QList<Download> dl;
|
2018-11-10 13:18:54 +01:00
|
|
|
QList<Tile *> tl;
|
|
|
|
QList<TileImage> imgs;
|
2018-02-20 23:37:19 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
|
Tile &t = list[i];
|
2018-09-22 12:42:49 +02:00
|
|
|
QString file(tileFile(t));
|
2018-11-10 13:18:54 +01:00
|
|
|
|
2020-12-22 22:09:09 +01:00
|
|
|
if (QPixmapCache::find(file, &t.pixmap()))
|
2018-11-10 13:18:54 +01:00
|
|
|
continue;
|
|
|
|
|
2018-02-20 23:37:19 +01:00
|
|
|
QFileInfo fi(file);
|
|
|
|
|
2018-10-04 23:02:43 +02:00
|
|
|
if (fi.exists())
|
2019-05-20 23:23:24 +02:00
|
|
|
imgs.append(TileImage(file, &t, _scaledSize));
|
2018-10-04 23:02:43 +02:00
|
|
|
else {
|
|
|
|
QUrl url(tileUrl(t));
|
|
|
|
if (url.isLocalFile())
|
2019-05-20 23:23:24 +02:00
|
|
|
imgs.append(TileImage(url.toLocalFile(), &t, _scaledSize));
|
2018-11-10 13:18:54 +01:00
|
|
|
else {
|
2018-10-04 23:02:43 +02:00
|
|
|
dl.append(Download(url, file));
|
2018-11-10 13:18:54 +01:00
|
|
|
tl.append(&t);
|
|
|
|
}
|
2018-10-04 23:02:43 +02:00
|
|
|
}
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
2018-11-10 13:18:54 +01:00
|
|
|
if (!dl.empty()) {
|
|
|
|
QEventLoop wait;
|
|
|
|
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
|
|
|
|
if (_downloader->get(dl, _authorization))
|
|
|
|
wait.exec();
|
2018-02-20 23:37:19 +01:00
|
|
|
|
2018-11-10 13:18:54 +01:00
|
|
|
for (int i = 0; i < tl.size(); i++) {
|
|
|
|
Tile *t = tl[i];
|
|
|
|
QString file = tileFile(*t);
|
2019-03-05 23:05:50 +01:00
|
|
|
if (QFileInfo(file).exists())
|
2019-05-20 23:23:24 +02:00
|
|
|
imgs.append(TileImage(file, t, _scaledSize));
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
}
|
2018-11-10 13:18:54 +01:00
|
|
|
|
2020-07-02 23:51:15 +02:00
|
|
|
QFuture<void> future = QtConcurrent::map(imgs, &TileImage::load);
|
2018-11-10 13:18:54 +01:00
|
|
|
future.waitForFinished();
|
|
|
|
|
|
|
|
for (int i = 0; i < imgs.size(); i++)
|
|
|
|
imgs[i].createPixmap();
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void TileLoader::clearCache()
|
|
|
|
{
|
|
|
|
QDir dir = QDir(_dir);
|
|
|
|
QStringList list = dir.entryList();
|
|
|
|
|
|
|
|
for (int i = 0; i < list.count(); i++)
|
|
|
|
dir.remove(list.at(i));
|
2018-03-15 18:46:34 +01:00
|
|
|
|
|
|
|
_downloader->clearErrors();
|
2020-03-01 11:43:08 +01:00
|
|
|
|
|
|
|
QPixmapCache::clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileLoader::setScaledSize(int size)
|
|
|
|
{
|
|
|
|
if (_scaledSize == size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_scaledSize = size;
|
|
|
|
QPixmapCache::clear();
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
2018-09-22 12:42:49 +02:00
|
|
|
QUrl TileLoader::tileUrl(const Tile &tile) const
|
2018-02-20 23:37:19 +01:00
|
|
|
{
|
|
|
|
QString url(_url);
|
|
|
|
|
2018-03-30 10:25:05 +02:00
|
|
|
if (!tile.bbox().isNull()) {
|
|
|
|
QString bbox = QString("%1,%2,%3,%4").arg(
|
|
|
|
QString::number(tile.bbox().left(), 'f', 6),
|
|
|
|
QString::number(tile.bbox().bottom(), 'f', 6),
|
|
|
|
QString::number(tile.bbox().right(), 'f', 6),
|
|
|
|
QString::number(tile.bbox().top(), 'f', 6));
|
|
|
|
url.replace("$bbox", bbox);
|
2019-05-20 23:23:24 +02:00
|
|
|
} else if (_quadTiles) {
|
|
|
|
url.replace("$quadkey", quadKey(tile.xy(), tile.zoom().toInt()));
|
2018-03-30 10:25:05 +02:00
|
|
|
} else {
|
|
|
|
url.replace("$z", tile.zoom().toString());
|
|
|
|
url.replace("$x", QString::number(tile.xy().x()));
|
|
|
|
url.replace("$y", QString::number(tile.xy().y()));
|
|
|
|
}
|
2018-02-20 23:37:19 +01:00
|
|
|
|
2018-09-22 12:42:49 +02:00
|
|
|
return QUrl(url);
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString TileLoader::tileFile(const Tile &tile) const
|
|
|
|
{
|
2018-10-04 23:02:43 +02:00
|
|
|
return _dir + QLatin1Char('/') + tile.zoom().toString() + QLatin1Char('-')
|
|
|
|
+ QString::number(tile.xy().x()) + QLatin1Char('-')
|
|
|
|
+ QString::number(tile.xy().y());
|
2018-02-20 23:37:19 +01:00
|
|
|
}
|