diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index 07200860..4c3324b1 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -126,21 +126,20 @@ Map *MapSource::map(QXmlStreamReader &reader) { QString name, url, layer, style, set; QString format("image/png"); - bool invert = false; + bool wmts, rest = false, invertAxis = false; Range z(ZOOM_MIN, ZOOM_MAX); RectC b(Coordinates(BOUNDS_LEFT, BOUNDS_TOP), Coordinates(BOUNDS_RIGHT, BOUNDS_BOTTOM)); - const QXmlStreamAttributes &attr = reader.attributes(); - bool wmts = (attr.hasAttribute("type") && attr.value("type") == "WMTS") - ? true : false; + wmts = (reader.attributes().value("type") == "WMTS") ? true : false; while (reader.readNextStartElement()) { if (reader.name() == "name") name = reader.readElementText(); - else if (reader.name() == "url") + else if (reader.name() == "url") { + rest = (reader.attributes().value("type") == "REST") ? true : false; url = reader.readElementText(); - else if (reader.name() == "zoom") { + } else if (reader.name() == "zoom") { z = zooms(reader); reader.skipCurrentElement(); } else if (reader.name() == "bounds") { @@ -155,7 +154,7 @@ Map *MapSource::map(QXmlStreamReader &reader) else if (reader.name() == "set") set = reader.readElementText(); else if (reader.name() == "axis") - invert = (reader.readElementText() == "yx") ? true : false; + invertAxis = (reader.readElementText() == "yx") ? true : false; else reader.skipCurrentElement(); } @@ -163,7 +162,8 @@ Map *MapSource::map(QXmlStreamReader &reader) if (reader.error()) return 0; else if (wmts) - return new WMTSMap(name, url, format, layer, style, set, invert); + return new WMTSMap(name, WMTS::Setup(url, layer, set, style, format, + rest), invertAxis); else return new OnlineMap(name, url, z, b); } diff --git a/src/map/onlinemap.cpp b/src/map/onlinemap.cpp index e20108e7..6bb7e1cd 100644 --- a/src/map/onlinemap.cpp +++ b/src/map/onlinemap.cpp @@ -41,12 +41,21 @@ static int scale2zoom(qreal scale) OnlineMap::OnlineMap(const QString &name, const QString &url, - const Range &zooms, const RectC &bounds, QObject *parent) - : Map(parent), _name(name), _zooms(zooms), _bounds(bounds) + const Range &zooms, const RectC &bounds, QObject *parent) : + Map(parent), _name(name), _zooms(zooms), _bounds(bounds), + _block(false), _valid(false) { - _block = false; + QString dir(TILES_DIR + "/" + _name); + _zoom = _zooms.max(); - _tileLoader = TileLoader(url, TILES_DIR + "/" + name); + _tileLoader = TileLoader(url, dir); + + if (!QDir().mkpath(dir)) { + _errorString = "Error creating tiles dir"; + return; + } + + _valid = true; } void OnlineMap::load() diff --git a/src/map/onlinemap.h b/src/map/onlinemap.h index 33195b0c..cd08e99e 100644 --- a/src/map/onlinemap.h +++ b/src/map/onlinemap.h @@ -39,6 +39,9 @@ public: void load(); void unload(); + bool isValid() const {return _valid;} + QString errorString() const {return _errorString;} + private slots: void emitLoaded(); @@ -53,6 +56,9 @@ private: RectC _bounds; int _zoom; bool _block; + + bool _valid; + QString _errorString; }; #endif // ONLINEMAP_H diff --git a/src/map/tileloader.cpp b/src/map/tileloader.cpp index 70f29da9..c7f4a7ac 100644 --- a/src/map/tileloader.cpp +++ b/src/map/tileloader.cpp @@ -17,13 +17,6 @@ static bool loadTileFile(Tile &tile, const QString &file) Downloader *TileLoader::_downloader = 0; -TileLoader::TileLoader(const QString &url, const QString &dir) - : _url(url), _dir(dir) -{ - if (!QDir().mkpath(_dir)) - qWarning("Error creating tiles dir: %s\n", qPrintable(_dir)); -} - void TileLoader::loadTilesAsync(QList &list) { QList dl; diff --git a/src/map/tileloader.h b/src/map/tileloader.h index 9906326c..9bbb7346 100644 --- a/src/map/tileloader.h +++ b/src/map/tileloader.h @@ -9,7 +9,8 @@ class TileLoader { public: TileLoader() {} - TileLoader(const QString &url, const QString &dir); + TileLoader(const QString &url, const QString &dir) + : _url(url), _dir(dir) {} void loadTilesAsync(QList &list); void loadTilesSync(QList &list); diff --git a/src/map/wmts.cpp b/src/map/wmts.cpp index 25bcae60..29b64e9a 100644 --- a/src/map/wmts.cpp +++ b/src/map/wmts.cpp @@ -194,6 +194,7 @@ void WMTS::layer(QXmlStreamReader &reader, const QString &layer, { QString id; RectC bounds; + QString tpl; while (reader.readNextStartElement()) { if (reader.name() == "Identifier") @@ -202,12 +203,19 @@ void WMTS::layer(QXmlStreamReader &reader, const QString &layer, tileMatrixSetLink(reader, set); else if (reader.name() == "WGS84BoundingBox") bounds = wgs84BoundingBox(reader); - else + else if (reader.name() == "ResourceURL") { + const QXmlStreamAttributes &attr = reader.attributes(); + if (attr.value("resourceType") == "tile") + tpl = attr.value("template").toString(); + reader.skipCurrentElement(); + } else reader.skipCurrentElement(); } - if (id == layer) + if (id == layer) { _bounds = bounds; + _tileUrl = tpl; + } } void WMTS::contents(QXmlStreamReader &reader, const QString &layer, @@ -264,9 +272,7 @@ bool WMTS::getCapabilities(const QString &url, const QString &file) { QList dl; - QString capabilitiesUrl = QString("%1?service=WMTS&Version=1.0.0" - "&request=GetCapabilities").arg(url); - dl.append(Download(capabilitiesUrl, file)); + dl.append(Download(url, file)); QEventLoop wait; QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit())); @@ -281,17 +287,31 @@ bool WMTS::getCapabilities(const QString &url, const QString &file) } } -bool WMTS::load(const QString &file, const QString &url, const QString &layer, - const QString &set) +bool WMTS::load(const QString &file, const WMTS::Setup &setup) { - QMap::const_iterator it; + QString capaUrl = setup.rest ? setup.url : + QString("%1?service=WMTS&Version=1.0.0&request=GetCapabilities") + .arg(setup.url); if (!QFileInfo(file).exists()) - if (!getCapabilities(url, file)) + if (!getCapabilities(capaUrl, file)) return false; - if (!parseCapabilities(file, layer, set)) + if (!parseCapabilities(file, setup.layer, setup.set)) return false; + if (!setup.rest) + _tileUrl = QString("%1?service=WMTS&Version=1.0.0&request=GetTile" + "&Format=%2&Layer=%3&Style=%4&TileMatrixSet=%5&TileMatrix=$z" + "&TileRow=$y&TileCol=$x").arg(setup.url).arg(setup.format) + .arg(setup.layer).arg(setup.style).arg(setup.set); + else { + _tileUrl.replace("{Style}", setup.style); + _tileUrl.replace("{TileMatrixSet}", setup.set); + _tileUrl.replace("{TileMatrix}", "$z"); + _tileUrl.replace("{TileRow}", "$y"); + _tileUrl.replace("{TileCol}", "$x"); + } + if (_matrixes.isEmpty()) { _errorString = "No usable tile matrix found"; return false; @@ -300,6 +320,10 @@ bool WMTS::load(const QString &file, const QString &url, const QString &layer, _errorString = "Missing CRS definition"; return false; } + if (_tileUrl.isNull()) { + _errorString = "Missing tile URL"; + return false; + } return true; } @@ -325,6 +349,14 @@ QList WMTS::zooms() const } #ifndef QT_NO_DEBUG +QDebug operator<<(QDebug dbg, const WMTS::Setup &setup) +{ + dbg.nospace() << "Setup(" << setup.url << ", " << setup.layer << ", " + << setup.set << ", " << setup.style << ", " << setup.format << ", " + << setup.rest << ")"; + return dbg.space(); +} + QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom) { dbg.nospace() << "Zoom(" << zoom.id << ", " << zoom.scaleDenominator << ", " diff --git a/src/map/wmts.h b/src/map/wmts.h index 4da6db99..9d365c98 100644 --- a/src/map/wmts.h +++ b/src/map/wmts.h @@ -15,6 +15,20 @@ class Downloader; class WMTS { public: + struct Setup { + QString url; + QString layer; + QString set; + QString style; + QString format; + bool rest; + + Setup(const QString &url, const QString &layer, const QString &set, + const QString &style, const QString &format, bool rest) : + url(url), layer(layer), set(set), style(style), format(format), + rest(rest) {} + }; + struct Zoom { QString id; qreal scaleDenominator; @@ -32,13 +46,13 @@ public: {return scaleDenominator > other.scaleDenominator;} }; - bool load(const QString &path, const QString &url, const QString &layer, - const QString &set); + bool load(const QString &path, const Setup &setup); const QString &errorString() const {return _errorString;} const RectC &bounds() const {return _bounds;} QList zooms() const; const Projection &projection() const {return _projection;} + QString tileUrl() const {return _tileUrl;} static Downloader *downloader() {return _downloader;} static void setDownloader(Downloader *downloader) @@ -94,6 +108,7 @@ private: QSet _limits; RectC _bounds; Projection _projection; + QString _tileUrl; QString _errorString; @@ -114,6 +129,7 @@ inline uint qHash(const WMTS::MatrixLimits &key) } #ifndef QT_NO_DEBUG +QDebug operator<<(QDebug dbg, const WMTS::Setup &setup); QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom); #endif // QT_NO_DEBUG diff --git a/src/map/wmtsmap.cpp b/src/map/wmtsmap.cpp index 95d37d55..11c62e23 100644 --- a/src/map/wmtsmap.cpp +++ b/src/map/wmtsmap.cpp @@ -9,30 +9,27 @@ #define CAPABILITIES_FILE "capabilities.xml" -WMTSMap::WMTSMap(const QString &name, const QString &url, const QString &format, - const QString &layer, const QString &style, const QString &set, - bool invertAxis, QObject *parent) : - Map(parent), _name(name), _url(url), _layer(layer), _set(set), - _invertAxis(invertAxis), _zoom(0), _valid(false) +WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, bool invertAxis, + QObject *parent) : Map(parent), _name(name), _setup(setup), + _invertAxis(invertAxis), _zoom(0), _valid(false) { QString dir(TILES_DIR + "/" + _name); QString file = dir + "/" + CAPABILITIES_FILE; - QString tileUrl = QString("%1?service=WMTS&Version=1.0.0&request=GetTile" - "&Format=%2&Layer=%3&Style=%4&TileMatrixSet=%5&TileMatrix=$z&TileRow=$y" - "&TileCol=$x").arg(_url).arg(format).arg(layer).arg(style) - .arg(_set); - _tileLoader = TileLoader(tileUrl, dir); + if (!QDir().mkpath(dir)) { + _errorString = "Error creating tiles dir"; + return; + } WMTS wmts; - if (!wmts.load(file, _url, _layer, _set)) { + if (!wmts.load(file, _setup)) { _errorString = wmts.errorString(); return; } _bounds = wmts.bounds(); _zooms = wmts.zooms(); _projection = wmts.projection(); - + _tileLoader = TileLoader(wmts.tileUrl(), dir); updateTransform(); _block = false; @@ -91,10 +88,12 @@ void WMTSMap::clearCache() _tileLoader.clearCache(); WMTS wmts; - if (!wmts.load(file, _url, _layer, _set)) + if (!wmts.load(file, _setup)) return; + _bounds = wmts.bounds(); _zooms = wmts.zooms(); _projection = wmts.projection(); + _tileLoader = TileLoader(wmts.tileUrl(), dir); if (_zoom >= _zooms.size()) _zoom = _zooms.size() - 1; diff --git a/src/map/wmtsmap.h b/src/map/wmtsmap.h index 14127450..c2fb829a 100644 --- a/src/map/wmtsmap.h +++ b/src/map/wmtsmap.h @@ -13,9 +13,8 @@ class WMTSMap : public Map Q_OBJECT public: - WMTSMap(const QString &name, const QString &url, const QString &format, - const QString &layer, const QString &style, const QString &set, - bool invertAxis, QObject *parent = 0); + WMTSMap(const QString &name, const WMTS::Setup &setup, bool invertAxis, + QObject *parent = 0); const QString &name() const {return _name;} @@ -54,7 +53,8 @@ private: QPointF ll2xy(const Coordinates &c) const; Coordinates xy2ll(const QPointF &p) const; - QString _name, _url, _layer, _set; + QString _name; + WMTS::Setup _setup; TileLoader _tileLoader; RectC _bounds; QList _zooms;