mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added support for non-SQL Orux maps
+ error handling fixes/improvements
This commit is contained in:
parent
9a4514a464
commit
22e5ffaa0c
@ -234,6 +234,10 @@ void OruxMap::calibrationPoints(QXmlStreamReader &reader, const QSize &size,
|
||||
return;
|
||||
|
||||
CalibrationPoint p(corner2point(corner, size), Coordinates(lon, lat));
|
||||
if (!p.isValid()) {
|
||||
reader.raiseError(QString("invalid calibration point"));
|
||||
return;
|
||||
}
|
||||
points.append(p);
|
||||
|
||||
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;
|
||||
QSize tileSize, size, calibrationSize;
|
||||
QString datum, projection;
|
||||
QString datum, projection, fileName;
|
||||
QList<CalibrationPoint> points;
|
||||
Projection proj;
|
||||
Transform t;
|
||||
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (!intAttr(reader, attr, "layerLevel", zoom))
|
||||
@ -256,10 +262,10 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("OruxTracker"))
|
||||
oruxTracker(reader, level + 1);
|
||||
oruxTracker(reader, dir, level + 1);
|
||||
else if (reader.name() == QLatin1String("MapName")) {
|
||||
QString name(reader.readElementText());
|
||||
if (!level)
|
||||
if (!level && dir.isEmpty())
|
||||
_name = name;
|
||||
} else if (reader.name() == QLatin1String("MapChunks")) {
|
||||
int xMax, yMax, width, height;
|
||||
@ -277,6 +283,8 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
|
||||
return;
|
||||
if (!strAttr(reader, attr, "projection", projection))
|
||||
return;
|
||||
if (!strAttr(reader, attr, "file_name", fileName))
|
||||
return;
|
||||
|
||||
tileSize = QSize(width, height);
|
||||
size = QSize(xMax * width, yMax * height);
|
||||
@ -309,29 +317,50 @@ void OruxMap::mapCalibration(QXmlStreamReader &reader, int level)
|
||||
calibrationSize = QSize(width, height);
|
||||
|
||||
reader.readElementText();
|
||||
} else if (reader.name() == QLatin1String("CalibrationPoints"))
|
||||
} else if (reader.name() == QLatin1String("CalibrationPoints")) {
|
||||
calibrationPoints(reader, calibrationSize, points);
|
||||
else
|
||||
|
||||
t = computeTransformation(proj, points);
|
||||
if (!t.isValid()) {
|
||||
reader.raiseError(t.errorString());
|
||||
return;
|
||||
}
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (tileSize.isValid()) {
|
||||
Transform t(computeTransformation(proj, points));
|
||||
_zooms.append(Zoom(zoom, tileSize, size, proj, t));
|
||||
if (!t.isValid()) {
|
||||
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()) {
|
||||
if (reader.name() == QLatin1String("MapCalibration"))
|
||||
mapCalibration(reader, level);
|
||||
mapCalibration(reader, dir, level);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
bool OruxMap::readXML(const QString &path)
|
||||
bool OruxMap::readXML(const QString &path, const QString &dir)
|
||||
{
|
||||
QFile file(path);
|
||||
|
||||
@ -341,7 +370,7 @@ bool OruxMap::readXML(const QString &path)
|
||||
QXmlStreamReader reader(&file);
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("OruxTracker"))
|
||||
oruxTracker(reader, 0);
|
||||
oruxTracker(reader, dir, 0);
|
||||
else
|
||||
reader.raiseError("Not a Orux map calibration file");
|
||||
}
|
||||
@ -354,51 +383,67 @@ bool OruxMap::readXML(const QString &path)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
OruxMap::OruxMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapRatio(1.0), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QDir dir(fi.absoluteDir());
|
||||
|
||||
if (!readXML(fileName))
|
||||
return;
|
||||
if (_zooms.isEmpty()) {
|
||||
_errorString = "No usable zoom level found";
|
||||
return;
|
||||
QStringList list(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
|
||||
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());
|
||||
|
||||
|
||||
QFileInfo fi(fileName);
|
||||
QDir dir(fi.absoluteDir());
|
||||
QString dbFile(dir.absoluteFilePath("OruxMapsImages.db"));
|
||||
if (!QFileInfo::exists(dbFile)) {
|
||||
_errorString = "Image DB file not found";
|
||||
return;
|
||||
if (dir.exists("OruxMapsImages.db")) {
|
||||
QString dbFile(dir.absoluteFilePath("OruxMapsImages.db"));
|
||||
_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();
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -436,12 +481,14 @@ int OruxMap::zoomOut()
|
||||
|
||||
void OruxMap::load()
|
||||
{
|
||||
_db.open();
|
||||
if (_db.isValid())
|
||||
_db.open();
|
||||
}
|
||||
|
||||
void OruxMap::unload()
|
||||
{
|
||||
_db.close();
|
||||
if (_db.isValid())
|
||||
_db.close();
|
||||
}
|
||||
|
||||
void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
@ -450,19 +497,37 @@ void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal 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);
|
||||
query.prepare("SELECT image FROM tiles WHERE z=:z AND x=:x AND y=:y");
|
||||
query.bindValue(":z", zoom);
|
||||
query.bindValue(":x", x);
|
||||
query.bindValue(":y", y);
|
||||
query.exec();
|
||||
if (!query.first())
|
||||
return QPixmap();
|
||||
if (_db.isValid()) {
|
||||
QSqlQuery query(_db);
|
||||
query.prepare("SELECT image FROM tiles WHERE z=:z AND x=:x AND y=:y");
|
||||
query.bindValue(":z", z.zoom);
|
||||
query.bindValue(":x", x);
|
||||
query.bindValue(":y", y);
|
||||
query.exec();
|
||||
|
||||
QImage img(QImage::fromData(query.value(0).toByteArray()));
|
||||
return QPixmap::fromImage(img);
|
||||
if (!query.first()) {
|
||||
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)
|
||||
@ -484,14 +549,12 @@ void OruxMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
+ "_" + QString::number(x/z.tileSize.width())
|
||||
+ "_" + QString::number(y/z.tileSize.height());
|
||||
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())
|
||||
QPixmapCache::insert(key, pixmap);
|
||||
}
|
||||
|
||||
if (pixmap.isNull())
|
||||
qWarning("%s: error loading tile image", qPrintable(key));
|
||||
else {
|
||||
if (!pixmap.isNull()) {
|
||||
pixmap.setDevicePixelRatio(_mapRatio);
|
||||
QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height());
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSqlDatabase>
|
||||
#include <QDir>
|
||||
#include "map.h"
|
||||
#include "projection.h"
|
||||
#include "transform.h"
|
||||
@ -44,9 +45,10 @@ public:
|
||||
private:
|
||||
struct Zoom {
|
||||
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),
|
||||
transform(transform) {}
|
||||
transform(transform), fileName(fileName), set(set) {}
|
||||
bool operator<(const Zoom &other) const
|
||||
{return zoom < other.zoom;}
|
||||
|
||||
@ -55,14 +57,16 @@ private:
|
||||
QSize size;
|
||||
Projection projection;
|
||||
Transform transform;
|
||||
QString fileName;
|
||||
QDir set;
|
||||
};
|
||||
|
||||
bool readXML(const QString &path);
|
||||
void oruxTracker(QXmlStreamReader &reader, int level);
|
||||
void mapCalibration(QXmlStreamReader &reader, int level);
|
||||
bool readXML(const QString &path, const QString &dir = QString());
|
||||
void oruxTracker(QXmlStreamReader &reader, const QString &dir, int level);
|
||||
void mapCalibration(QXmlStreamReader &reader, const QString &dir, int level);
|
||||
void calibrationPoints(QXmlStreamReader &reader, const QSize &size,
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user