1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-27 21:24:47 +01:00

Do not depend on the file extension when loading the maps

This commit is contained in:
Martin Tůma 2022-04-29 23:16:10 +02:00
parent 40febb8c0e
commit 93aadb7e74
34 changed files with 225 additions and 99 deletions

View File

@ -424,6 +424,14 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
painter->drawPixmap(tp, pixmap); 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 #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const AQMMap::File &file) QDebug operator<<(QDebug dbg, const AQMMap::File &file)
{ {

View File

@ -39,6 +39,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
struct File { struct File {
QByteArray name; QByteArray name;

View File

@ -293,19 +293,10 @@ void Atlas::unload()
_maps.at(i)->unload(); _maps.at(i)->unload();
} }
bool Atlas::isAtlas(const QString &path) Map *Atlas::create(const QString &path, const Projection &, bool *isDir)
{ {
QFileInfo fi(path); if (isDir)
QString suffix = fi.suffix().toLower(); *isDir = true;
if (suffix == "tar") { return new Atlas(path);
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;
} }

View File

@ -34,7 +34,7 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static bool isAtlas(const QString &path); static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
struct Zoom { struct Zoom {

View File

@ -461,3 +461,11 @@ void BSBMap::unload()
delete _img; delete _img;
_img = 0; _img = 0;
} }
Map *BSBMap::create(const QString &path, const Projection &, bool *isMap)
{
if (isMap)
*isMap = false;
return new BSBMap(path);
}

View File

@ -32,6 +32,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isMap);
private: private:
bool parseBSB(const QByteArray &line); bool parseBSB(const QByteArray &line);
bool parseKNP(const QByteArray &line, QString &datum, QString &proj, bool parseKNP(const QByteArray &line, QString &datum, QString &proj,

View File

@ -74,3 +74,11 @@ void GeoTIFFMap::unload()
delete _img; delete _img;
_img = 0; _img = 0;
} }
Map *GeoTIFFMap::create(const QString &path, const Projection &, bool *isDir)
{
if (isDir)
*isDir = false;
return new GeoTIFFMap(path);
}

View File

@ -28,6 +28,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
Projection _projection; Projection _projection;
Transform _transform; Transform _transform;

View File

@ -222,3 +222,11 @@ void IMGMap::setOutputProjection(const Projection &projection)
updateTransform(); updateTransform();
QPixmapCache::clear(); QPixmapCache::clear();
} }
Map* IMGMap::create(const QString &path, const Projection &, bool *isDir)
{
if (isDir)
*isDir = GMAPData::isGMAP(path);
return new IMGMap(path);
}

View File

@ -41,6 +41,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map* create(const QString &path, const Projection &, bool *isDir);
private: private:
Transform transform(int zoom) const; Transform transform(int zoom) const;
void updateTransform(); void updateTransform();

View File

@ -63,9 +63,12 @@ bool JNXMap::readTiles()
&& readValue(levels))) && readValue(levels)))
return false; return false;
if (version < 3 || version > 4)
return false;
_bounds = RectC(Coordinates(ic2dc(lon1), ic2dc(lat1)), _bounds = RectC(Coordinates(ic2dc(lon1), ic2dc(lat1)),
Coordinates(ic2dc(lon2), ic2dc(lat2))); Coordinates(ic2dc(lon2), ic2dc(lat2)));
if (!levels || !_bounds.isValid()) if (!levels || levels > 32 || !_bounds.isValid())
return false; return false;
if (!_file.seek(version > 3 ? 0x34 : 0x30)) 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);
}

View File

@ -42,6 +42,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir);
private: private:
struct Tile { struct Tile {
qint32 top, right, bottom, left; qint32 top, right, bottom, left;

View File

@ -513,3 +513,11 @@ void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex,
map.draw(painter, pr, flags); map.draw(painter, pr, flags);
painter->restore(); painter->restore();
} }
Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir)
{
if (isDir)
*isDir = false;
return new KMZMap(path, proj);
}

View File

@ -39,6 +39,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir);
private: private:
class Overlay { class Overlay {
public: public:

View File

@ -1,7 +1,6 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QApplication> #include <QApplication>
#include "IMG/gmapdata.h"
#include "atlas.h" #include "atlas.h"
#include "ozimap.h" #include "ozimap.h"
#include "jnxmap.h" #include "jnxmap.h"
@ -21,54 +20,67 @@
#include "maplist.h" #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) Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
{ {
ParserMap::iterator it;
QFileInfo fi(path); QFileInfo fi(path);
QString suffix = fi.suffix().toLower(); QString suffix(fi.suffix().toLower());
Map *map = 0; Map *map = 0;
if (Atlas::isAtlas(path)) { if ((it = _parsers.find(suffix)) != _parsers.end()) {
if (isDir) while (it != _parsers.end() && it.key() == suffix) {
*isDir = true; delete map;
map = new Atlas(path); map = it.value()(path, proj, isDir);
} else if (suffix == "xml") { if (map->isValid())
if (MapSource::isMap(path)) { break;
map = MapSource::loadMap(path);
} else if (IMG::GMAPData::isGMAP(path)) { ++it;
map = new IMGMap(path); }
if (isDir) } else {
*isDir = true; for (it = _parsers.begin(); it != _parsers.end(); it++) {
map = it.value()(path, proj, isDir);
if (map->isValid())
break;
else {
delete map;
map = 0;
}
}
} }
} 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);
return map ? map : new InvalidMap(path, "Unknown file format"); 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", "GeoTIFF images") + " (*.tif *.tiff);;"
+ qApp->translate("MapList", "World-file georeferenced images") + qApp->translate("MapList", "World-file georeferenced images")
+ " (*.wld *.jgw *.gfw *.pgw *.tfw);;" + " (*.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 MapList::filter()
{ {
QStringList filter; QStringList filter;
filter << "*.aqm" << "*.gfw" << "*.gmap" << "*.gmapi" << "*.img" << "*.jgw" QString last;
<< "*.jnx" << "*.kap" << "*.kmz" << "*.map" << "*.mbtiles" << "*.pgw"
<< "*.qct" << "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba" for (ParserMap::iterator it = _parsers.begin(); it != _parsers.end(); it++) {
<< "*.tfw" << "*.tif" << "*.tiff" << "*.wld" << "*.xml"; if (it.key() != last)
filter << "*." + it.key();
last = it.key();
}
return filter; return filter;
} }

View File

@ -15,10 +15,16 @@ public:
static QStringList filter(); static QStringList filter();
private: private:
typedef Map*(*ParserCb)(const QString &, const Projection &, bool *isDir);
typedef QMultiMap<QString, ParserCb> ParserMap;
static Map *loadFile(const QString &path, const Projection &proj, static Map *loadFile(const QString &path, const Projection &proj,
bool *isDir = 0); bool *isDir = 0);
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj, static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
TreeNode<Map *> *parent = 0); TreeNode<Map *> *parent = 0);
static ParserMap parsers();
static ParserMap _parsers;
}; };
#endif // MAPLIST_H #endif // MAPLIST_H

View File

@ -382,7 +382,7 @@ bool MapData::readHeader()
return true; 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)) { if (!_file.open(QFile::ReadOnly | QIODevice::Unbuffered)) {
_errorString = _file.errorString(); _errorString = _file.errorString();
@ -682,19 +682,6 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
return true; 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 #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag) QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag)
{ {

View File

@ -81,8 +81,6 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static bool isMapsforge(const QString &path);
private: private:
struct SubFileInfo { struct SubFileInfo {
quint8 base; quint8 base;

View File

@ -23,8 +23,10 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _data(fileName), _zoom(0), : Map(fileName, parent), _data(fileName), _zoom(0),
_projection(PCS::pcs(3857)), _tileRatio(1.0) _projection(PCS::pcs(3857)), _tileRatio(1.0)
{ {
if (_data.isValid()) {
_zoom = _data.zooms().min(); _zoom = _data.zooms().min();
updateTransform(); updateTransform();
}
} }
void MapsforgeMap::load() void MapsforgeMap::load()
@ -233,3 +235,11 @@ void MapsforgeMap::setOutputProjection(const Projection &projection)
updateTransform(); updateTransform();
QPixmapCache::clear(); QPixmapCache::clear();
} }
Map *MapsforgeMap::create(const QString &path, const Projection &, bool *isMap)
{
if (isMap)
*isMap = false;
return new MapsforgeMap(path);
}

View File

@ -71,6 +71,8 @@ public:
bool isValid() const {return _data.isValid();} bool isValid() const {return _data.isValid();}
QString errorString() const {return _data.errorString();} QString errorString() const {return _data.errorString();}
static Map *create(const QString &path, const Projection &, bool *isMap);
private slots: private slots:
void jobFinished(MapsforgeMapJob *job); void jobFinished(MapsforgeMapJob *job);

View File

@ -206,26 +206,16 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
} }
} }
bool MapSource::isMap(const QString &path) Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir)
{
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)
{ {
Q_UNUSED(proj);
Config config; Config config;
QFile file(path); QFile file(path);
if (isDir)
*isDir = false;
if (!file.open(QFile::ReadOnly | QFile::Text)) if (!file.open(QFile::ReadOnly | QFile::Text))
return new InvalidMap(path, file.errorString()); return new InvalidMap(path, file.errorString());

View File

@ -10,12 +10,12 @@
class Map; class Map;
class QXmlStreamReader; class QXmlStreamReader;
class Projection;
class MapSource class MapSource
{ {
public: public:
static Map *loadMap(const QString &path); static Map *create(const QString &path, const Projection &proj, bool *isDir);
static bool isMap(const QString &path);
private: private:
enum Type { enum Type {

View File

@ -332,3 +332,11 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p)
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale)
* coordinatesRatio()); * coordinatesRatio());
} }
Map *MBTilesMap::create(const QString &path, const Projection &, bool *isDir)
{
if (isDir)
*isDir = false;
return new MBTilesMap(path);
}

View File

@ -34,6 +34,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
qreal tileSize() const; qreal tileSize() const;
qreal coordinatesRatio() const; qreal coordinatesRatio() const;

View File

@ -379,3 +379,11 @@ void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
if (_img) if (_img)
_img->setDevicePixelRatio(_mapRatio); _img->setDevicePixelRatio(_mapRatio);
} }
Map *OziMap::create(const QString &path, const Projection &, bool *isDir)
{
if (isDir)
*isDir = true;
return new OziMap(path);
}

View File

@ -47,6 +47,8 @@ public:
QPointF pp2xy(const PointD &p) const QPointF pp2xy(const PointD &p) const
{return _transform.proj2img(p) / _mapRatio;} {return _transform.proj2img(p) / _mapRatio;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
struct ImageInfo { struct ImageInfo {
QSize size; QSize size;

View File

@ -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);
}

View File

@ -30,6 +30,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
bool readName(QDataStream &stream); bool readName(QDataStream &stream);
bool readSize(QDataStream &stream); bool readSize(QDataStream &stream);

View File

@ -458,3 +458,11 @@ void RMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
Q_UNUSED(deviceRatio); Q_UNUSED(deviceRatio);
_mapRatio = mapRatio; _mapRatio = mapRatio;
} }
Map *RMap::create(const QString &path, const Projection &, bool *isDir)
{
if (isDir)
*isDir = false;
return new RMap(path);
}

View File

@ -34,6 +34,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
struct Header { struct Header {
quint32 type; quint32 type;

View File

@ -271,3 +271,11 @@ Coordinates SqliteMap::xy2ll(const QPointF &p)
qreal scale = OSM::zoom2scale(_zoom, _tileSize); qreal scale = OSM::zoom2scale(_zoom, _tileSize);
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio); 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);
}

View File

@ -32,6 +32,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir);
private: private:
int limitZoom(int zoom) const; int limitZoom(int zoom) const;
qreal tileSize() const; qreal tileSize() const;

View File

@ -121,3 +121,12 @@ void WorldFileMap::setInputProjection(const Projection &projection)
_projection = projection; _projection = projection;
} }
Map *WorldFileMap::create(const QString &path, const Projection &proj,
bool *isDir)
{
if (isDir)
*isDir = false;
return new WorldFileMap(path, proj);
}

View File

@ -12,7 +12,8 @@ class WorldFileMap : public Map
Q_OBJECT Q_OBJECT
public: public:
WorldFileMap(const QString &fileName, const Projection &proj, QObject *parent = 0); WorldFileMap(const QString &fileName, const Projection &proj,
QObject *parent = 0);
~WorldFileMap(); ~WorldFileMap();
QRectF bounds(); QRectF bounds();
@ -29,6 +30,8 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir);
private: private:
Projection _projection; Projection _projection;
Transform _transform; Transform _transform;