diff --git a/gpxsee.pro b/gpxsee.pro index 2c208b27..76d7861f 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -91,8 +91,10 @@ HEADERS += src/common/config.h \ src/map/IMG/bitmapline.h \ src/map/IMG/bitstream.h \ src/map/IMG/deltastream.h \ + src/map/IMG/gmap.h \ src/map/IMG/huffmanstream.h \ src/map/IMG/huffmantable.h \ + src/map/IMG/mapdata.h \ src/map/IMG/textpathitem.h \ src/map/IMG/textpointitem.h \ src/map/projection.h \ @@ -249,8 +251,10 @@ SOURCES += src/main.cpp \ src/map/IMG/bitmapline.cpp \ src/map/IMG/bitstream.cpp \ src/map/IMG/deltastream.cpp \ + src/map/IMG/gmap.cpp \ src/map/IMG/huffmanstream.cpp \ src/map/IMG/huffmantable.cpp \ + src/map/IMG/mapdata.cpp \ src/map/IMG/textpathitem.cpp \ src/map/IMG/textpointitem.cpp \ src/map/maplist.cpp \ diff --git a/src/map/IMG/bitstream.cpp b/src/map/IMG/bitstream.cpp index 6039bb80..771e32ff 100644 --- a/src/map/IMG/bitstream.cpp +++ b/src/map/IMG/bitstream.cpp @@ -32,7 +32,7 @@ bool BitStream1::read(int bits, quint32 &val) bool BitStream1::flush() { - if (_length && !_file.seek(_hdl, _hdl.pos + _length)) + if (_length && !_file.seek(_hdl, _hdl.pos() + _length)) return false; _length = 0; @@ -68,7 +68,7 @@ bool BitStream4::read(int bits, quint32 &val) bool BitStream4::flush() { - if (_length && !_file.seek(_hdl, _hdl.pos + _length)) + if (_length && !_file.seek(_hdl, _hdl.pos() + _length)) return false; _length = 0; diff --git a/src/map/IMG/gmap.cpp b/src/map/IMG/gmap.cpp new file mode 100644 index 00000000..c45e4699 --- /dev/null +++ b/src/map/IMG/gmap.cpp @@ -0,0 +1,151 @@ +#include +#include +#include "vectortile.h" +#include "gmap.h" + + +static SubFile::Type tileType(const QString &suffix) +{ + if (!suffix.compare("TRE")) + return SubFile::TRE; + else if (!suffix.compare("RGN")) + return SubFile::RGN; + else if (!suffix.compare("LBL")) + return SubFile::LBL; + else if (!suffix.compare("TYP")) + return SubFile::TYP; + else if (!suffix.compare("GMP")) + return SubFile::GMP; + else if (!suffix.compare("NET")) + return SubFile::NET; + else + return SubFile::Unknown; +} + +void GMAP::subProduct(QXmlStreamReader &reader, QString &dataDir, + QString &baseMap) +{ + while (reader.readNextStartElement()) { + if (reader.name() == "Directory") + dataDir = reader.readElementText(); + else if (reader.name() == "BaseMap") + baseMap = reader.readElementText(); + else + reader.skipCurrentElement(); + } +} + +void GMAP::mapProduct(QXmlStreamReader &reader, QString &dataDir, + QString &typFile, QString &baseMap) +{ + while (reader.readNextStartElement()) { + if (reader.name() == "Name") + _name = reader.readElementText(); + else if (reader.name() == "TYP") + typFile = reader.readElementText(); + else if (reader.name() == "SubProduct") + subProduct(reader, dataDir, baseMap); + else + reader.skipCurrentElement(); + } +} + +bool GMAP::readXML(const QString &path, QString &dataDir, QString &typFile, + QString &baseMap) +{ + QFile file(path); + + if (!file.open(QFile::ReadOnly | QFile::Text)) + return false; + + QXmlStreamReader reader(&file); + if (reader.readNextStartElement()) { + if (reader.name() == "MapProduct") + mapProduct(reader, dataDir, typFile, baseMap); + else + reader.raiseError("Not a GMAP XML file"); + } + if (reader.error()) { + _errorString = QString("%1: %2").arg(reader.lineNumber()) + .arg(reader.errorString()); + return false; + } + + return true; +} + +bool GMAP::loadTile(const QDir &dir, quint16 &id) +{ + VectorTile *tile = new VectorTile(); + + QFileInfoList ml = dir.entryInfoList(QDir::Files); + for (int i = 0; i < ml.size(); i++) { + const QFileInfo &fi = ml.at(i); + SubFile::Type type = tileType(fi.suffix()); + if (VectorTile::isTileFile(type)) { + SubFile *file = tile->addFile(fi.absoluteFilePath(), type); + file->setId(id++); + } + } + + if (!tile->init()) { + qWarning("%s: Invalid map tile", qPrintable(dir.path())); + delete tile; + return false; + } + + double min[2], max[2]; + min[0] = tile->bounds().left(); + min[1] = tile->bounds().bottom(); + max[0] = tile->bounds().right(); + max[1] = tile->bounds().top(); + _tileTree.Insert(min, max, tile); + + _bounds |= tile->bounds(); + + return true; +} + +GMAP::GMAP(const QString &fileName) : _fileName(fileName) +{ + QString dataDirPath, typFile, baseMap; + if (!readXML(fileName, dataDirPath, typFile, baseMap)) + return; + + QDir baseDir(QFileInfo(fileName).absoluteDir()); + if (!baseDir.exists(dataDirPath)) { + _errorString = "Missing/invalid map data directory"; + return; + } + QDir dataDir(baseDir.filePath(dataDirPath)); + QFileInfoList ml = dataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + + quint16 id = 0; + for (int i = 0; i < ml.size(); i++) { + const QFileInfo &fi = ml.at(i); + if (fi.isDir() && fi.baseName() != baseMap) + loadTile(QDir(fi.absoluteFilePath()), id); + } + + if (baseDir.exists(typFile)) + _typ = new SubFile(baseDir.filePath(typFile)); + + if (!_tileTree.Count()) + _errorString = "No usable map tile found"; + else + _valid = true; +} + +bool GMAP::isGMAP(const QString &path) +{ + QFile file(path); + + if (!file.open(QFile::ReadOnly | QFile::Text)) + return false; + + QXmlStreamReader reader(&file); + if (reader.readNextStartElement() && reader.name() == "MapProduct") + return true; + + return false; +} diff --git a/src/map/IMG/gmap.h b/src/map/IMG/gmap.h new file mode 100644 index 00000000..ed5d400d --- /dev/null +++ b/src/map/IMG/gmap.h @@ -0,0 +1,30 @@ +#ifndef GMAP_H +#define GMAP_H + +#include "mapdata.h" + +class QXmlStreamReader; +class QDir; + +class GMAP : public MapData +{ +public: + GMAP(const QString &fileName); + + QString fileName() const {return _fileName;} + + static bool isGMAP(const QString &path); + +private: + QString _fileName; + + bool readXML(const QString &path, QString &dataDir, QString &typFile, + QString &baseMap); + void mapProduct(QXmlStreamReader &reader, QString &dataDir, + QString &typFile, QString &baseMap); + void subProduct(QXmlStreamReader &reader, QString &dataDir, + QString &baseMap); + bool loadTile(const QDir &dir, quint16 &id); +}; + +#endif // GMAP_H diff --git a/src/map/IMG/huffmantable.cpp b/src/map/IMG/huffmantable.cpp index bb003258..cdf3c519 100644 --- a/src/map/IMG/huffmantable.cpp +++ b/src/map/IMG/huffmantable.cpp @@ -55,7 +55,7 @@ bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl, return false; if (!file.readVUInt32(hdl, recordSize)) return false; - recordOffset = hdl.pos + recordSize; + recordOffset = hdl.pos() + recordSize; if (recordOffset > offset + size) return false; }; diff --git a/src/map/IMG/img.cpp b/src/map/IMG/img.cpp index 2bed58ae..26dbcaab 100644 --- a/src/map/IMG/img.cpp +++ b/src/map/IMG/img.cpp @@ -1,6 +1,6 @@ #include #include -#include "common/programpaths.h" + #include "vectortile.h" #include "img.h" @@ -8,32 +8,6 @@ typedef QMap TileMap; -struct PolyCTX -{ - PolyCTX(const RectC &rect, int bits, QList *polygons, - QList *lines, QCache *polyCache) - : rect(rect), bits(bits), polygons(polygons), lines(lines), - polyCache(polyCache) {} - - const RectC ▭ - int bits; - QList *polygons; - QList *lines; - QCache *polyCache; -}; - -struct PointCTX -{ - PointCTX(const RectC &rect, int bits, QList *points, - QCache > *pointCache) - : rect(rect), bits(bits), points(points), pointCache(pointCache) {} - - const RectC ▭ - int bits; - QList *points; - QCache > *pointCache; -}; - static SubFile::Type tileType(const char str[3]) { if (!memcmp(str, "TRE", 3)) @@ -52,8 +26,7 @@ static SubFile::Type tileType(const char str[3]) return SubFile::Unknown; } -IMG::IMG(const QString &fileName) - : _file(fileName), _typ(0), _style(0), _valid(false) +IMG::IMG(const QString &fileName) : _file(fileName) { #define CHECK(condition) \ if (!(condition)) { \ @@ -191,86 +164,6 @@ IMG::IMG(const QString &fileName) _valid = true; } -IMG::~IMG() -{ - TileTree::Iterator it; - for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) - delete _tileTree.GetAt(it); - - delete _typ; - delete _style; -} - -void IMG::load() -{ - Q_ASSERT(!_style); - - if (_typ) - _style = new Style(_typ); - else { - QFile typFile(ProgramPaths::typFile()); - if (typFile.open(QIODevice::ReadOnly)) { - SubFile typ(&typFile); - _style = new Style(&typ); - } else - _style = new Style(); - } -} - -void IMG::clear() -{ - TileTree::Iterator it; - for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) - _tileTree.GetAt(it)->clear(); - - delete _style; - _style = 0; - - _polyCache.clear(); - _pointCache.clear(); -} - -static bool polyCb(VectorTile *tile, void *context) -{ - PolyCTX *ctx = (PolyCTX*)context; - tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache); - return true; -} - -static bool pointCb(VectorTile *tile, void *context) -{ - PointCTX *ctx = (PointCTX*)context; - tile->points(ctx->rect, ctx->bits, ctx->points, ctx->pointCache); - return true; -} - -void IMG::polys(const RectC &rect, int bits, QList *polygons, - QList *lines) -{ - PolyCTX ctx(rect, bits, polygons, lines, &_polyCache); - double min[2], max[2]; - - min[0] = rect.left(); - min[1] = rect.bottom(); - max[0] = rect.right(); - max[1] = rect.top(); - - _tileTree.Search(min, max, polyCb, &ctx); -} - -void IMG::points(const RectC &rect, int bits, QList *points) -{ - PointCTX ctx(rect, bits, points, &_pointCache); - double min[2], max[2]; - - min[0] = rect.left(); - min[1] = rect.bottom(); - max[0] = rect.right(); - max[1] = rect.top(); - - _tileTree.Search(min, max, pointCb, &ctx); -} - qint64 IMG::read(char *data, qint64 maxSize) { qint64 ret = _file.read(data, maxSize); @@ -292,28 +185,12 @@ template bool IMG::readValue(T &val) return true; } -bool IMG::readBlock(int blockNum, QByteArray &data) +bool IMG::readBlock(int blockNum, char *data) { if (!_file.seek((qint64)blockNum * (qint64)_blockSize)) return false; - data.resize(_blockSize); - if (read(data.data(), _blockSize) < _blockSize) + if (read(data, _blockSize) < _blockSize) return false; return true; } - -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const IMG::Point &point) -{ - dbg.nospace() << "Point(" << hex << point.type << ", " << point.label - << ", " << point.poi << ")"; - return dbg.space(); -} - -QDebug operator<<(QDebug dbg, const IMG::Poly &poly) -{ - dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")"; - return dbg.space(); -} -#endif // QT_NO_DEBUG diff --git a/src/map/IMG/img.h b/src/map/IMG/img.h index 6dd88ce9..7173a447 100644 --- a/src/map/IMG/img.h +++ b/src/map/IMG/img.h @@ -2,105 +2,26 @@ #define IMG_H #include -#include -#include -#include -#include "common/rtree.h" -#include "common/rectc.h" -#include "style.h" -#include "label.h" +#include "mapdata.h" -class VectorTile; -class SubFile; -class SubDiv; - -class IMG +class IMG : public MapData { public: - struct Poly { - /* QPointF insted of Coordinates for performance reasons (no need to - duplicate all the vectors for drawing). Note, that we do not want to - ll2xy() the points in the IMG class as this can not be done in - parallel. */ - QVector points; - Label label; - quint32 type; - RectC boundingRect; - - bool operator<(const Poly &other) const - {return type > other.type;} - }; - - struct Point { - Point() : id(0) {} - - Coordinates coordinates; - Label label; - quint32 type; - bool poi; - quint64 id; - - bool operator<(const Point &other) const - {return id < other.id;} - }; - - struct Polys { - Polys() {} - Polys(const QList &polygons, const QList &lines) - : polygons(polygons), lines(lines) {} - - QList polygons; - QList lines; - }; - IMG(const QString &fileName); - ~IMG(); - - void load(); - void clear(); QString fileName() const {return _file.fileName();} - const QString &name() const {return _name;} - const RectC &bounds() const {return _bounds;} - - void polys(const RectC &rect, int bits, QList *polygons, - QList *lines); - void points(const RectC &rect, int bits, QList *points); - const Style *style() const {return _style;} - - bool isValid() const {return _valid;} - const QString &errorString() const {return _errorString;} private: friend class SubFile; - typedef RTree TileTree; - int blockSize() const {return _blockSize;} - bool readBlock(int blockNum, QByteArray &data); + bool readBlock(int blockNum, char *data); qint64 read(char *data, qint64 maxSize); template bool readValue(T &val); QFile _file; quint8 _key; int _blockSize; - - QString _name; - RectC _bounds; - TileTree _tileTree; - SubFile *_typ; - Style *_style; - - QCache _polyCache; - QCache > _pointCache; - - bool _valid; - QString _errorString; }; -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const IMG::Point &point); -QDebug operator<<(QDebug dbg, const IMG::Poly &poly); -#endif // QT_NO_DEBUG - #endif // IMG_H diff --git a/src/map/IMG/lblfile.h b/src/map/IMG/lblfile.h index 493f4024..7eeb4ecc 100644 --- a/src/map/IMG/lblfile.h +++ b/src/map/IMG/lblfile.h @@ -12,6 +12,9 @@ public: LBLFile(IMG *img) : SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {} + LBLFile(const QString &path) + : SubFile(path), _codec(0), _offset(0), _size(0), _poiOffset(0), + _poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {} LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {} diff --git a/src/map/IMG/mapdata.cpp b/src/map/IMG/mapdata.cpp new file mode 100644 index 00000000..801fe78d --- /dev/null +++ b/src/map/IMG/mapdata.cpp @@ -0,0 +1,108 @@ +#include "common/programpaths.h" +#include "vectortile.h" +#include "style.h" +#include "mapdata.h" + + +struct PolyCTX +{ + PolyCTX(const RectC &rect, int bits, QList *polygons, + QList *lines, QCache *polyCache) : rect(rect), bits(bits), polygons(polygons), + lines(lines), polyCache(polyCache) {} + + const RectC ▭ + int bits; + QList *polygons; + QList *lines; + QCache *polyCache; +}; + +struct PointCTX +{ + PointCTX(const RectC &rect, int bits, QList *points, + QCache > *pointCache) + : rect(rect), bits(bits), points(points), pointCache(pointCache) {} + + const RectC ▭ + int bits; + QList *points; + QCache > *pointCache; +}; + +inline bool polyCb(VectorTile *tile, void *context) +{ + PolyCTX *ctx = (PolyCTX*)context; + tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache); + return true; +} + +inline bool pointCb(VectorTile *tile, void *context) +{ + PointCTX *ctx = (PointCTX*)context; + tile->points(ctx->rect, ctx->bits, ctx->points, ctx->pointCache); + return true; +} + + +MapData::~MapData() +{ + TileTree::Iterator it; + for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) + delete _tileTree.GetAt(it); + + delete _typ; + delete _style; +} + +void MapData::polys(const RectC &rect, int bits, QList *polygons, + QList *lines) +{ + PolyCTX ctx(rect, bits, polygons, lines, &_polyCache); + double min[2], max[2]; + + min[0] = rect.left(); + min[1] = rect.bottom(); + max[0] = rect.right(); + max[1] = rect.top(); + + _tileTree.Search(min, max, polyCb, &ctx); +} + +void MapData::points(const RectC &rect, int bits, QList *points) +{ + PointCTX ctx(rect, bits, points, &_pointCache); + double min[2], max[2]; + + min[0] = rect.left(); + min[1] = rect.bottom(); + max[0] = rect.right(); + max[1] = rect.top(); + + _tileTree.Search(min, max, pointCb, &ctx); +} + +void MapData::load() +{ + Q_ASSERT(!_style); + + if (_typ) + _style = new Style(_typ); + else { + SubFile typ(ProgramPaths::typFile()); + _style = new Style(&typ); + } +} + +void MapData::clear() +{ + TileTree::Iterator it; + for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) + _tileTree.GetAt(it)->clear(); + + delete _style; + _style = 0; + + _polyCache.clear(); + _pointCache.clear(); +} diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h new file mode 100644 index 00000000..ac14becb --- /dev/null +++ b/src/map/IMG/mapdata.h @@ -0,0 +1,105 @@ +#ifndef MAPDATA_H +#define MAPDATA_H + +#include +#include +#include +#include +#include "common/rectc.h" +#include "common/rtree.h" +#include "label.h" + +class Style; +class SubDiv; +class SubFile; +class VectorTile; + +class MapData +{ +public: + struct Poly { + /* QPointF insted of Coordinates for performance reasons (no need to + duplicate all the vectors for drawing). Note, that we do not want to + ll2xy() the points in the IMG class as this can not be done in + parallel. */ + QVector points; + Label label; + quint32 type; + RectC boundingRect; + + bool operator<(const Poly &other) const + {return type > other.type;} + }; + + struct Point { + Point() : id(0) {} + + Coordinates coordinates; + Label label; + quint32 type; + bool poi; + quint64 id; + + bool operator<(const Point &other) const + {return id < other.id;} + }; + + struct Polys { + Polys() {} + Polys(const QList &polygons, const QList &lines) + : polygons(polygons), lines(lines) {} + + QList polygons; + QList lines; + }; + + MapData() : _typ(0), _style(0), _valid(false) {} + virtual ~MapData(); + + const QString &name() const {return _name;} + const RectC &bounds() const {return _bounds;} + const Style *style() const {return _style;} + void polys(const RectC &rect, int bits, QList *polygons, + QList *lines); + void points(const RectC &rect, int bits, QList *points); + + void load(); + void clear(); + + virtual QString fileName() const = 0; + + bool isValid() const {return _valid;} + QString errorString() const {return _errorString;} + +protected: + typedef RTree TileTree; + + QString _name; + RectC _bounds; + SubFile *_typ; + Style *_style; + + TileTree _tileTree; + QCache _polyCache; + QCache > _pointCache; + + bool _valid; + QString _errorString; +}; + +#ifndef QT_NO_DEBUG +inline QDebug operator<<(QDebug dbg, const MapData::Point &point) +{ + dbg.nospace() << "Point(" << hex << point.type << ", " << point.label + << ", " << point.poi << ")"; + return dbg.space(); +} + +inline QDebug operator<<(QDebug dbg, const MapData::Poly &poly) +{ + dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")"; + return dbg.space(); +} +#endif // QT_NO_DEBUG + +#endif // MAPDATA_H diff --git a/src/map/IMG/netfile.h b/src/map/IMG/netfile.h index 9efba89d..bc0779ff 100644 --- a/src/map/IMG/netfile.h +++ b/src/map/IMG/netfile.h @@ -6,9 +6,12 @@ class NETFile : public SubFile { public: - NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _multiplier(0) {} - NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), - _offset(0), _size(0), _multiplier(0) {} + NETFile(IMG *img) + : SubFile(img), _offset(0), _size(0), _multiplier(0) {} + NETFile(const QString &path) + : SubFile(path), _offset(0), _size(0), _multiplier(0) {} + NETFile(SubFile *gmp, quint32 offset) + : SubFile(gmp, offset), _offset(0), _size(0), _multiplier(0) {} bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset); diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index c0dc8ab6..71822863 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -35,7 +35,7 @@ bool RGNFile::skipClassFields(Handle &hdl) const break; } - return seek(hdl, hdl.pos + rs); + return seek(hdl, hdl.pos() + rs); } bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3], @@ -133,7 +133,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv, qint16 lon, lat; quint16 len; - while (hdl.pos < (int)segment.end()) { + while (hdl.pos() < (int)segment.end()) { IMG::Poly poly; if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr) @@ -206,7 +206,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, if (!seek(hdl, segment.offset())) return false; - while (hdl.pos < (int)segment.end()) { + while (hdl.pos() < (int)segment.end()) { IMG::Poly poly; QPoint pos; @@ -305,7 +305,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv, if (!seek(hdl, segment.offset())) return false; - while (hdl.pos < (int)segment.end()) { + while (hdl.pos() < (int)segment.end()) { IMG::Point point; if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr) @@ -327,7 +327,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv, point.poi = labelPtr & 0x400000; if (lbl && (labelPtr & 0x3FFFFF)) { point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi); - point.id = ((quint64)point.type)<<40 | ((quint64)lbl->offset())<<24 + point.id = ((quint64)point.type)<<40 | ((quint64)lbl->id())<<24 | (labelPtr & 0x3FFFFF); } @@ -351,7 +351,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, if (!seek(hdl, segment.offset())) return false; - while (hdl.pos < (int)segment.end()) { + while (hdl.pos() < (int)segment.end()) { IMG::Point point; if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype) @@ -382,7 +382,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, if (lbl && (labelPtr & 0x3FFFFF)) { point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi); point.id = ((quint64)point.type)<<40 - | ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF); + | ((quint64)lbl->id())<<24 | (labelPtr & 0x3FFFFF); } points->append(point); diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index f9336385..b432147e 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -24,6 +24,10 @@ public: : SubFile(img), _offset(0), _size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) {clearFlags();} + RGNFile(const QString &path) + : SubFile(path), _offset(0), _size(0), _polygonsOffset(0), + _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0), + _pointsSize(0), _init(false) {clearFlags();} RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0), _size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) diff --git a/src/map/IMG/style.cpp b/src/map/IMG/style.cpp index 5b38d96c..139149f4 100644 --- a/src/map/IMG/style.cpp +++ b/src/map/IMG/style.cpp @@ -341,7 +341,7 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl) len = len >> 2; } - if (!file->seek(hdl, hdl.pos + len)) + if (!file->seek(hdl, hdl.pos() + len)) return false; return true; @@ -890,7 +890,7 @@ bool Style::parseDrawOrder(SubFile *file, SubFile::Handle &hdl, bool Style::parseTYPFile(SubFile *file) { - SubFile::Handle hdl; + SubFile::Handle hdl(file); Section points, lines, polygons, order; quint16 tmp16, codepage; diff --git a/src/map/IMG/subfile.cpp b/src/map/IMG/subfile.cpp index 7820fb97..794987b8 100644 --- a/src/map/IMG/subfile.cpp +++ b/src/map/IMG/subfile.cpp @@ -5,22 +5,35 @@ bool SubFile::seek(Handle &handle, quint32 pos) const { - if (_file) - return _file->seek(pos); - else { + if (handle._file) { + int blockNum = pos / BLOCK_SIZE; + + if (handle._blockNum != blockNum) { + if (!handle._file->seek((qint64)blockNum * BLOCK_SIZE)) + return false; + if (handle._file->read(handle._data.data(), BLOCK_SIZE) < 0) + return false; + handle._blockNum = blockNum; + } + + handle._blockPos = pos % BLOCK_SIZE; + handle._pos = pos; + + return true; + } else { quint32 blockSize = _img->blockSize(); int blockNum = pos / blockSize; - if (handle.blockNum != blockNum) { + if (handle._blockNum != blockNum) { if (blockNum >= _blocks->size()) return false; - if (!_img->readBlock(_blocks->at(blockNum), handle.data)) + if (!_img->readBlock(_blocks->at(blockNum), handle._data.data())) return false; - handle.blockNum = blockNum; + handle._blockNum = blockNum; } - handle.blockPos = pos % blockSize; - handle.pos = pos; + handle._blockPos = pos % blockSize; + handle._pos = pos; return true; } @@ -28,14 +41,10 @@ bool SubFile::seek(Handle &handle, quint32 pos) const bool SubFile::readByte(Handle &handle, quint8 &val) const { - if (_file) - return _file->getChar((char*)&val); - else { - val = handle.data.at(handle.blockPos++); - handle.pos++; - return (handle.blockPos >= _img->blockSize()) - ? seek(handle, handle.pos) : true; - } + int blockSize = handle._file ? BLOCK_SIZE : _img->blockSize(); + val = handle._data.at(handle._blockPos++); + handle._pos++; + return (handle._blockPos >= blockSize) ? seek(handle, handle._pos) : true; } bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const @@ -77,7 +86,7 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const return false; if (!(bits & 1)) { - seek(hdl, hdl.pos - 1); + seek(hdl, hdl._pos - 1); if (!((bits>>1) & 1)) { if (!((bits>>2) & 1)) { if (!readUInt32(hdl, bitfield)) @@ -97,8 +106,3 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const return true; } - -QString SubFile::fileName() const -{ - return _file ? _file->fileName() : _img->fileName(); -} diff --git a/src/map/IMG/subfile.h b/src/map/IMG/subfile.h index c987c886..d1d275a1 100644 --- a/src/map/IMG/subfile.h +++ b/src/map/IMG/subfile.h @@ -3,38 +3,64 @@ #include #include +#include +#include "img.h" -class QFile; -class IMG; + +#define BLOCK_SIZE 8192 class SubFile { public: enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP}; - struct Handle + class Handle { - Handle() : blockNum(-1), blockPos(-1), pos(-1) {} + public: + Handle(const SubFile *subFile) + : _file(0), _blockNum(-1), _blockPos(-1), _pos(-1) + { + if (subFile && subFile->_path) { + _file = new QFile(*(subFile->_path)); + _file->open(QIODevice::ReadOnly); + _data.resize(BLOCK_SIZE); + } else if (subFile) + _data.resize(subFile->_img->blockSize()); + _blockNum = -1; + _blockPos = -1; + _pos = -1; + } + ~Handle() {delete _file;} - QByteArray data; - int blockNum; - int blockPos; - int pos; + int pos() const {return _pos;} + + private: + friend class SubFile; + + QFile *_file; + QByteArray _data; + int _blockNum; + int _blockPos; + int _pos; }; SubFile(IMG *img) - : _gmpOffset(0), _img(img), _blocks(new QVector()), _file(0) {} + : _gmpOffset(0), _img(img), _blocks(new QVector()), _path(0), + _id(0) {} SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img), - _blocks(gmp->_blocks), _file(gmp->_file) {} - SubFile(QFile *file) - : _gmpOffset(0), _img(0), _blocks(0), _file(file) {} + _blocks(gmp->_blocks), _path(gmp->_path), _id(gmp->id()) {} + SubFile(const QString &path) + : _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)), _id(0) {} ~SubFile() { - if (!_gmpOffset) + if (!_gmpOffset) { delete _blocks; + delete _path; + } } void addBlock(quint16 block) {_blocks->append(block);} + void setId(quint16 id) {_id = id;} bool seek(Handle &handle, quint32 pos) const; @@ -114,8 +140,8 @@ public: bool readVUInt32(Handle &hdl, quint32 &val) const; bool readVBitfield32(Handle &hdl, quint32 &bitfield) const; - quint16 offset() const {return _blocks->first();} - QString fileName() const; + quint16 id() const {return _blocks ? _blocks->first() : _id;} + QString fileName() const {return _path ? *_path : _img->fileName();} protected: quint32 _gmpOffset; @@ -125,7 +151,8 @@ private: IMG *_img; QVector *_blocks; - QFile *_file; + QString *_path; + quint16 _id; }; #endif // SUBFILE_H diff --git a/src/map/IMG/trefile.cpp b/src/map/IMG/trefile.cpp index 02c11aa2..0bfd0cb7 100644 --- a/src/map/IMG/trefile.cpp +++ b/src/map/IMG/trefile.cpp @@ -39,7 +39,7 @@ TREFile::~TREFile() bool TREFile::init() { - Handle hdl; + Handle hdl(this); quint8 locked; quint16 hdrLen; @@ -113,7 +113,7 @@ bool TREFile::init() bool TREFile::load(int idx) { - Handle hdl; + Handle hdl(this); QList sl; SubDiv *s = 0; SubDivTree *tree = new SubDivTree(); @@ -199,7 +199,7 @@ bool TREFile::load(int idx) if (i) sl.at(i-1)->setExtEnds(polygons, lines, points); - if (!seek(hdl, hdl.pos + _extended.itemSize - 12)) + if (!seek(hdl, hdl.pos() + _extended.itemSize - 12)) goto error; } diff --git a/src/map/IMG/trefile.h b/src/map/IMG/trefile.h index 88159de5..6d16c003 100644 --- a/src/map/IMG/trefile.h +++ b/src/map/IMG/trefile.h @@ -14,6 +14,7 @@ class TREFile : public SubFile { public: TREFile(IMG *img) : SubFile(img) {} + TREFile(const QString &path) : SubFile(path) {} TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {} ~TREFile(); diff --git a/src/map/IMG/vectortile.cpp b/src/map/IMG/vectortile.cpp index 56945f5f..64e8c2dc 100644 --- a/src/map/IMG/vectortile.cpp +++ b/src/map/IMG/vectortile.cpp @@ -59,6 +59,29 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type) } } +SubFile *VectorTile::addFile(const QString &path, SubFile::Type type) +{ + switch (type) { + case SubFile::TRE: + _tre = new TREFile(path); + return _tre; + case SubFile::RGN: + _rgn = new RGNFile(path); + return _rgn; + case SubFile::LBL: + _lbl = new LBLFile(path); + return _lbl; + case SubFile::NET: + _net = new NETFile(path); + return _net; + case SubFile::GMP: + _gmp = new SubFile(path); + return _gmp; + default: + return 0; + } +} + bool VectorTile::init() { if (_gmp && !initGMP()) @@ -72,7 +95,7 @@ bool VectorTile::init() bool VectorTile::initGMP() { - SubFile::Handle hdl; + SubFile::Handle hdl(_gmp); quint32 tre, rgn, lbl, net; if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre) @@ -92,7 +115,7 @@ void VectorTile::polys(const RectC &rect, int bits, QList *polygons, QList *lines, QCache *polyCache) const { - SubFile::Handle rgnHdl, lblHdl, netHdl; + SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net); if (!_rgn->initialized() && !_rgn->init(rgnHdl)) return; @@ -131,7 +154,7 @@ void VectorTile::polys(const RectC &rect, int bits, QList *polygons, void VectorTile::points(const RectC &rect, int bits, QList *points, QCache > *pointCache) const { - SubFile::Handle rgnHdl, lblHdl; + SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl); if (!_rgn->initialized() && !_rgn->init(rgnHdl)) return; diff --git a/src/map/IMG/vectortile.h b/src/map/IMG/vectortile.h index 76f39061..8ac84f4d 100644 --- a/src/map/IMG/vectortile.h +++ b/src/map/IMG/vectortile.h @@ -23,6 +23,7 @@ public: SubFile *file(SubFile::Type type); SubFile *addFile(IMG *img, SubFile::Type type); + SubFile *addFile(const QString &path, SubFile::Type type); void polys(const RectC &rect, int bits, QList *polygons, QList *lines, QCache *polyCache) @@ -37,8 +38,6 @@ public: || type == SubFile::GMP); } - friend QDebug operator<<(QDebug dbg, const VectorTile &tile); - private: bool initGMP(); diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index 038c145b..5ea914b7 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -13,6 +13,9 @@ #include "IMG/textpathitem.h" #include "IMG/textpointitem.h" #include "IMG/bitmapline.h" +#include "IMG/style.h" +#include "IMG/img.h" +#include "IMG/gmap.h" #include "pcs.h" #include "rectd.h" #include "imgmap.h" @@ -35,9 +38,9 @@ public: const QString &key() const {return _key;} const QPoint &xy() const {return _xy;} QImage &img() {return _img;} - QList &polygons() {return _polygons;} - QList &lines() {return _lines;} - QList &points() {return _points;} + QList &polygons() {return _polygons;} + QList &lines() {return _lines;} + QList &points() {return _points;} void render() { @@ -70,9 +73,9 @@ private: QPoint _xy; QString _key; QImage _img; - QList _polygons; - QList _lines; - QList _points; + QList _polygons; + QList _lines; + QList _points; }; @@ -226,11 +229,17 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect) || polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill))); } + IMGMap::IMGMap(const QString &fileName, QObject *parent) - : Map(parent), _img(fileName), _projection(PCS::pcs(3857)), _valid(false) + : Map(parent), _projection(PCS::pcs(3857)), _valid(false) { - if (!_img.isValid()) { - _errorString = _img.errorString(); + if (GMAP::isGMAP(fileName)) + _data = new GMAP(fileName); + else + _data = new IMG(fileName); + + if (!_data->isValid()) { + _errorString = _data->errorString(); return; } @@ -242,17 +251,17 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent) void IMGMap::load() { - _img.load(); + _data->load(); } void IMGMap::unload() { - _img.clear(); + _data->clear(); } QRectF IMGMap::bounds() { - RectD prect(_img.bounds(), _projection); + RectD prect(_data->bounds(), _projection); return QRectF(_transform.proj2img(prect.topLeft()), _transform.proj2img(prect.bottomRight())); } @@ -302,7 +311,7 @@ Transform IMGMap::transform(int zoom) const { double scale = _projection.isGeographic() ? 360.0 / (1<bounds().topLeft())); return Transform(ReferencePoint(PointD(0, 0), topLeft), PointD(scale, scale)); } @@ -322,14 +331,14 @@ Coordinates IMGMap::xy2ll(const QPointF &p) return _projection.xy2ll(_transform.img2proj(p)); } -void IMGMap::drawPolygons(QPainter *painter, const QList &polygons) +void IMGMap::drawPolygons(QPainter *painter, const QList &polygons) { - for (int n = 0; n < _img.style()->drawOrder().size(); n++) { + for (int n = 0; n < _data->style()->drawOrder().size(); n++) { for (int i = 0; i < polygons.size(); i++) { - const IMG::Poly &poly = polygons.at(i); - if (poly.type != _img.style()->drawOrder().at(n)) + const MapData::Poly &poly = polygons.at(i); + if (poly.type != _data->style()->drawOrder().at(n)) continue; - const Style::Polygon &style = _img.style()->polygon(poly.type); + const Style::Polygon &style = _data->style()->polygon(poly.type); painter->setPen(style.pen()); painter->setBrush(style.brush()); @@ -338,13 +347,13 @@ void IMGMap::drawPolygons(QPainter *painter, const QList &polygons) } } -void IMGMap::drawLines(QPainter *painter, const QList &lines) +void IMGMap::drawLines(QPainter *painter, const QList &lines) { painter->setBrush(Qt::NoBrush); for (int i = 0; i < lines.size(); i++) { - const IMG::Poly &poly = lines.at(i); - const Style::Line &style = _img.style()->line(poly.type); + const MapData::Poly &poly = lines.at(i); + const Style::Line &style = _data->style()->line(poly.type); if (style.background() == Qt::NoPen) continue; @@ -354,8 +363,8 @@ void IMGMap::drawLines(QPainter *painter, const QList &lines) } for (int i = 0; i < lines.size(); i++) { - const IMG::Poly &poly = lines.at(i); - const Style::Line &style = _img.style()->line(poly.type); + const MapData::Poly &poly = lines.at(i); + const Style::Line &style = _data->style()->line(poly.type); if (!style.img().isNull()) BitmapLine::draw(painter, poly.points, style.img()); @@ -372,12 +381,11 @@ void IMGMap::drawTextItems(QPainter *painter, const QList &textItems) textItems.at(i)->paint(painter); } - -void IMGMap::processPolygons(QList &polygons, +void IMGMap::processPolygons(QList &polygons, QList &textItems) { for (int i = 0; i < polygons.size(); i++) { - IMG::Poly &poly = polygons[i]; + MapData::Poly &poly = polygons[i]; for (int j = 0; j < poly.points.size(); j++) { QPointF &p = poly.points[j]; p = ll2xy(Coordinates(p.x(), p.y())); @@ -389,7 +397,7 @@ void IMGMap::processPolygons(QList &polygons, if (_zoom <= 23 && (Style::isWaterArea(poly.type) || Style::isMilitaryArea(poly.type) || Style::isNatureReserve(poly.type))) { - const Style::Polygon &style = _img.style()->polygon(poly.type); + const Style::Polygon &style = _data->style()->polygon(poly.type); TextPointItem *item = new TextPointItem( centroid(poly.points).toPoint(), &poly.label.text(), poiFont(), 0, &style.brush().color()); @@ -402,13 +410,13 @@ void IMGMap::processPolygons(QList &polygons, } } -void IMGMap::processLines(QList &lines, const QRect &tileRect, +void IMGMap::processLines(QList &lines, const QRect &tileRect, QList &textItems) { qStableSort(lines); for (int i = 0; i < lines.size(); i++) { - IMG::Poly &poly = lines[i]; + MapData::Poly &poly = lines[i]; for (int j = 0; j < poly.points.size(); j++) { QPointF &p = poly.points[j]; p = ll2xy(Coordinates(p.x(), p.y())); @@ -420,12 +428,12 @@ void IMGMap::processLines(QList &lines, const QRect &tileRect, processShields(lines, tileRect, textItems); } -void IMGMap::processStreetNames(QList &lines, const QRect &tileRect, - QList &textItems) +void IMGMap::processStreetNames(QList &lines, + const QRect &tileRect, QList &textItems) { for (int i = 0; i < lines.size(); i++) { - IMG::Poly &poly = lines[i]; - const Style::Line &style = _img.style()->line(poly.type); + MapData::Poly &poly = lines[i]; + const Style::Line &style = _data->style()->line(poly.type); if (style.img().isNull() && style.foreground() == Qt::NoPen) continue; @@ -449,7 +457,7 @@ void IMGMap::processStreetNames(QList &lines, const QRect &tileRect, } } -void IMGMap::processShields(QList &lines, const QRect &tileRect, +void IMGMap::processShields(QList &lines, const QRect &tileRect, QList &textItems) { for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) { @@ -460,7 +468,7 @@ void IMGMap::processShields(QList &lines, const QRect &tileRect, QHash sp; for (int i = 0; i < lines.size(); i++) { - const IMG::Poly &poly = lines.at(i); + const MapData::Poly &poly = lines.at(i); const Label::Shield &shield = poly.label.shield(); if (!shield.isValid() || shield.type() != type || !Style::isMajorRoad(poly.type)) @@ -513,14 +521,14 @@ void IMGMap::processShields(QList &lines, const QRect &tileRect, } } -void IMGMap::processPoints(QList &points, +void IMGMap::processPoints(QList &points, QList &textItems) { qSort(points); for (int i = 0; i < points.size(); i++) { - IMG::Point &point = points[i]; - const Style::Point &style = _img.style()->point(point.type); + MapData::Point &point = points[i]; + const Style::Point &style = _data->style()->point(point.type); if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type))) continue; @@ -574,7 +582,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) for (int j = 0; j < height; j++) { QPixmap pm; QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE); - QString key = _img.fileName() + "-" + QString::number(_zoom) + "_" + QString key = _data->fileName() + "-" + QString::number(_zoom) + "_" + QString::number(ttl.x()) + "_" + QString::number(ttl.y()); if (QPixmapCache::find(key, pm)) painter->drawPixmap(ttl, pm); @@ -584,13 +592,13 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) RectD polyRect(_transform.img2proj(ttl), _transform.img2proj( QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE))); - _img.polys(polyRect.toRectC(_projection, 4), _zoom, + _data->polys(polyRect.toRectC(_projection, 4), _zoom, &(tile.polygons()), &(tile.lines())); RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x() + TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT))); - _img.points(pointRect.toRectC(_projection, 4), _zoom, + _data->points(pointRect.toRectC(_projection, 4), _zoom, &(tile.points())); } } diff --git a/src/map/imgmap.h b/src/map/imgmap.h index 36b7dee8..03dec65b 100644 --- a/src/map/imgmap.h +++ b/src/map/imgmap.h @@ -4,7 +4,7 @@ #include "map.h" #include "projection.h" #include "transform.h" -#include "IMG/img.h" +#include "IMG/mapdata.h" class TextItem; @@ -14,8 +14,9 @@ class IMGMap : public Map public: IMGMap(const QString &fileName, QObject *parent = 0); + ~IMGMap() {delete _data;} - QString name() const {return _img.name();} + QString name() const {return _data->name();} QRectF bounds(); @@ -43,21 +44,21 @@ private: Transform transform(int zoom) const; void updateTransform(); - void drawPolygons(QPainter *painter, const QList &polygons); - void drawLines(QPainter *painter, const QList &lines); + void drawPolygons(QPainter *painter, const QList &polygons); + void drawLines(QPainter *painter, const QList &lines); void drawTextItems(QPainter *painter, const QList &textItems); - void processPolygons(QList &polygons, + void processPolygons(QList &polygons, QList &textItems); - void processLines(QList &lines, const QRect &tileRect, + void processLines(QList &lines, const QRect &tileRect, QList &textItems); - void processPoints(QList &points, QList &textItems); - void processShields(QList &lines, const QRect &tileRect, + void processPoints(QList &points, QList &textItems); + void processShields(QList &lines, const QRect &tileRect, QList &textItems); - void processStreetNames(QList &lines, const QRect &tileRect, + void processStreetNames(QList &lines, const QRect &tileRect, QList &textItems); - IMG _img; + MapData *_data; int _zoom; Projection _projection; Transform _transform; diff --git a/src/map/maplist.cpp b/src/map/maplist.cpp index aebcd5d7..91f8b610 100644 --- a/src/map/maplist.cpp +++ b/src/map/maplist.cpp @@ -8,20 +8,27 @@ #include "mbtilesmap.h" #include "rmap.h" #include "imgmap.h" +#include "IMG/gmap.h" #include "maplist.h" -bool MapList::loadMap(Map* map, const QString &path, bool dir) +bool MapList::loadMap(Map *map, const QString &path, bool dir) { - if (map->isValid()) { + if (map && map->isValid()) { _maps.append(map); return true; - } else { + } else if (map) { if (dir) _errorString += path + ": " + map->errorString() + "\n"; else _errorString = map->errorString(); return false; + } else { + if (dir) + _errorString += path + ": " + "Unknown map format\n"; + else + _errorString = "Unknown map format"; + return false; } } @@ -41,18 +48,22 @@ Map *MapList::loadSource(const QString &path, bool dir) return map; } -bool MapList::loadFile(const QString &path, bool *atlas, bool dir) +bool MapList::loadFile(const QString &path, bool *terminate, bool dir) { QFileInfo fi(path); QString suffix = fi.suffix().toLower(); - Map *map; + Map *map = 0; if (Atlas::isAtlas(path)) { - *atlas = true; + *terminate = true; map = new Atlas(path, this); } else if (suffix == "xml") { - if (!(map = loadSource(path, dir))) + if (MapSource::isMap(path) && !(map = loadSource(path, dir))) return false; + else if (GMAP::isGMAP(path)) { + *terminate = true; + map = new IMGMap(path); + } } else if (suffix == "jnx") map = new JNXMap(path, this); else if (suffix == "tif" || suffix == "tiff") @@ -85,15 +96,15 @@ bool MapList::loadDirR(const QString &path) for (int i = 0; i < ml.size(); i++) { const QFileInfo &fi = ml.at(i); QString suffix = fi.suffix().toLower(); - bool atlas = false; + bool terminate = false; if (fi.isDir() && fi.fileName() != "set") { if (!loadDirR(fi.absoluteFilePath())) ret = false; } else if (filter().contains("*." + suffix)) { - if (!loadFile(fi.absoluteFilePath(), &atlas, true)) + if (!loadFile(fi.absoluteFilePath(), &terminate, true)) ret = false; - if (atlas) + if (terminate) break; } } @@ -120,7 +131,7 @@ QString MapList::formats() return tr("Supported files") + " (*.img *.jnx *.map *.mbtiles *.rmap *.rtmap *.tar *.tba *.tif *.tiff *.xml);;" - + tr("Garmin IMG maps") + " (*.img);;" + + tr("Garmin IMG maps") + " (*.img *.xml);;" + tr("Garmin JNX maps") + " (*.jnx);;" + tr("OziExplorer maps") + " (*.map);;" + tr("MBTiles maps") + " (*.mbtiles);;" diff --git a/src/map/maplist.h b/src/map/maplist.h index 87426a90..394738ab 100644 --- a/src/map/maplist.h +++ b/src/map/maplist.h @@ -23,7 +23,7 @@ public: static QStringList filter(); private: - bool loadFile(const QString &path, bool *atlas, bool dir); + bool loadFile(const QString &path, bool *terminate, bool dir); bool loadDirR(const QString &path); Map *loadSource(const QString &path, bool dir); bool loadMap(Map *map, const QString &path, bool dir); diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index 5b18875c..c881b9b4 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -222,6 +222,20 @@ 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() == "map") + return true; + + return false; +} + Map *MapSource::loadMap(const QString &path, QString &errorString) { Config config; diff --git a/src/map/mapsource.h b/src/map/mapsource.h index ee6f0c89..abeecdd6 100644 --- a/src/map/mapsource.h +++ b/src/map/mapsource.h @@ -15,6 +15,7 @@ class MapSource { public: static Map *loadMap(const QString &path, QString &errorString); + static bool isMap(const QString &path); private: enum Type {