mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-06 07:32:51 +02:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
fafe6c4b03 | |||
b156e25023 | |||
e15deccfca | |||
9b24bccfed | |||
589c602d21 | |||
b7df3cbe0e | |||
f08f5893a3 | |||
1d5f7db12f | |||
532a1eb69f | |||
1efb4e494d | |||
4653f771a6 | |||
22e5ffaa0c | |||
9a4514a464 | |||
7d47f243ea |
@ -1,4 +1,4 @@
|
||||
version: 11.3.{build}
|
||||
version: 11.4.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
@ -11,7 +11,8 @@ GPS log file formats.
|
||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
|
||||
Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images, BSB charts, KMZ maps,
|
||||
AlpineQuest maps, Locus/OsmAnd/RMaps SQLite maps, Mapsforge vector maps,
|
||||
QCT maps, GEMF maps, Osmdroid SQLite maps, ESRI World-File georeferenced images).
|
||||
QCT maps, GEMF maps, Osmdroid SQLite maps, Orux maps,
|
||||
ESRI World-File georeferenced images).
|
||||
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts
|
||||
graphs.
|
||||
* Support for DEM files (SRTM HGT).
|
||||
|
@ -3,7 +3,7 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 11.3
|
||||
VERSION = 11.4
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
|
2523
lang/gpxsee_ca.ts
Normal file
2523
lang/gpxsee_ca.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -200,13 +200,13 @@
|
||||
<location filename="../src/GUI/elevationgraph.cpp" line="60"/>
|
||||
<source>Up</source>
|
||||
<extracomment>Use an Unicode arrow (U+2197) when there is no abbreviation or extremly short term for "Up" in your language</extracomment>
|
||||
<translation type="unfinished">Opp</translation>
|
||||
<translation>Opp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/elevationgraph.cpp" line="64"/>
|
||||
<source>Down</source>
|
||||
<extracomment>Use an Unicode arrow (U+2198) when there is no abbreviation or extremly short term for "Down" in your language</extracomment>
|
||||
<translation type="unfinished">Ned</translation>
|
||||
<translation>Ned</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/elevationgraph.cpp" line="67"/>
|
||||
@ -374,7 +374,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="219"/>
|
||||
<source>Open directory...</source>
|
||||
<translation type="unfinished">Åpne mappe …</translation>
|
||||
<translation>Åpne mappe …</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="224"/>
|
||||
@ -598,7 +598,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="477"/>
|
||||
<source>Show tabs</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Vis faner</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="486"/>
|
||||
@ -712,7 +712,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="955"/>
|
||||
<source>Open directory</source>
|
||||
<translation type="unfinished">Åpne mappe</translation>
|
||||
<translation>Åpne mappe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="1959"/>
|
||||
@ -1029,7 +1029,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/gearratiograph.cpp" line="28"/>
|
||||
<source>Top</source>
|
||||
<translation type="unfinished">Topp</translation>
|
||||
<translation>Topp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gearratiograph.cpp" line="30"/>
|
||||
@ -1236,7 +1236,7 @@
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="157"/>
|
||||
<source>GEMF maps</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>GEMF-kart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="162"/>
|
||||
@ -1256,7 +1256,7 @@
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="166"/>
|
||||
<source>Orux maps</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Orux-kart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="167"/>
|
||||
@ -1266,7 +1266,7 @@
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="169"/>
|
||||
<source>Osmdroid SQLite maps</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Osmdroid SQLite-kart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="170"/>
|
||||
@ -1286,7 +1286,7 @@
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="177"/>
|
||||
<source>All files</source>
|
||||
<translation type="unfinished">Alle filer</translation>
|
||||
<translation>Alle filer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/map/maplist.cpp" line="168"/>
|
||||
@ -1921,7 +1921,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="779"/>
|
||||
<source>Initial paths</source>
|
||||
<translation type="unfinished">Forvalgte stier</translation>
|
||||
<translation>Forvalgte stier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="814"/>
|
||||
|
@ -37,7 +37,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "11.3"
|
||||
!define VERSION "11.4"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -99,18 +99,26 @@ void WaypointItem::updateCache()
|
||||
QPainterPath p;
|
||||
qreal pointSize = _font.bold() ? HS(_size) : _size;
|
||||
|
||||
if (_showLabel) {
|
||||
if (_showLabel && !_waypoint.name().isEmpty()) {
|
||||
QFontMetrics fm(_font);
|
||||
_labelBB = fm.tightBoundingRect(_waypoint.name());
|
||||
|
||||
if (_showIcon && _icon) {
|
||||
if (_font.bold())
|
||||
p.addRect(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
p.addRect(-_icon->width() * 0.625, _waypoint.icon().isNull()
|
||||
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
|
||||
_icon->width() * 1.25, _icon->height() * 1.25);
|
||||
else
|
||||
p.addRect(-_icon->width()/2.0, -_icon->height(), _icon->width(),
|
||||
p.addRect(-_icon->width()/2.0, _waypoint.icon().isNull()
|
||||
? -_icon->height() : -_icon->height()/2, _icon->width(),
|
||||
_icon->height());
|
||||
p.addRect(0, 0, _labelBB.width(), _labelBB.height() + fm.descent());
|
||||
|
||||
if (_waypoint.icon().isNull())
|
||||
p.addRect(0, 0, _labelBB.width(), _labelBB.height()
|
||||
+ fm.descent());
|
||||
else
|
||||
p.addRect(_icon->width()/2, _icon->height()/2, _labelBB.width(),
|
||||
_labelBB.height() + fm.descent());
|
||||
} else {
|
||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
p.addRect(pointSize/2, pointSize/2, _labelBB.width(),
|
||||
@ -119,10 +127,12 @@ void WaypointItem::updateCache()
|
||||
} else {
|
||||
if (_showIcon && _icon) {
|
||||
if (_font.bold())
|
||||
p.addRect(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
p.addRect(-_icon->width() * 0.625, _waypoint.icon().isNull()
|
||||
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
|
||||
_icon->width() * 1.25, _icon->height() * 1.25);
|
||||
else
|
||||
p.addRect(-_icon->width()/2, -_icon->height(), _icon->width(),
|
||||
p.addRect(-_icon->width()/2, _waypoint.icon().isNull()
|
||||
? -_icon->height() : -_icon->height()/2, _icon->width(),
|
||||
_icon->height());
|
||||
} else
|
||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
@ -140,12 +150,16 @@ void WaypointItem::paint(QPainter *painter,
|
||||
|
||||
painter->setPen(_color);
|
||||
|
||||
if (_showLabel) {
|
||||
if (_showLabel && !_waypoint.name().isEmpty()) {
|
||||
painter->setFont(_font);
|
||||
if (_showIcon && _icon)
|
||||
painter->drawText(-qMax(_labelBB.x(), 0), _labelBB.height(),
|
||||
_waypoint.name());
|
||||
else
|
||||
if (_showIcon && _icon) {
|
||||
if (_waypoint.icon().isNull())
|
||||
painter->drawText(-qMax(_labelBB.x(), 0), _labelBB.height(),
|
||||
_waypoint.name());
|
||||
else
|
||||
painter->drawText(_icon->width()/2 - qMax(_labelBB.x(), 0),
|
||||
_icon->height()/2 + _labelBB.height(), _waypoint.name());
|
||||
} else
|
||||
painter->drawText(pointSize/2 - qMax(_labelBB.x(), 0), pointSize/2
|
||||
+ _labelBB.height(), _waypoint.name());
|
||||
}
|
||||
@ -153,11 +167,13 @@ void WaypointItem::paint(QPainter *painter,
|
||||
painter->setBrush(QBrush(_color, Qt::SolidPattern));
|
||||
if (_showIcon && _icon) {
|
||||
if (_font.bold())
|
||||
painter->drawPixmap(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
painter->drawPixmap(-_icon->width() * 0.625, _waypoint.icon().isNull()
|
||||
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
|
||||
_icon->scaled(_icon->width() * 1.25, _icon->height() * 1.25,
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
else
|
||||
painter->drawPixmap(-_icon->width()/2.0, -_icon->height(), *_icon);
|
||||
painter->drawPixmap(-_icon->width()/2.0, _waypoint.icon().isNull()
|
||||
? -_icon->height() : -_icon->height()/2, *_icon);
|
||||
} else
|
||||
painter->drawEllipse(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
|
||||
|
@ -68,7 +68,7 @@ void NetworkTimeout::timerEvent(QTimerEvent *ev)
|
||||
return;
|
||||
QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
|
||||
if (reply->isRunning())
|
||||
reply->close();
|
||||
reply->abort();
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <QFileInfo>
|
||||
#include <QTemporaryDir>
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <QUrl>
|
||||
#include <QCoreApplication>
|
||||
@ -139,3 +140,9 @@ QString Util::displayName(const QString &path)
|
||||
return path;
|
||||
#endif // Q_OS_ANDROID
|
||||
}
|
||||
|
||||
const QTemporaryDir &Util::tempDir()
|
||||
{
|
||||
static QTemporaryDir dir;
|
||||
return dir;
|
||||
}
|
||||
|
@ -3,12 +3,15 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QTemporaryDir;
|
||||
|
||||
namespace Util
|
||||
{
|
||||
int str2int(const char *str, int len);
|
||||
double niceNum(double x, bool round);
|
||||
QString file2name(const QString &path);
|
||||
QString displayName(const QString &path);
|
||||
const QTemporaryDir &tempDir();
|
||||
}
|
||||
|
||||
#endif // UTIL_H
|
||||
|
@ -53,6 +53,7 @@ static QMultiMap<QString, Parser*> parsers()
|
||||
map.insert("gpx", &gpx);
|
||||
map.insert("tcx", &tcx);
|
||||
map.insert("kml", &kml);
|
||||
map.insert("kmz", &kml);
|
||||
map.insert("fit", &fit);
|
||||
map.insert("csv", &csv);
|
||||
map.insert("igc", &igc);
|
||||
@ -162,7 +163,7 @@ QString Data::formats()
|
||||
+ qApp->translate("Data", "IGC files") + " (*.igc);;"
|
||||
+ qApp->translate("Data", "ITN files") + " (*.itn);;"
|
||||
+ qApp->translate("Data", "JPEG images") + " (*.jpg *.jpeg);;"
|
||||
+ qApp->translate("Data", "KML files") + " (*.kml);;"
|
||||
+ qApp->translate("Data", "KML files") + " (*.kml *.kmz);;"
|
||||
+ qApp->translate("Data", "LOC files") + " (*.loc);;"
|
||||
+ qApp->translate("Data", "NMEA files") + " (*.nmea);;"
|
||||
+ qApp->translate("Data", "ONmove files") + " (*.omd *.ghp);;"
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "common/garmin.h"
|
||||
#include "common/textcodec.h"
|
||||
#include "common/color.h"
|
||||
#include "common/util.h"
|
||||
#include "address.h"
|
||||
#include "gpiparser.h"
|
||||
|
||||
@ -388,12 +389,6 @@ static quint32 readAddress(DataStream &stream, Waypoint &waypoint)
|
||||
return rs + rh.size;
|
||||
}
|
||||
|
||||
static const QTemporaryDir &tempDir()
|
||||
{
|
||||
static QTemporaryDir dir;
|
||||
return dir;
|
||||
}
|
||||
|
||||
static quint32 readImageInfo(DataStream &stream, Waypoint &waypoint,
|
||||
const QString &fileName, int &imgId)
|
||||
{
|
||||
@ -408,12 +403,12 @@ static quint32 readImageInfo(DataStream &stream, Waypoint &waypoint,
|
||||
ba.resize(size);
|
||||
stream.readRawData(ba.data(), ba.size());
|
||||
|
||||
if (tempDir().isValid()) {
|
||||
if (Util::tempDir().isValid()) {
|
||||
QBuffer buf(&ba);
|
||||
QImageReader ir(&buf);
|
||||
|
||||
QByteArray id(fileName.toUtf8() + QByteArray::number(imgId++));
|
||||
QFile imgFile(tempDir().path() + "/" + QString("%0.%1").arg(
|
||||
QFile imgFile(Util::tempDir().path() + "/" + QString("%0.%1").arg(
|
||||
QCryptographicHash::hash(id, QCryptographicHash::Sha1).toHex(),
|
||||
QString(ir.format())));
|
||||
imgFile.open(QIODevice::WriteOnly);
|
||||
|
@ -1,5 +1,33 @@
|
||||
/*
|
||||
WARNING: This code uses internal Qt API - the QZipReader class for reading
|
||||
ZIP files - and things may break if Qt changes the API. For Qt5 this is not
|
||||
a problem as we can "see the future" now and there are no changes in all
|
||||
the supported Qt5 versions up to the last one (5.15). In Qt6 the class
|
||||
might change or even disappear in the future, but this is very unlikely
|
||||
as there were no changes for several years and The Qt Company's policy
|
||||
is: "do not invest any resources into any desktop related stuff unless
|
||||
absolutely necessary". There is an issue (QTBUG-3897) since the year 2009 to
|
||||
include the ZIP reader into the public API, which aptly illustrates the
|
||||
effort The Qt Company is willing to make about anything desktop related...
|
||||
*/
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTemporaryDir>
|
||||
#include <QCryptographicHash>
|
||||
#include <QtEndian>
|
||||
#include <QUrl>
|
||||
#include <QRegularExpression>
|
||||
#include <private/qzipreader_p.h>
|
||||
#include "common/util.h"
|
||||
#include "kmlparser.h"
|
||||
|
||||
static bool isZIP(QFile *file)
|
||||
{
|
||||
quint32 magic;
|
||||
|
||||
return (file->read((char *)&magic, sizeof(magic)) == (qint64)sizeof(magic)
|
||||
&& qFromLittleEndian(magic) == 0x04034b50);
|
||||
}
|
||||
|
||||
qreal KMLParser::number()
|
||||
{
|
||||
@ -463,6 +491,9 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
|
||||
const QDateTime ×tamp)
|
||||
{
|
||||
TrackData *tp = 0;
|
||||
Area *ap = 0;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Point")) {
|
||||
waypoints.append(Waypoint());
|
||||
@ -472,28 +503,90 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
w.setTimestamp(timestamp);
|
||||
point(w);
|
||||
} else if (_reader.name() == QLatin1String("LineString")) {
|
||||
tracks.append(TrackData());
|
||||
TrackData &t = tracks.last();
|
||||
t.append(SegmentData());
|
||||
t.setName(name);
|
||||
t.setDescription(desc);
|
||||
lineString(t.last());
|
||||
if (!tp) {
|
||||
tracks.append(TrackData());
|
||||
tp = &tracks.last();
|
||||
tp->setName(name);
|
||||
tp->setDescription(desc);
|
||||
}
|
||||
tp->append(SegmentData());
|
||||
lineString(tp->last());
|
||||
} else if (_reader.name() == QLatin1String("Polygon")) {
|
||||
areas.append(Area());
|
||||
Area &a = areas.last();
|
||||
a.setName(name);
|
||||
a.setDescription(desc);
|
||||
polygon(a);
|
||||
if (!ap) {
|
||||
areas.append(Area());
|
||||
ap = &areas.last();
|
||||
ap->setName(name);
|
||||
ap->setDescription(desc);
|
||||
}
|
||||
polygon(*ap);
|
||||
} else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::placemark(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||
QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
QString name, desc, phone, address;
|
||||
QString img, id;
|
||||
Waypoint w;
|
||||
static QRegularExpression re("\\$\\[[^\\]]+\\]");
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("name"))
|
||||
w.setName(_reader.readElementText());
|
||||
else if (_reader.name() == QLatin1String("description"))
|
||||
w.setDescription(_reader.readElementText());
|
||||
else if (_reader.name() == QLatin1String("phoneNumber"))
|
||||
w.setPhone(_reader.readElementText());
|
||||
else if (_reader.name() == QLatin1String("address"))
|
||||
w.setAddress(_reader.readElementText());
|
||||
else if (_reader.name() == QLatin1String("TimeStamp"))
|
||||
w.setTimestamp(timeStamp());
|
||||
else if (_reader.name() == QLatin1String("Style")) {
|
||||
style(ctx.dir, icons);
|
||||
id = QString();
|
||||
} else if (_reader.name() == QLatin1String("StyleMap"))
|
||||
styleMap(icons);
|
||||
else if (_reader.name() == QLatin1String("Icon"))
|
||||
img = icon();
|
||||
else if (_reader.name() == QLatin1String("Point"))
|
||||
point(w);
|
||||
else if (_reader.name() == QLatin1String("styleUrl"))
|
||||
id = styleUrl();
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (!w.coordinates().isNull()) {
|
||||
w.setIcon(icons.value(id));
|
||||
|
||||
img.replace(re, "0");
|
||||
if (!QUrl(img).scheme().isEmpty())
|
||||
w.addLink(Link(img, "Photo Overlay"));
|
||||
else if (ctx.zip && Util::tempDir().isValid()) {
|
||||
QFileInfo fi(img);
|
||||
QByteArray id(ctx.path.toUtf8() + img.toUtf8());
|
||||
QString path(Util::tempDir().path() + "/" + QString("%0.%1")
|
||||
.arg(QCryptographicHash::hash(id, QCryptographicHash::Sha1)
|
||||
.toHex(), QString(fi.suffix())));
|
||||
QFile::rename(ctx.dir.absoluteFilePath(img), path);
|
||||
w.addImage(path);
|
||||
} else if (!ctx.zip)
|
||||
w.addImage(ctx.dir.absoluteFilePath(img));
|
||||
|
||||
waypoints.append(w);
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints,
|
||||
QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
QString name, desc, phone, address, id;
|
||||
QDateTime timestamp;
|
||||
Waypoint *wp = 0;
|
||||
TrackData *tp = 0;
|
||||
Area *ap = 0;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("name"))
|
||||
@ -506,87 +599,185 @@ void KMLParser::placemark(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
address = _reader.readElementText();
|
||||
else if (_reader.name() == QLatin1String("TimeStamp"))
|
||||
timestamp = timeStamp();
|
||||
else if (_reader.name() == QLatin1String("Style")) {
|
||||
style(ctx.dir, icons);
|
||||
id = QString();
|
||||
} else if (_reader.name() == QLatin1String("StyleMap"))
|
||||
styleMap(icons);
|
||||
else if (_reader.name() == QLatin1String("MultiGeometry"))
|
||||
multiGeometry(tracks, areas, waypoints, name, desc, timestamp);
|
||||
else if (_reader.name() == QLatin1String("Point")) {
|
||||
waypoints.append(Waypoint());
|
||||
Waypoint &w = waypoints.last();
|
||||
w.setName(name);
|
||||
w.setDescription(desc);
|
||||
w.setTimestamp(timestamp);
|
||||
w.setAddress(address);
|
||||
w.setPhone(phone);
|
||||
point(w);
|
||||
wp = &waypoints.last();
|
||||
point(*wp);
|
||||
} else if (_reader.name() == QLatin1String("LineString")
|
||||
|| _reader.name() == QLatin1String("LinearRing")) {
|
||||
tracks.append(TrackData());
|
||||
TrackData &t = tracks.last();
|
||||
t.append(SegmentData());
|
||||
t.setName(name);
|
||||
t.setDescription(desc);
|
||||
lineString(t.last());
|
||||
tp = &tracks.last();
|
||||
tp->append(SegmentData());
|
||||
lineString(tp->last());
|
||||
} else if (_reader.name() == QLatin1String("Track")) {
|
||||
tracks.append(TrackData());
|
||||
TrackData &t = tracks.last();
|
||||
t.append(SegmentData());
|
||||
t.setName(name);
|
||||
t.setDescription(desc);
|
||||
track(t.last());
|
||||
tp = &tracks.last();
|
||||
tp->append(SegmentData());
|
||||
track(tp->last());
|
||||
} else if (_reader.name() == QLatin1String("MultiTrack")) {
|
||||
tracks.append(TrackData());
|
||||
TrackData &t = tracks.last();
|
||||
t.setName(name);
|
||||
t.setDescription(desc);
|
||||
multiTrack(t);
|
||||
tp = &tracks.last();
|
||||
multiTrack(*tp);
|
||||
} else if (_reader.name() == QLatin1String("Polygon")) {
|
||||
areas.append(Area());
|
||||
Area &a = areas.last();
|
||||
a.setName(name);
|
||||
a.setDescription(desc);
|
||||
polygon(a);
|
||||
} else
|
||||
ap = &areas.last();
|
||||
polygon(*ap);
|
||||
} else if (_reader.name() == QLatin1String("styleUrl"))
|
||||
id = styleUrl();
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (wp) {
|
||||
wp->setName(name);
|
||||
wp->setDescription(desc);
|
||||
wp->setTimestamp(timestamp);
|
||||
wp->setAddress(address);
|
||||
wp->setPhone(phone);
|
||||
wp->setIcon(icons.value(id));
|
||||
} else if (tp) {
|
||||
tp->setName(name);
|
||||
tp->setDescription(desc);
|
||||
} else if (ap) {
|
||||
ap->setName(name);
|
||||
ap->setDescription(desc);
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::folder(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
QString KMLParser::icon()
|
||||
{
|
||||
QString path;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("href"))
|
||||
path = _reader.readElementText();
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
QString KMLParser::styleUrl()
|
||||
{
|
||||
QString id(_reader.readElementText());
|
||||
return (id.at(0) == '#') ? id.right(id.size() - 1) : QString();
|
||||
}
|
||||
|
||||
void KMLParser::iconStyle(const QDir &dir, const QString &id,
|
||||
QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(tracks, areas, waypoints);
|
||||
if (_reader.name() == QLatin1String("Icon"))
|
||||
icons.insert(id, QPixmap(dir.absoluteFilePath(icon())));
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::document(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
void KMLParser::styleMapPair(const QString &id, QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
QString key, url;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Document"))
|
||||
document(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(tracks, areas, waypoints);
|
||||
if (_reader.name() == QLatin1String("key"))
|
||||
key = _reader.readElementText();
|
||||
else if (_reader.name() == QLatin1String("styleUrl"))
|
||||
url = styleUrl();
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (key == "normal")
|
||||
icons.insert(id, icons.value(url));
|
||||
}
|
||||
|
||||
void KMLParser::styleMap(QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
QString id = _reader.attributes().value("id").toString();
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Pair"))
|
||||
styleMapPair(id, icons);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::kml(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
void KMLParser::style(const QDir &dir, QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
QString id = _reader.attributes().value("id").toString();
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("IconStyle"))
|
||||
iconStyle(dir, id, icons);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::folder(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints,
|
||||
QMap<QString, QPixmap> &icons)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Document"))
|
||||
document(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(tracks, areas, waypoints);
|
||||
document(ctx, tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(tracks, areas, waypoints);
|
||||
folder(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("PhotoOverlay"))
|
||||
photoOverlay(ctx, waypoints, icons);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::document(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
QMap<QString, QPixmap> icons;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Document"))
|
||||
document(ctx, tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("PhotoOverlay"))
|
||||
photoOverlay(ctx, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("Style"))
|
||||
style(ctx.dir, icons);
|
||||
else if (_reader.name() == QLatin1String("StyleMap"))
|
||||
styleMap(icons);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::kml(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
QMap<QString, QPixmap> icons;
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Document"))
|
||||
document(ctx, tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(ctx, tracks, areas, waypoints, icons);
|
||||
else if (_reader.name() == QLatin1String("PhotoOverlay"))
|
||||
photoOverlay(ctx, waypoints, icons);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
@ -596,15 +787,50 @@ bool KMLParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
QList<RouteData> &routes, QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
Q_UNUSED(routes);
|
||||
QFileInfo fi(*file);
|
||||
|
||||
_reader.clear();
|
||||
_reader.setDevice(file);
|
||||
|
||||
if (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("kml"))
|
||||
kml(tracks, areas, waypoints);
|
||||
else
|
||||
_reader.raiseError("Not a KML file");
|
||||
if (isZIP(file)) {
|
||||
QZipReader zip(fi.absoluteFilePath(), QIODevice::ReadOnly);
|
||||
QTemporaryDir tempDir;
|
||||
if (!tempDir.isValid() || !zip.extractAll(tempDir.path()))
|
||||
_reader.raiseError("Error extracting ZIP file");
|
||||
else {
|
||||
QDir zipDir(tempDir.path());
|
||||
QFileInfoList files(zipDir.entryInfoList(QStringList("*.kml"),
|
||||
QDir::Files));
|
||||
|
||||
if (files.isEmpty())
|
||||
_reader.raiseError("No KML file found in ZIP file");
|
||||
else {
|
||||
QFile kmlFile(files.first().absoluteFilePath());
|
||||
if (!kmlFile.open(QIODevice::ReadOnly))
|
||||
_reader.raiseError("Error opening KML file");
|
||||
else {
|
||||
_reader.setDevice(&kmlFile);
|
||||
|
||||
if (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("kml"))
|
||||
kml(Ctx(fi.absoluteFilePath(), zipDir, true),
|
||||
tracks, areas, waypoints);
|
||||
else
|
||||
_reader.raiseError("Not a KML file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file->reset();
|
||||
_reader.setDevice(file);
|
||||
|
||||
if (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("kml"))
|
||||
kml(Ctx(fi.absoluteFilePath(), fi.absoluteDir(), false), tracks,
|
||||
areas, waypoints);
|
||||
else
|
||||
_reader.raiseError("Not a KML file");
|
||||
}
|
||||
}
|
||||
|
||||
return !_reader.error();
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include "parser.h"
|
||||
|
||||
class KMLParser : public Parser
|
||||
@ -14,17 +15,28 @@ public:
|
||||
int errorLine() const {return _reader.lineNumber();}
|
||||
|
||||
private:
|
||||
void kml(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
struct Ctx {
|
||||
Ctx(const QString &path, const QDir &dir, bool zip)
|
||||
: path(path), dir(dir), zip(zip) {}
|
||||
|
||||
QString path;
|
||||
QDir dir;
|
||||
bool zip;
|
||||
};
|
||||
|
||||
void kml(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
void document(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
void folder(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
void placemark(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
void document(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
void folder(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints, QMap<QString, QPixmap> &icons);
|
||||
void placemark(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints, QMap<QString, QPixmap> &icons);
|
||||
void multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
|
||||
const QDateTime ×tamp);
|
||||
void photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||
QMap<QString, QPixmap> &icons);
|
||||
void track(SegmentData &segment);
|
||||
void multiTrack(TrackData &t);
|
||||
void lineString(SegmentData &segment);
|
||||
@ -45,6 +57,13 @@ private:
|
||||
QDateTime timeStamp();
|
||||
qreal number();
|
||||
QDateTime time();
|
||||
QString icon();
|
||||
QString styleUrl();
|
||||
void style(const QDir &dir, QMap<QString, QPixmap> &icons);
|
||||
void styleMapPair(const QString &id, QMap<QString, QPixmap> &icons);
|
||||
void styleMap(QMap<QString, QPixmap> &icons);
|
||||
void iconStyle(const QDir &dir, const QString &id,
|
||||
QMap<QString, QPixmap> &icons);
|
||||
|
||||
QXmlStreamReader _reader;
|
||||
};
|
||||
|
@ -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,14 @@ 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;
|
||||
QList<CalibrationPoint> points;
|
||||
QString fileName;
|
||||
Projection proj;
|
||||
Transform t;
|
||||
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (!intAttr(reader, attr, "layerLevel", zoom))
|
||||
@ -256,13 +261,14 @@ 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;
|
||||
QString datum, projection;
|
||||
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (!intAttr(reader, attr, "xMax", xMax))
|
||||
@ -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,52 @@ 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")) {
|
||||
QList<CalibrationPoint> points;
|
||||
|
||||
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 +372,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 +385,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 +483,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 +499,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 +551,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);
|
||||
|
||||
|
Reference in New Issue
Block a user