diff --git a/src/map/aqmmap.cpp b/src/map/aqmmap.cpp index c12db33e..7717d58a 100644 --- a/src/map/aqmmap.cpp +++ b/src/map/aqmmap.cpp @@ -424,6 +424,14 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp) painter->drawPixmap(tp, pixmap); } +Map *AQMMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new AQMMap(path); +} + #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const AQMMap::File &file) { diff --git a/src/map/aqmmap.h b/src/map/aqmmap.h index f1f0f86e..1d85513e 100644 --- a/src/map/aqmmap.h +++ b/src/map/aqmmap.h @@ -39,6 +39,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: struct File { QByteArray name; diff --git a/src/map/atlas.cpp b/src/map/atlas.cpp index 88cad7b3..e3474f22 100644 --- a/src/map/atlas.cpp +++ b/src/map/atlas.cpp @@ -293,19 +293,10 @@ void Atlas::unload() _maps.at(i)->unload(); } -bool Atlas::isAtlas(const QString &path) +Map *Atlas::create(const QString &path, const Projection &, bool *isDir) { - QFileInfo fi(path); - QString suffix = fi.suffix().toLower(); + if (isDir) + *isDir = true; - if (suffix == "tar") { - Tar tar(path); - if (!tar.open()) - return false; - QString tbaFileName = fi.completeBaseName() + ".tba"; - return tar.contains(tbaFileName); - } else if (suffix == "tba") - return true; - - return false; + return new Atlas(path); } diff --git a/src/map/atlas.h b/src/map/atlas.h index 3a10d2db..9648cba5 100644 --- a/src/map/atlas.h +++ b/src/map/atlas.h @@ -34,7 +34,7 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static bool isAtlas(const QString &path); + static Map *create(const QString &path, const Projection &, bool *isDir); private: struct Zoom { diff --git a/src/map/bsbmap.cpp b/src/map/bsbmap.cpp index 3758a50f..18746428 100644 --- a/src/map/bsbmap.cpp +++ b/src/map/bsbmap.cpp @@ -461,3 +461,11 @@ void BSBMap::unload() delete _img; _img = 0; } + +Map *BSBMap::create(const QString &path, const Projection &, bool *isMap) +{ + if (isMap) + *isMap = false; + + return new BSBMap(path); +} diff --git a/src/map/bsbmap.h b/src/map/bsbmap.h index ee323ee7..c2c8a640 100644 --- a/src/map/bsbmap.h +++ b/src/map/bsbmap.h @@ -32,6 +32,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isMap); + private: bool parseBSB(const QByteArray &line); bool parseKNP(const QByteArray &line, QString &datum, QString &proj, diff --git a/src/map/geotiffmap.cpp b/src/map/geotiffmap.cpp index 9d3b87cb..59e4717f 100644 --- a/src/map/geotiffmap.cpp +++ b/src/map/geotiffmap.cpp @@ -74,3 +74,11 @@ void GeoTIFFMap::unload() delete _img; _img = 0; } + +Map *GeoTIFFMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new GeoTIFFMap(path); +} diff --git a/src/map/geotiffmap.h b/src/map/geotiffmap.h index 85761720..44cef4e6 100644 --- a/src/map/geotiffmap.h +++ b/src/map/geotiffmap.h @@ -28,6 +28,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: Projection _projection; Transform _transform; diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index befa292a..35ffca2e 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -222,3 +222,11 @@ void IMGMap::setOutputProjection(const Projection &projection) updateTransform(); QPixmapCache::clear(); } + +Map* IMGMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = GMAPData::isGMAP(path); + + return new IMGMap(path); +} diff --git a/src/map/imgmap.h b/src/map/imgmap.h index 068e2932..fb41140c 100644 --- a/src/map/imgmap.h +++ b/src/map/imgmap.h @@ -41,6 +41,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map* create(const QString &path, const Projection &, bool *isDir); + private: Transform transform(int zoom) const; void updateTransform(); diff --git a/src/map/jnxmap.cpp b/src/map/jnxmap.cpp index ddab2b41..26df7310 100644 --- a/src/map/jnxmap.cpp +++ b/src/map/jnxmap.cpp @@ -63,9 +63,12 @@ bool JNXMap::readTiles() && readValue(levels))) return false; + if (version < 3 || version > 4) + return false; + _bounds = RectC(Coordinates(ic2dc(lon1), ic2dc(lat1)), Coordinates(ic2dc(lon2), ic2dc(lat2))); - if (!levels || !_bounds.isValid()) + if (!levels || levels > 32 || !_bounds.isValid()) return false; if (!_file.seek(version > 3 ? 0x34 : 0x30)) @@ -304,3 +307,11 @@ void JNXMap::setInputProjection(const Projection &projection) } } } + +Map *JNXMap::create(const QString &path, const Projection &proj, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new JNXMap(path, proj); +} diff --git a/src/map/jnxmap.h b/src/map/jnxmap.h index 82c0f27f..947c2584 100644 --- a/src/map/jnxmap.h +++ b/src/map/jnxmap.h @@ -42,6 +42,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &proj, bool *isDir); + private: struct Tile { qint32 top, right, bottom, left; diff --git a/src/map/kmzmap.cpp b/src/map/kmzmap.cpp index 7218a8cb..ebfdfeaa 100644 --- a/src/map/kmzmap.cpp +++ b/src/map/kmzmap.cpp @@ -513,3 +513,11 @@ void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex, map.draw(painter, pr, flags); painter->restore(); } + +Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new KMZMap(path, proj); +} diff --git a/src/map/kmzmap.h b/src/map/kmzmap.h index dd1b227a..155c6b40 100644 --- a/src/map/kmzmap.h +++ b/src/map/kmzmap.h @@ -39,6 +39,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &proj, bool *isDir); + private: class Overlay { public: diff --git a/src/map/maplist.cpp b/src/map/maplist.cpp index 2925be7c..81fc59ba 100644 --- a/src/map/maplist.cpp +++ b/src/map/maplist.cpp @@ -1,7 +1,6 @@ #include #include #include -#include "IMG/gmapdata.h" #include "atlas.h" #include "ozimap.h" #include "jnxmap.h" @@ -21,54 +20,67 @@ #include "maplist.h" +MapList::ParserMap MapList::parsers() +{ + MapList::ParserMap map; + + map.insert("tar", &Atlas::create); + map.insert("tar", &OziMap::create); + map.insert("tba", &Atlas::create); + map.insert("xml", &MapSource::create); + map.insert("xml", &IMGMap::create); + map.insert("img", &IMGMap::create); + map.insert("jnx", &JNXMap::create); + map.insert("tif", &GeoTIFFMap::create); + map.insert("tiff", &GeoTIFFMap::create); + map.insert("mbtiles", &MBTilesMap::create); + map.insert("rmap", &RMap::create); + map.insert("rtmap", &RMap::create); + map.insert("map", &MapsforgeMap::create); + map.insert("map", &OziMap::create); + map.insert("kap", &BSBMap::create); + map.insert("kmz", &KMZMap::create); + map.insert("aqm", &AQMMap::create); + map.insert("sqlitedb", &SqliteMap::create); + map.insert("wld", &WorldFileMap::create); + map.insert("jgw", &WorldFileMap::create); + map.insert("gfw", &WorldFileMap::create); + map.insert("pgw", &WorldFileMap::create); + map.insert("tfw", &WorldFileMap::create); + map.insert("qct", &QCTMap::create); + + return map; +} + +MapList::ParserMap MapList::_parsers = parsers(); + Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir) { + ParserMap::iterator it; QFileInfo fi(path); - QString suffix = fi.suffix().toLower(); + QString suffix(fi.suffix().toLower()); Map *map = 0; - if (Atlas::isAtlas(path)) { - if (isDir) - *isDir = true; - map = new Atlas(path); - } else if (suffix == "xml") { - if (MapSource::isMap(path)) { - map = MapSource::loadMap(path); - } else if (IMG::GMAPData::isGMAP(path)) { - map = new IMGMap(path); - if (isDir) - *isDir = true; + if ((it = _parsers.find(suffix)) != _parsers.end()) { + while (it != _parsers.end() && it.key() == suffix) { + delete map; + map = it.value()(path, proj, isDir); + if (map->isValid()) + break; + + ++it; } - } else if (suffix == "jnx") - map = new JNXMap(path, proj); - else if (suffix == "tif" || suffix == "tiff") - map = new GeoTIFFMap(path); - else if (suffix == "mbtiles") - map = new MBTilesMap(path); - else if (suffix == "rmap" || suffix == "rtmap") - map = new RMap(path); - else if (suffix == "img") - map = new IMGMap(path); - else if (suffix == "map") { - if (Mapsforge::MapData::isMapsforge(path)) - map = new MapsforgeMap(path); - else - map = new OziMap(path); - } else if (suffix == "tar") - map = new OziMap(path); - else if (suffix == "kap") - map = new BSBMap(path); - else if (suffix == "kmz") - map = new KMZMap(path, proj); - else if (suffix == "aqm") - map = new AQMMap(path); - else if (suffix == "sqlitedb") - map = new SqliteMap(path); - else if (suffix == "wld" || suffix == "jgw" || suffix == "gfw" - || suffix == "pgw" || suffix == "tfw") - map = new WorldFileMap(path, proj); - else if (suffix == "qct") - map = new QCTMap(path); + } else { + for (it = _parsers.begin(); it != _parsers.end(); it++) { + map = it.value()(path, proj, isDir); + if (map->isValid()) + break; + else { + delete map; + map = 0; + } + } + } return map ? map : new InvalidMap(path, "Unknown file format"); } @@ -140,15 +152,20 @@ QString MapList::formats() + qApp->translate("MapList", "GeoTIFF images") + " (*.tif *.tiff);;" + qApp->translate("MapList", "World-file georeferenced images") + " (*.wld *.jgw *.gfw *.pgw *.tfw);;" - + qApp->translate("MapList", "Online map sources") + " (*.xml)"; + + qApp->translate("MapList", "Online map sources") + " (*.xml);;" + + qApp->translate("MapList", "All files") + " (*)"; } QStringList MapList::filter() { QStringList filter; - filter << "*.aqm" << "*.gfw" << "*.gmap" << "*.gmapi" << "*.img" << "*.jgw" - << "*.jnx" << "*.kap" << "*.kmz" << "*.map" << "*.mbtiles" << "*.pgw" - << "*.qct" << "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba" - << "*.tfw" << "*.tif" << "*.tiff" << "*.wld" << "*.xml"; + QString last; + + for (ParserMap::iterator it = _parsers.begin(); it != _parsers.end(); it++) { + if (it.key() != last) + filter << "*." + it.key(); + last = it.key(); + } + return filter; } diff --git a/src/map/maplist.h b/src/map/maplist.h index 2c84b3ec..3bf8153c 100644 --- a/src/map/maplist.h +++ b/src/map/maplist.h @@ -15,10 +15,16 @@ public: static QStringList filter(); private: + typedef Map*(*ParserCb)(const QString &, const Projection &, bool *isDir); + typedef QMultiMap ParserMap; + static Map *loadFile(const QString &path, const Projection &proj, bool *isDir = 0); static TreeNode loadDir(const QString &path, const Projection &proj, TreeNode *parent = 0); + + static ParserMap parsers(); + static ParserMap _parsers; }; #endif // MAPLIST_H diff --git a/src/map/mapsforge/mapdata.cpp b/src/map/mapsforge/mapdata.cpp index 3269a14f..86382e98 100644 --- a/src/map/mapsforge/mapdata.cpp +++ b/src/map/mapsforge/mapdata.cpp @@ -382,7 +382,7 @@ bool MapData::readHeader() return true; } -MapData::MapData(const QString &fileName) : _file(fileName) +MapData::MapData(const QString &fileName) : _file(fileName), _valid(false) { if (!_file.open(QFile::ReadOnly | QIODevice::Unbuffered)) { _errorString = _file.errorString(); @@ -682,19 +682,6 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList *list) return true; } -bool MapData::isMapsforge(const QString &path) -{ - QFile file(path); - char magic[sizeof(MAGIC) - 1]; - - if (!file.open(QFile::ReadOnly)) - return false; - if (file.read(magic, sizeof(magic)) < (qint64)sizeof(magic)) - return false; - - return !memcmp(magic, MAGIC, sizeof(magic)); -} - #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag) { diff --git a/src/map/mapsforge/mapdata.h b/src/map/mapsforge/mapdata.h index a65b49ca..a278ac54 100644 --- a/src/map/mapsforge/mapdata.h +++ b/src/map/mapsforge/mapdata.h @@ -81,8 +81,6 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static bool isMapsforge(const QString &path); - private: struct SubFileInfo { quint8 base; diff --git a/src/map/mapsforgemap.cpp b/src/map/mapsforgemap.cpp index dfa3ae49..947e94ea 100644 --- a/src/map/mapsforgemap.cpp +++ b/src/map/mapsforgemap.cpp @@ -23,8 +23,10 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent) : Map(fileName, parent), _data(fileName), _zoom(0), _projection(PCS::pcs(3857)), _tileRatio(1.0) { - _zoom = _data.zooms().min(); - updateTransform(); + if (_data.isValid()) { + _zoom = _data.zooms().min(); + updateTransform(); + } } void MapsforgeMap::load() @@ -233,3 +235,11 @@ void MapsforgeMap::setOutputProjection(const Projection &projection) updateTransform(); QPixmapCache::clear(); } + +Map *MapsforgeMap::create(const QString &path, const Projection &, bool *isMap) +{ + if (isMap) + *isMap = false; + + return new MapsforgeMap(path); +} diff --git a/src/map/mapsforgemap.h b/src/map/mapsforgemap.h index 904def40..488b9ea9 100644 --- a/src/map/mapsforgemap.h +++ b/src/map/mapsforgemap.h @@ -71,6 +71,8 @@ public: bool isValid() const {return _data.isValid();} QString errorString() const {return _data.errorString();} + static Map *create(const QString &path, const Projection &, bool *isMap); + private slots: void jobFinished(MapsforgeMapJob *job); diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index 49569e84..dbf08db6 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -206,26 +206,16 @@ void MapSource::map(QXmlStreamReader &reader, Config &config) } } -bool MapSource::isMap(const QString &path) -{ - QFile file(path); - - if (!file.open(QFile::ReadOnly | QFile::Text)) - return false; - - QXmlStreamReader reader(&file); - if (reader.readNextStartElement() && reader.name() == QLatin1String("map")) - return true; - - return false; -} - -Map *MapSource::loadMap(const QString &path) +Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir) { + Q_UNUSED(proj); Config config; QFile file(path); + if (isDir) + *isDir = false; + if (!file.open(QFile::ReadOnly | QFile::Text)) return new InvalidMap(path, file.errorString()); diff --git a/src/map/mapsource.h b/src/map/mapsource.h index 29ba96b4..7c9d045e 100644 --- a/src/map/mapsource.h +++ b/src/map/mapsource.h @@ -10,12 +10,12 @@ class Map; class QXmlStreamReader; +class Projection; class MapSource { public: - static Map *loadMap(const QString &path); - static bool isMap(const QString &path); + static Map *create(const QString &path, const Projection &proj, bool *isDir); private: enum Type { diff --git a/src/map/mbtilesmap.cpp b/src/map/mbtilesmap.cpp index cf647f72..7af7047c 100644 --- a/src/map/mbtilesmap.cpp +++ b/src/map/mbtilesmap.cpp @@ -332,3 +332,11 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p) return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * coordinatesRatio()); } + +Map *MBTilesMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new MBTilesMap(path); +} diff --git a/src/map/mbtilesmap.h b/src/map/mbtilesmap.h index 73efe2d1..d7cf56ff 100644 --- a/src/map/mbtilesmap.h +++ b/src/map/mbtilesmap.h @@ -34,6 +34,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: qreal tileSize() const; qreal coordinatesRatio() const; diff --git a/src/map/ozimap.cpp b/src/map/ozimap.cpp index f1fd1d40..e8cd901e 100644 --- a/src/map/ozimap.cpp +++ b/src/map/ozimap.cpp @@ -379,3 +379,11 @@ void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) if (_img) _img->setDevicePixelRatio(_mapRatio); } + +Map *OziMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = true; + + return new OziMap(path); +} diff --git a/src/map/ozimap.h b/src/map/ozimap.h index 6e2cf86c..b027a534 100644 --- a/src/map/ozimap.h +++ b/src/map/ozimap.h @@ -47,6 +47,8 @@ public: QPointF pp2xy(const PointD &p) const {return _transform.proj2img(p) / _mapRatio;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: struct ImageInfo { QSize size; diff --git a/src/map/qctmap.cpp b/src/map/qctmap.cpp index f4786e18..cebb70d7 100644 --- a/src/map/qctmap.cpp +++ b/src/map/qctmap.cpp @@ -485,3 +485,11 @@ void QCTMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } } + +Map *QCTMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new QCTMap(path); +} diff --git a/src/map/qctmap.h b/src/map/qctmap.h index 3758933d..a29bf728 100644 --- a/src/map/qctmap.h +++ b/src/map/qctmap.h @@ -30,6 +30,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: bool readName(QDataStream &stream); bool readSize(QDataStream &stream); diff --git a/src/map/rmap.cpp b/src/map/rmap.cpp index be0fb38e..931b9121 100644 --- a/src/map/rmap.cpp +++ b/src/map/rmap.cpp @@ -458,3 +458,11 @@ void RMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Q_UNUSED(deviceRatio); _mapRatio = mapRatio; } + +Map *RMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new RMap(path); +} diff --git a/src/map/rmap.h b/src/map/rmap.h index 22c12415..7eed061f 100644 --- a/src/map/rmap.h +++ b/src/map/rmap.h @@ -34,6 +34,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: struct Header { quint32 type; diff --git a/src/map/sqlitemap.cpp b/src/map/sqlitemap.cpp index 41285568..b2b065da 100644 --- a/src/map/sqlitemap.cpp +++ b/src/map/sqlitemap.cpp @@ -271,3 +271,11 @@ Coordinates SqliteMap::xy2ll(const QPointF &p) qreal scale = OSM::zoom2scale(_zoom, _tileSize); return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio); } + +Map *SqliteMap::create(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = false; + + return new SqliteMap(path); +} diff --git a/src/map/sqlitemap.h b/src/map/sqlitemap.h index bf2cbaa8..99285304 100644 --- a/src/map/sqlitemap.h +++ b/src/map/sqlitemap.h @@ -32,6 +32,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &, bool *isDir); + private: int limitZoom(int zoom) const; qreal tileSize() const; diff --git a/src/map/worldfilemap.cpp b/src/map/worldfilemap.cpp index 5eb5fed9..a5faab49 100644 --- a/src/map/worldfilemap.cpp +++ b/src/map/worldfilemap.cpp @@ -121,3 +121,12 @@ void WorldFileMap::setInputProjection(const Projection &projection) _projection = projection; } + +Map *WorldFileMap::create(const QString &path, const Projection &proj, + bool *isDir) +{ + if (isDir) + *isDir = false; + + return new WorldFileMap(path, proj); +} diff --git a/src/map/worldfilemap.h b/src/map/worldfilemap.h index b359864c..59ec3518 100644 --- a/src/map/worldfilemap.h +++ b/src/map/worldfilemap.h @@ -12,7 +12,8 @@ class WorldFileMap : public Map Q_OBJECT public: - WorldFileMap(const QString &fileName, const Projection &proj, QObject *parent = 0); + WorldFileMap(const QString &fileName, const Projection &proj, + QObject *parent = 0); ~WorldFileMap(); QRectF bounds(); @@ -29,6 +30,8 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} + static Map *create(const QString &path, const Projection &proj, bool *isDir); + private: Projection _projection; Transform _transform;