1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/map/mapsource.cpp

243 lines
6.4 KiB
C++
Raw Normal View History

#include <QFile>
#include <QXmlStreamReader>
#include "onlinemap.h"
2018-02-20 23:37:19 +01:00
#include "wmtsmap.h"
#include "wmsmap.h"
2018-01-29 00:19:57 +01:00
#include "mapsource.h"
#define ZOOM_MAX 19
#define ZOOM_MIN 0
#define BOUNDS_LEFT -180
#define BOUNDS_TOP 85.0511
#define BOUNDS_RIGHT 180
#define BOUNDS_BOTTOM -85.0511
MapSource::Config::Config() : type(TMS), zooms(ZOOM_MIN, ZOOM_MAX),
bounds(Coordinates(BOUNDS_LEFT, BOUNDS_TOP), Coordinates(BOUNDS_RIGHT,
BOUNDS_BOTTOM)), format("image/png"), axisOrder(Unknown), rest(false) {}
static AxisOrder axisOrder(QXmlStreamReader &reader)
{
QXmlStreamAttributes attr = reader.attributes();
if (attr.value("axis") == "yx")
return AxisOrder::YX;
else if (attr.value("axis") == "xy")
return AxisOrder::XY;
else
return AxisOrder::Unknown;
}
2018-02-27 21:50:29 +01:00
Range MapSource::zooms(QXmlStreamReader &reader)
{
const QXmlStreamAttributes &attr = reader.attributes();
int min, max;
bool res;
if (attr.hasAttribute("min")) {
min = attr.value("min").toString().toInt(&res);
if (!res || (min < ZOOM_MIN || min > ZOOM_MAX)) {
reader.raiseError("Invalid minimal zoom level");
2018-02-27 21:50:29 +01:00
return Range();
}
} else
min = ZOOM_MIN;
if (attr.hasAttribute("max")) {
max = attr.value("max").toString().toInt(&res);
if (!res || (max < ZOOM_MIN || max > ZOOM_MAX)) {
reader.raiseError("Invalid maximal zoom level");
2018-02-27 21:50:29 +01:00
return Range();
}
} else
max = ZOOM_MAX;
2018-02-27 21:50:29 +01:00
if (min > max) {
reader.raiseError("Invalid maximal/minimal zoom level combination");
2018-02-27 21:50:29 +01:00
return Range();
}
return Range(min, max);
}
2018-02-27 21:50:29 +01:00
RectC MapSource::bounds(QXmlStreamReader &reader)
{
const QXmlStreamAttributes &attr = reader.attributes();
double top, left, bottom, right;
bool res;
if (attr.hasAttribute("top")) {
top = attr.value("top").toString().toDouble(&res);
if (!res || (top < BOUNDS_BOTTOM || top > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds top value");
2018-02-27 21:50:29 +01:00
return RectC();
}
} else
top = BOUNDS_TOP;
if (attr.hasAttribute("bottom")) {
bottom = attr.value("bottom").toString().toDouble(&res);
if (!res || (bottom < BOUNDS_BOTTOM || bottom > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds bottom value");
2018-02-27 21:50:29 +01:00
return RectC();
}
} else
bottom = BOUNDS_BOTTOM;
if (attr.hasAttribute("left")) {
left = attr.value("left").toString().toDouble(&res);
if (!res || (left < BOUNDS_LEFT || left > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds left value");
2018-02-27 21:50:29 +01:00
return RectC();
}
} else
left = BOUNDS_LEFT;
if (attr.hasAttribute("right")) {
right = attr.value("right").toString().toDouble(&res);
if (!res || (right < BOUNDS_LEFT || right > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds right value");
2018-02-27 21:50:29 +01:00
return RectC();
}
} else
right = BOUNDS_RIGHT;
2018-02-27 21:50:29 +01:00
if (bottom >= top) {
reader.raiseError("Invalid bottom/top bounds combination");
2018-02-27 21:50:29 +01:00
return RectC();
}
2018-02-27 21:50:29 +01:00
if (left >= right) {
reader.raiseError("Invalid left/right bounds combination");
2018-02-27 21:50:29 +01:00
return RectC();
}
2018-02-27 21:50:29 +01:00
return RectC(Coordinates(left, top), Coordinates(right, bottom));
}
void MapSource::map(QXmlStreamReader &reader, Config &config)
{
const QXmlStreamAttributes &attr = reader.attributes();
config.type = (attr.value("type") == "WMTS") ? WMTS
: (attr.value("type") == "WMS") ? WMS : TMS;
2018-02-20 23:37:19 +01:00
while (reader.readNextStartElement()) {
if (reader.name() == "name")
config.name = reader.readElementText();
2018-02-25 02:31:01 +01:00
else if (reader.name() == "url") {
config.rest = (reader.attributes().value("type") == "REST")
2018-02-27 21:50:29 +01:00
? true : false;
config.url = reader.readElementText();
2018-02-25 02:31:01 +01:00
} else if (reader.name() == "zoom") {
config.zooms = zooms(reader);
reader.skipCurrentElement();
} else if (reader.name() == "bounds") {
config.bounds = bounds(reader);
reader.skipCurrentElement();
} else if (reader.name() == "format")
config.format = reader.readElementText();
else if (reader.name() == "layer")
config.layer = reader.readElementText();
2018-02-20 23:37:19 +01:00
else if (reader.name() == "style")
config.style = reader.readElementText();
else if (reader.name() == "set") {
config.axisOrder = axisOrder(reader);
config.set = reader.readElementText();
2018-03-11 10:31:41 +01:00
} else if (reader.name() == "dimension") {
QXmlStreamAttributes attr = reader.attributes();
if (!attr.hasAttribute("id"))
reader.raiseError("Missing dimension id");
else
config.dimensions.append(QPair<QString, QString>(
2018-03-11 10:31:41 +01:00
attr.value("id").toString(), reader.readElementText()));
} else if (reader.name() == "crs") {
config.axisOrder = axisOrder(reader);
config.crs = reader.readElementText();
} else if (reader.name() == "authorization") {
QXmlStreamAttributes attr = reader.attributes();
config.authorization = Authorization(
attr.value("username").toString(),
attr.value("password").toString());
reader.skipCurrentElement();
} else
reader.skipCurrentElement();
}
}
2018-02-20 23:37:19 +01:00
Map *MapSource::loadFile(const QString &path)
{
QFile file(path);
QXmlStreamReader reader;
Config config;
Map *m;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
return 0;
}
reader.setDevice(&file);
if (reader.readNextStartElement()) {
2018-01-29 00:19:57 +01:00
if (reader.name() == "map")
map(reader, config);
else
2018-01-29 00:19:57 +01:00
reader.raiseError("Not an online map source file");
}
if (reader.error()) {
2018-02-20 23:37:19 +01:00
_errorString = QString("%1: %2").arg(reader.lineNumber())
.arg(reader.errorString());
return 0;
}
if (config.name.isEmpty()) {
_errorString = "Missing name definition";
return 0;
}
if (config.url.isEmpty()) {
_errorString = "Missing URL definition";
return 0;
}
if (config.type == WMTS || config.type == WMS) {
if (config.layer.isEmpty()) {
_errorString = "Missing layer definition";
return 0;
}
if (config.format.isEmpty()) {
_errorString = "Missing format definition";
return 0;
}
}
if (config.type == WMTS) {
if (config.set.isEmpty()) {
_errorString = "Missing set definiton";
return 0;
}
}
if (config.type == WMS) {
if (config.crs.isEmpty()) {
_errorString = "Missing CRS definiton";
return 0;
}
}
if (config.type == WMTS)
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
config.set, config.style, config.format, config.rest, config.axisOrder,
config.dimensions, config.authorization));
else if (config.type == WMS)
m = new WMSMap(config.name, WMS::Setup(config.url, config.layer,
config.style, config.format, config.crs, config.axisOrder,
config.authorization));
else
m = new OnlineMap(config.name, config.url, config.zooms, config.bounds);
if (!m->isValid()) {
_errorString = m->errorString();
delete m;
return 0;
2018-02-20 23:37:19 +01:00
}
return m;
}