1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Compare commits

..

2 Commits

Author SHA1 Message Date
22e5ffaa0c Added support for non-SQL Orux maps
+ error handling fixes/improvements
2022-08-11 23:39:36 +02:00
9a4514a464 Version++ 2022-08-11 23:38:48 +02:00
5 changed files with 138 additions and 71 deletions

View File

@ -1,4 +1,4 @@
version: 11.3.{build} version: 11.4.{build}
configuration: configuration:
- Release - Release

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 11.3 VERSION = 11.4
QT += core \ QT += core \
gui \ gui \

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "11.3" !define VERSION "11.4"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -234,6 +234,10 @@ void OruxMap::calibrationPoints(QXmlStreamReader &reader, const QSize &size,
return; return;
CalibrationPoint p(corner2point(corner, size), Coordinates(lon, lat)); CalibrationPoint p(corner2point(corner, size), Coordinates(lon, lat));
if (!p.isValid()) {
reader.raiseError(QString("invalid calibration point"));
return;
}
points.append(p); points.append(p);
reader.readElementText(); reader.readElementText();
@ -242,13 +246,15 @@ void OruxMap::calibrationPoints(QXmlStreamReader &reader, const QSize &size,
} }
} }
void OruxMap::mapCalibration(QXmlStreamReader &reader, int level) void OruxMap::mapCalibration(QXmlStreamReader &reader, const QString &dir,
int level)
{ {
int zoom; int zoom;
QSize tileSize, size, calibrationSize; QSize tileSize, size, calibrationSize;
QString datum, projection; QString datum, projection, fileName;
QList<CalibrationPoint> points; QList<CalibrationPoint> points;
Projection proj; Projection proj;
Transform t;
QXmlStreamAttributes attr = reader.attributes(); QXmlStreamAttributes attr = reader.attributes();
if (!intAttr(reader, attr, "layerLevel", zoom)) if (!intAttr(reader, attr, "layerLevel", zoom))
@ -256,10 +262,10 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("OruxTracker")) if (reader.name() == QLatin1String("OruxTracker"))
oruxTracker(reader, level + 1); oruxTracker(reader, dir, level + 1);
else if (reader.name() == QLatin1String("MapName")) { else if (reader.name() == QLatin1String("MapName")) {
QString name(reader.readElementText()); QString name(reader.readElementText());
if (!level) if (!level && dir.isEmpty())
_name = name; _name = name;
} else if (reader.name() == QLatin1String("MapChunks")) { } else if (reader.name() == QLatin1String("MapChunks")) {
int xMax, yMax, width, height; int xMax, yMax, width, height;
@ -277,6 +283,8 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
return; return;
if (!strAttr(reader, attr, "projection", projection)) if (!strAttr(reader, attr, "projection", projection))
return; return;
if (!strAttr(reader, attr, "file_name", fileName))
return;
tileSize = QSize(width, height); tileSize = QSize(width, height);
size = QSize(xMax * width, yMax * height); size = QSize(xMax * width, yMax * height);
@ -309,29 +317,50 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
calibrationSize = QSize(width, height); calibrationSize = QSize(width, height);
reader.readElementText(); reader.readElementText();
} else if (reader.name() == QLatin1String("CalibrationPoints")) } else if (reader.name() == QLatin1String("CalibrationPoints")) {
calibrationPoints(reader, calibrationSize, points); calibrationPoints(reader, calibrationSize, points);
else
t = computeTransformation(proj, points);
if (!t.isValid()) {
reader.raiseError(t.errorString());
return;
}
} else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
if (tileSize.isValid()) { if (tileSize.isValid()) {
Transform t(computeTransformation(proj, points)); if (!t.isValid()) {
_zooms.append(Zoom(zoom, tileSize, size, proj, t)); reader.raiseError("Invalid map calibration");
return;
}
QDir mapDir(QFileInfo(path()).absoluteDir());
QDir subDir = dir.isEmpty()
? mapDir : QDir(mapDir.absoluteFilePath(dir));
QString set(subDir.absoluteFilePath("set"));
_zooms.append(Zoom(zoom, tileSize, size, proj, t, fileName, set));
} }
} }
void OruxMap::oruxTracker(QXmlStreamReader &reader, int level) void OruxMap::oruxTracker(QXmlStreamReader &reader, const QString &dir,
int level)
{ {
if (level > 1 || (level && !dir.isEmpty())) {
reader.raiseError("invalid map nesting");
return;
}
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("MapCalibration")) if (reader.name() == QLatin1String("MapCalibration"))
mapCalibration(reader, level); mapCalibration(reader, dir, level);
else else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
} }
bool OruxMap::readXML(const QString &path) bool OruxMap::readXML(const QString &path, const QString &dir)
{ {
QFile file(path); QFile file(path);
@ -341,7 +370,7 @@ bool OruxMap::readXML(const QString &path)
QXmlStreamReader reader(&file); QXmlStreamReader reader(&file);
if (reader.readNextStartElement()) { if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("OruxTracker")) if (reader.name() == QLatin1String("OruxTracker"))
oruxTracker(reader, 0); oruxTracker(reader, dir, 0);
else else
reader.raiseError("Not a Orux map calibration file"); reader.raiseError("Not a Orux map calibration file");
} }
@ -354,51 +383,67 @@ bool OruxMap::readXML(const QString &path)
return true; return true;
} }
OruxMap::OruxMap(const QString &fileName, QObject *parent) OruxMap::OruxMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _zoom(0), _mapRatio(1.0), _valid(false) : Map(fileName, parent), _zoom(0), _mapRatio(1.0), _valid(false)
{ {
QFileInfo fi(fileName);
QDir dir(fi.absoluteDir());
if (!readXML(fileName)) if (!readXML(fileName))
return; return;
if (_zooms.isEmpty()) { if (_zooms.isEmpty()) {
_errorString = "No usable zoom level found"; QStringList list(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
return; for (int i = 0; i < list.size(); i++) {
QDir subDir(dir.absoluteFilePath(list.at(i)));
if (!readXML(subDir.absoluteFilePath(list.at(i) + ".otrk2.xml"),
list.at(i))) {
_errorString = list.at(i) + ": " + _errorString;
return;
}
}
if (_zooms.isEmpty()) {
_errorString = "No usable zoom level found";
return;
}
} }
std::sort(_zooms.begin(), _zooms.end()); std::sort(_zooms.begin(), _zooms.end());
QFileInfo fi(fileName); if (dir.exists("OruxMapsImages.db")) {
QDir dir(fi.absoluteDir()); QString dbFile(dir.absoluteFilePath("OruxMapsImages.db"));
QString dbFile(dir.absoluteFilePath("OruxMapsImages.db")); _db = QSqlDatabase::addDatabase("QSQLITE", dbFile);
if (!QFileInfo::exists(dbFile)) { _db.setDatabaseName(dbFile);
_errorString = "Image DB file not found"; _db.setConnectOptions("QSQLITE_OPEN_READONLY");
return; if (!_db.open()) {
_errorString = "Error opening database file";
return;
}
QSqlRecord r = _db.record("tiles");
if (r.isEmpty()
|| r.field(0).name() != "x"
|| META_TYPE(r.field(0).type()) != QMetaType::Int
|| r.field(1).name() != "y"
|| META_TYPE(r.field(1).type()) != QMetaType::Int
|| r.field(2).name() != "z"
|| META_TYPE(r.field(2).type()) != QMetaType::Int
|| r.field(3).name() != "image"
|| META_TYPE(r.field(3).type()) != QMetaType::QByteArray) {
_errorString = "Invalid table format";
return;
}
_db.close();
} else {
for (int i = 0; i < _zooms.size(); i++) {
if (!_zooms.at(i).set.exists()) {
_errorString = "missing set directory (level "
+ QString::number(_zooms.at(i).zoom) + ")";
return;
}
}
} }
_db = QSqlDatabase::addDatabase("QSQLITE", dbFile);
_db.setDatabaseName(dbFile);
_db.setConnectOptions("QSQLITE_OPEN_READONLY");
if (!_db.open()) {
_errorString = "Error opening database file";
return;
}
QSqlRecord r = _db.record("tiles");
if (r.isEmpty()
|| r.field(0).name() != "x"
|| META_TYPE(r.field(0).type()) != QMetaType::Int
|| r.field(1).name() != "y"
|| META_TYPE(r.field(1).type()) != QMetaType::Int
|| r.field(2).name() != "z"
|| META_TYPE(r.field(2).type()) != QMetaType::Int
|| r.field(3).name() != "image"
|| META_TYPE(r.field(3).type()) != QMetaType::QByteArray) {
_errorString = "Invalid table format";
return;
}
_db.close();
_valid = true; _valid = true;
} }
@ -436,12 +481,14 @@ int OruxMap::zoomOut()
void OruxMap::load() void OruxMap::load()
{ {
_db.open(); if (_db.isValid())
_db.open();
} }
void OruxMap::unload() void OruxMap::unload()
{ {
_db.close(); if (_db.isValid())
_db.close();
} }
void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
@ -450,19 +497,37 @@ void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
_mapRatio = mapRatio; _mapRatio = mapRatio;
} }
QPixmap OruxMap::tile(int zoom, int x, int y) const QPixmap OruxMap::tile(const Zoom &z, int x, int y) const
{ {
QSqlQuery query(_db); if (_db.isValid()) {
query.prepare("SELECT image FROM tiles WHERE z=:z AND x=:x AND y=:y"); QSqlQuery query(_db);
query.bindValue(":z", zoom); query.prepare("SELECT image FROM tiles WHERE z=:z AND x=:x AND y=:y");
query.bindValue(":x", x); query.bindValue(":z", z.zoom);
query.bindValue(":y", y); query.bindValue(":x", x);
query.exec(); query.bindValue(":y", y);
if (!query.first()) query.exec();
return QPixmap();
QImage img(QImage::fromData(query.value(0).toByteArray())); if (!query.first()) {
return QPixmap::fromImage(img); qWarning("%s: SQL %d-%d-%d: not found", qPrintable(name()), z.zoom,
x, y);
return QPixmap();
} else {
QImage img(QImage::fromData(query.value(0).toByteArray()));
return QPixmap::fromImage(img);
}
} else {
QString fileName(z.fileName + "_" + QString::number(x) + "_"
+ QString::number(y) + ".omc2");
QString path(z.set.absoluteFilePath(fileName));
if (!QFileInfo::exists(path)) {
qWarning("%s: %s: not found", qPrintable(name()),
qPrintable(fileName));
return QPixmap();
} else {
QImage img(path);
return QPixmap::fromImage(img);
}
}
} }
void OruxMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void OruxMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
@ -484,14 +549,12 @@ void OruxMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
+ "_" + QString::number(x/z.tileSize.width()) + "_" + QString::number(x/z.tileSize.width())
+ "_" + QString::number(y/z.tileSize.height()); + "_" + QString::number(y/z.tileSize.height());
if (!QPixmapCache::find(key, &pixmap)) { if (!QPixmapCache::find(key, &pixmap)) {
pixmap = tile(z.zoom, x/z.tileSize.width(), y/z.tileSize.height()); pixmap = tile(z, x/z.tileSize.width(), y/z.tileSize.height());
if (!pixmap.isNull()) if (!pixmap.isNull())
QPixmapCache::insert(key, pixmap); QPixmapCache::insert(key, pixmap);
} }
if (pixmap.isNull()) if (!pixmap.isNull()) {
qWarning("%s: error loading tile image", qPrintable(key));
else {
pixmap.setDevicePixelRatio(_mapRatio); pixmap.setDevicePixelRatio(_mapRatio);
QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height()); QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height());
painter->drawPixmap(tp, pixmap); painter->drawPixmap(tp, pixmap);

View File

@ -3,6 +3,7 @@
#include <QDebug> #include <QDebug>
#include <QSqlDatabase> #include <QSqlDatabase>
#include <QDir>
#include "map.h" #include "map.h"
#include "projection.h" #include "projection.h"
#include "transform.h" #include "transform.h"
@ -44,9 +45,10 @@ public:
private: private:
struct Zoom { struct Zoom {
Zoom(int zoom, const QSize &tileSize, const QSize &size, Zoom(int zoom, const QSize &tileSize, const QSize &size,
const Projection &proj, const Transform &transform) const Projection &proj, const Transform &transform,
const QString &fileName, const QString &set)
: zoom(zoom), tileSize(tileSize), size(size), projection(proj), : zoom(zoom), tileSize(tileSize), size(size), projection(proj),
transform(transform) {} transform(transform), fileName(fileName), set(set) {}
bool operator<(const Zoom &other) const bool operator<(const Zoom &other) const
{return zoom < other.zoom;} {return zoom < other.zoom;}
@ -55,14 +57,16 @@ private:
QSize size; QSize size;
Projection projection; Projection projection;
Transform transform; Transform transform;
QString fileName;
QDir set;
}; };
bool readXML(const QString &path); bool readXML(const QString &path, const QString &dir = QString());
void oruxTracker(QXmlStreamReader &reader, int level); void oruxTracker(QXmlStreamReader &reader, const QString &dir, int level);
void mapCalibration(QXmlStreamReader &reader, int level); void mapCalibration(QXmlStreamReader &reader, const QString &dir, int level);
void calibrationPoints(QXmlStreamReader &reader, const QSize &size, void calibrationPoints(QXmlStreamReader &reader, const QSize &size,
QList<CalibrationPoint> &points); QList<CalibrationPoint> &points);
QPixmap tile(int zoom, int x, int y) const; QPixmap tile(const Zoom &z, int x, int y) const;
friend QDebug operator<<(QDebug dbg, const Zoom &zoom); friend QDebug operator<<(QDebug dbg, const Zoom &zoom);