#include #include #include #include "downloader.h" #include "crs.h" #include "wms.h" Downloader *WMS::_downloader = 0; void WMS::getMap(QXmlStreamReader &reader, CTX &ctx) { while (reader.readNextStartElement()) { if (reader.name() == "Format") { if (reader.readElementText() == ctx.setup.format()) ctx.format = true; } else reader.skipCurrentElement(); } } void WMS::request(QXmlStreamReader &reader, CTX &ctx) { while (reader.readNextStartElement()) { if (reader.name() == "GetMap") getMap(reader, ctx); else reader.skipCurrentElement(); } } QString WMS::style(QXmlStreamReader &reader) { QString name; while (reader.readNextStartElement()) { if (reader.name() == "Name") name = reader.readElementText(); else reader.skipCurrentElement(); } return name; } RectC WMS::geographicBoundingBox(QXmlStreamReader &reader) { qreal left, top, right, bottom; while (reader.readNextStartElement()) { if (reader.name() == "westBoundLongitude") left = reader.readElementText().toDouble(); else if (reader.name() == "eastBoundLongitude") right = reader.readElementText().toDouble(); else if (reader.name() == "northBoundLatitude") top = reader.readElementText().toDouble(); else if (reader.name() == "southBoundLatitude") bottom = reader.readElementText().toDouble(); else reader.skipCurrentElement(); } return RectC(Coordinates(left, top), Coordinates(right, bottom)); } void WMS::layer(QXmlStreamReader &reader, CTX &ctx, const QList &pCRSs, const QList &pStyles, RangeF &pScaleDenominator, RectC &pBoundingBox) { QString name; QList CRSs(pCRSs); QList styles(pStyles); RangeF scaleDenominator(pScaleDenominator); RectC boundingBox(pBoundingBox); while (reader.readNextStartElement()) { if (reader.name() == "Name") name = reader.readElementText(); else if (reader.name() == "CRS" || reader.name() == "SRS") CRSs.append(reader.readElementText()); else if (reader.name() == "Style") styles.append(style(reader)); else if (reader.name() == "MinScaleDenominator") scaleDenominator.setMin(reader.readElementText().toDouble()); else if (reader.name() == "MaxScaleDenominator") scaleDenominator.setMax(reader.readElementText().toDouble()); else if (reader.name() == "LatLonBoundingBox") { QXmlStreamAttributes attr = reader.attributes(); boundingBox = RectC(Coordinates( attr.value("minx").toString().toDouble(), attr.value("maxy").toString().toDouble()), Coordinates(attr.value("maxx").toString().toDouble(), attr.value("miny").toString().toDouble())); reader.skipCurrentElement(); } else if (reader.name() == "EX_GeographicBoundingBox") boundingBox = geographicBoundingBox(reader); else if (reader.name() == "Layer") layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox); else reader.skipCurrentElement(); } if (name == ctx.setup.layer()) { ctx.scaleDenominator = scaleDenominator; ctx.boundingBox = boundingBox; ctx.layer = true; ctx.style = styles.contains(ctx.setup.style()); ctx.crs = CRSs.contains(ctx.setup.crs()); } } void WMS::capability(QXmlStreamReader &reader, CTX &ctx) { QList CRSs; QList styles; RangeF scaleDenominator(2132.729583849784, 559082264.0287178); RectC boundingBox; while (reader.readNextStartElement()) { if (reader.name() == "Layer") layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox); else if (reader.name() == "Request") request(reader, ctx); else reader.skipCurrentElement(); } } void WMS::capabilities(QXmlStreamReader &reader, CTX &ctx) { _version = reader.attributes().value("version").toString(); while (reader.readNextStartElement()) { if (reader.name() == "Capability") capability(reader, ctx); else reader.skipCurrentElement(); } } bool WMS::parseCapabilities(const QString &path, const Setup &setup) { QFile file(path); CTX ctx(setup); QXmlStreamReader reader; if (!file.open(QFile::ReadOnly | QFile::Text)) { _errorString = file.errorString(); return false; } reader.setDevice(&file); if (reader.readNextStartElement()) { if (reader.name() == "WMS_Capabilities" || reader.name() == "WMT_MS_Capabilities") capabilities(reader, ctx); else reader.raiseError("Not a WMS Capabilities XML file"); } if (reader.error()) { _errorString = QString("%1:%2: %3").arg(path).arg(reader.lineNumber()) .arg(reader.errorString()); return false; } if (!ctx.layer) { _errorString = ctx.setup.layer() + ": layer not provided"; return false; } if (!ctx.style) { _errorString = ctx.setup.style() + ": style not provided"; return false; } if (!ctx.format) { _errorString = ctx.setup.format() + ": format not provided"; return false; } if (!ctx.crs) { _errorString = ctx.setup.crs() + ": CRS not provided"; return false; } _projection = CRS::projection(ctx.setup.crs()); if (_projection.isNull()) { _errorString = ctx.setup.crs() + ": unknown CRS"; return false; } if (!ctx.scaleDenominator.isValid()) { _errorString = "Invalid scale denominator range"; return false; } if (ctx.boundingBox.isNull()) { _errorString = "Missing bounding box"; return false; } _boundingBox = ctx.boundingBox; _scaleDenominator = ctx.scaleDenominator; return true; } bool WMS::getCapabilities(const QString &url, const QString &file, const Authorization &authorization) { QList dl; dl.append(Download(url, file)); QEventLoop wait; QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit())); if (_downloader->get(dl, authorization)) wait.exec(); if (QFileInfo(file).exists()) return true; else { _errorString = "Error downloading capabilities XML file"; return false; } } WMS::WMS(const QString &file, const WMS::Setup &setup) : _valid(false) { QString capaUrl = QString("%1?service=WMS&request=GetCapabilities") .arg(setup.url()); if (!QFileInfo(file).exists()) if (!getCapabilities(capaUrl, file, setup.authorization())) return; if (!parseCapabilities(file, setup)) return; _valid = true; }