mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-02-17 16:20:48 +01:00
Various KML/KMZ parsing fixes and code cleanup
This commit is contained in:
parent
b156e25023
commit
fafe6c4b03
@ -1,6 +1,7 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QTemporaryDir>
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@ -139,3 +140,9 @@ QString Util::displayName(const QString &path)
|
|||||||
return path;
|
return path;
|
||||||
#endif // Q_OS_ANDROID
|
#endif // Q_OS_ANDROID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QTemporaryDir &Util::tempDir()
|
||||||
|
{
|
||||||
|
static QTemporaryDir dir;
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
class QTemporaryDir;
|
||||||
|
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
int str2int(const char *str, int len);
|
int str2int(const char *str, int len);
|
||||||
double niceNum(double x, bool round);
|
double niceNum(double x, bool round);
|
||||||
QString file2name(const QString &path);
|
QString file2name(const QString &path);
|
||||||
QString displayName(const QString &path);
|
QString displayName(const QString &path);
|
||||||
|
const QTemporaryDir &tempDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UTIL_H
|
#endif // UTIL_H
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "common/garmin.h"
|
#include "common/garmin.h"
|
||||||
#include "common/textcodec.h"
|
#include "common/textcodec.h"
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
|
#include "common/util.h"
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
#include "gpiparser.h"
|
#include "gpiparser.h"
|
||||||
|
|
||||||
@ -388,12 +389,6 @@ static quint32 readAddress(DataStream &stream, Waypoint &waypoint)
|
|||||||
return rs + rh.size;
|
return rs + rh.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QTemporaryDir &tempDir()
|
|
||||||
{
|
|
||||||
static QTemporaryDir dir;
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
static quint32 readImageInfo(DataStream &stream, Waypoint &waypoint,
|
static quint32 readImageInfo(DataStream &stream, Waypoint &waypoint,
|
||||||
const QString &fileName, int &imgId)
|
const QString &fileName, int &imgId)
|
||||||
{
|
{
|
||||||
@ -408,12 +403,12 @@ static quint32 readImageInfo(DataStream &stream, Waypoint &waypoint,
|
|||||||
ba.resize(size);
|
ba.resize(size);
|
||||||
stream.readRawData(ba.data(), ba.size());
|
stream.readRawData(ba.data(), ba.size());
|
||||||
|
|
||||||
if (tempDir().isValid()) {
|
if (Util::tempDir().isValid()) {
|
||||||
QBuffer buf(&ba);
|
QBuffer buf(&ba);
|
||||||
QImageReader ir(&buf);
|
QImageReader ir(&buf);
|
||||||
|
|
||||||
QByteArray id(fileName.toUtf8() + QByteArray::number(imgId++));
|
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(),
|
QCryptographicHash::hash(id, QCryptographicHash::Sha1).toHex(),
|
||||||
QString(ir.format())));
|
QString(ir.format())));
|
||||||
imgFile.open(QIODevice::WriteOnly);
|
imgFile.open(QIODevice::WriteOnly);
|
||||||
|
@ -18,14 +18,9 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <private/qzipreader_p.h>
|
#include <private/qzipreader_p.h>
|
||||||
|
#include "common/util.h"
|
||||||
#include "kmlparser.h"
|
#include "kmlparser.h"
|
||||||
|
|
||||||
static const QTemporaryDir &tempDir()
|
|
||||||
{
|
|
||||||
static QTemporaryDir dir;
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isZIP(QFile *file)
|
static bool isZIP(QFile *file)
|
||||||
{
|
{
|
||||||
quint32 magic;
|
quint32 magic;
|
||||||
@ -496,6 +491,9 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
|||||||
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
|
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
|
||||||
const QDateTime ×tamp)
|
const QDateTime ×tamp)
|
||||||
{
|
{
|
||||||
|
TrackData *tp = 0;
|
||||||
|
Area *ap = 0;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("Point")) {
|
if (_reader.name() == QLatin1String("Point")) {
|
||||||
waypoints.append(Waypoint());
|
waypoints.append(Waypoint());
|
||||||
@ -505,18 +503,22 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
|||||||
w.setTimestamp(timestamp);
|
w.setTimestamp(timestamp);
|
||||||
point(w);
|
point(w);
|
||||||
} else if (_reader.name() == QLatin1String("LineString")) {
|
} else if (_reader.name() == QLatin1String("LineString")) {
|
||||||
tracks.append(TrackData());
|
if (!tp) {
|
||||||
TrackData &t = tracks.last();
|
tracks.append(TrackData());
|
||||||
t.append(SegmentData());
|
tp = &tracks.last();
|
||||||
t.setName(name);
|
tp->setName(name);
|
||||||
t.setDescription(desc);
|
tp->setDescription(desc);
|
||||||
lineString(t.last());
|
}
|
||||||
|
tp->append(SegmentData());
|
||||||
|
lineString(tp->last());
|
||||||
} else if (_reader.name() == QLatin1String("Polygon")) {
|
} else if (_reader.name() == QLatin1String("Polygon")) {
|
||||||
areas.append(Area());
|
if (!ap) {
|
||||||
Area &a = areas.last();
|
areas.append(Area());
|
||||||
a.setName(name);
|
ap = &areas.last();
|
||||||
a.setDescription(desc);
|
ap->setName(name);
|
||||||
polygon(a);
|
ap->setDescription(desc);
|
||||||
|
}
|
||||||
|
polygon(*ap);
|
||||||
} else
|
} else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@ -525,65 +527,55 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
|||||||
void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||||
QMap<QString, QPixmap> &icons)
|
QMap<QString, QPixmap> &icons)
|
||||||
{
|
{
|
||||||
QString name, desc, phone, address, path, link, id;
|
QString img, id;
|
||||||
QDateTime timestamp;
|
Waypoint w;
|
||||||
|
static QRegularExpression re("\\$\\[[^\\]]+\\]");
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("name"))
|
if (_reader.name() == QLatin1String("name"))
|
||||||
name = _reader.readElementText();
|
w.setName(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("description"))
|
else if (_reader.name() == QLatin1String("description"))
|
||||||
desc = _reader.readElementText();
|
w.setDescription(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("phoneNumber"))
|
else if (_reader.name() == QLatin1String("phoneNumber"))
|
||||||
phone = _reader.readElementText();
|
w.setPhone(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("address"))
|
else if (_reader.name() == QLatin1String("address"))
|
||||||
address = _reader.readElementText();
|
w.setAddress(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("TimeStamp"))
|
else if (_reader.name() == QLatin1String("TimeStamp"))
|
||||||
timestamp = timeStamp();
|
w.setTimestamp(timeStamp());
|
||||||
else if (_reader.name() == QLatin1String("Style"))
|
else if (_reader.name() == QLatin1String("Style")) {
|
||||||
style(ctx.dir, icons);
|
style(ctx.dir, icons);
|
||||||
else if (_reader.name() == QLatin1String("Icon")) {
|
id = QString();
|
||||||
QString image(icon());
|
} else if (_reader.name() == QLatin1String("StyleMap"))
|
||||||
|
styleMap(icons);
|
||||||
QRegularExpression re("\\$\\[[^\\]]+\\]");
|
else if (_reader.name() == QLatin1String("Icon"))
|
||||||
image.replace(re, "0");
|
img = icon();
|
||||||
QUrl url(image);
|
else if (_reader.name() == QLatin1String("Point"))
|
||||||
|
|
||||||
if (url.scheme() == "http" || url.scheme() == "https")
|
|
||||||
link = image;
|
|
||||||
else {
|
|
||||||
if (ctx.zip) {
|
|
||||||
if (tempDir().isValid()) {
|
|
||||||
QFileInfo fi(image);
|
|
||||||
QByteArray id(ctx.path.toUtf8() + image.toUtf8());
|
|
||||||
path = tempDir().path() + "/" + QString("%0.%1").arg(
|
|
||||||
QCryptographicHash::hash(id, QCryptographicHash::Sha1)
|
|
||||||
.toHex(), QString(fi.suffix()));
|
|
||||||
|
|
||||||
QFile::rename(ctx.dir.absoluteFilePath(image), path);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
path = ctx.dir.absoluteFilePath(image);
|
|
||||||
}
|
|
||||||
} 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);
|
|
||||||
w.setIcon(icons.value(id));
|
|
||||||
if (!path.isNull())
|
|
||||||
w.addImage(path);
|
|
||||||
if (!link.isNull())
|
|
||||||
w.addLink(Link(link, "Photo Overlay"));
|
|
||||||
point(w);
|
point(w);
|
||||||
} else if (_reader.name() == QLatin1String("styleUrl")) {
|
else if (_reader.name() == QLatin1String("styleUrl"))
|
||||||
id = _reader.readElementText();
|
id = styleUrl();
|
||||||
id = (id.at(0) == '#') ? id.right(id.size() - 1) : QString();
|
else
|
||||||
} else
|
|
||||||
_reader.skipCurrentElement();
|
_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,
|
void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
|
||||||
@ -592,6 +584,9 @@ void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
|
|||||||
{
|
{
|
||||||
QString name, desc, phone, address, id;
|
QString name, desc, phone, address, id;
|
||||||
QDateTime timestamp;
|
QDateTime timestamp;
|
||||||
|
Waypoint *wp = 0;
|
||||||
|
TrackData *tp = 0;
|
||||||
|
Area *ap = 0;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("name"))
|
if (_reader.name() == QLatin1String("name"))
|
||||||
@ -604,53 +599,56 @@ void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
|
|||||||
address = _reader.readElementText();
|
address = _reader.readElementText();
|
||||||
else if (_reader.name() == QLatin1String("TimeStamp"))
|
else if (_reader.name() == QLatin1String("TimeStamp"))
|
||||||
timestamp = timeStamp();
|
timestamp = timeStamp();
|
||||||
else if (_reader.name() == QLatin1String("Style"))
|
else if (_reader.name() == QLatin1String("Style")) {
|
||||||
style(ctx.dir, icons);
|
style(ctx.dir, icons);
|
||||||
|
id = QString();
|
||||||
|
} else if (_reader.name() == QLatin1String("StyleMap"))
|
||||||
|
styleMap(icons);
|
||||||
else if (_reader.name() == QLatin1String("MultiGeometry"))
|
else if (_reader.name() == QLatin1String("MultiGeometry"))
|
||||||
multiGeometry(tracks, areas, waypoints, name, desc, timestamp);
|
multiGeometry(tracks, areas, waypoints, name, desc, timestamp);
|
||||||
else if (_reader.name() == QLatin1String("Point")) {
|
else if (_reader.name() == QLatin1String("Point")) {
|
||||||
waypoints.append(Waypoint());
|
waypoints.append(Waypoint());
|
||||||
Waypoint &w = waypoints.last();
|
wp = &waypoints.last();
|
||||||
w.setName(name);
|
point(*wp);
|
||||||
w.setDescription(desc);
|
|
||||||
w.setTimestamp(timestamp);
|
|
||||||
w.setAddress(address);
|
|
||||||
w.setPhone(phone);
|
|
||||||
w.setIcon(icons.value(id));
|
|
||||||
point(w);
|
|
||||||
} else if (_reader.name() == QLatin1String("LineString")
|
} else if (_reader.name() == QLatin1String("LineString")
|
||||||
|| _reader.name() == QLatin1String("LinearRing")) {
|
|| _reader.name() == QLatin1String("LinearRing")) {
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
TrackData &t = tracks.last();
|
tp = &tracks.last();
|
||||||
t.append(SegmentData());
|
tp->append(SegmentData());
|
||||||
t.setName(name);
|
lineString(tp->last());
|
||||||
t.setDescription(desc);
|
|
||||||
lineString(t.last());
|
|
||||||
} else if (_reader.name() == QLatin1String("Track")) {
|
} else if (_reader.name() == QLatin1String("Track")) {
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
TrackData &t = tracks.last();
|
tp = &tracks.last();
|
||||||
t.append(SegmentData());
|
tp->append(SegmentData());
|
||||||
t.setName(name);
|
track(tp->last());
|
||||||
t.setDescription(desc);
|
|
||||||
track(t.last());
|
|
||||||
} else if (_reader.name() == QLatin1String("MultiTrack")) {
|
} else if (_reader.name() == QLatin1String("MultiTrack")) {
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
TrackData &t = tracks.last();
|
tp = &tracks.last();
|
||||||
t.setName(name);
|
multiTrack(*tp);
|
||||||
t.setDescription(desc);
|
|
||||||
multiTrack(t);
|
|
||||||
} else if (_reader.name() == QLatin1String("Polygon")) {
|
} else if (_reader.name() == QLatin1String("Polygon")) {
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
Area &a = areas.last();
|
ap = &areas.last();
|
||||||
a.setName(name);
|
polygon(*ap);
|
||||||
a.setDescription(desc);
|
} else if (_reader.name() == QLatin1String("styleUrl"))
|
||||||
polygon(a);
|
id = styleUrl();
|
||||||
} else if (_reader.name() == QLatin1String("styleUrl")) {
|
else
|
||||||
id = _reader.readElementText();
|
|
||||||
id = (id.at(0) == '#') ? id.right(id.size() - 1) : QString();
|
|
||||||
} else
|
|
||||||
_reader.skipCurrentElement();
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString KMLParser::icon()
|
QString KMLParser::icon()
|
||||||
@ -667,6 +665,12 @@ QString KMLParser::icon()
|
|||||||
return path;
|
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,
|
void KMLParser::iconStyle(const QDir &dir, const QString &id,
|
||||||
QMap<QString, QPixmap> &icons)
|
QMap<QString, QPixmap> &icons)
|
||||||
{
|
{
|
||||||
@ -678,6 +682,35 @@ void KMLParser::iconStyle(const QDir &dir, const QString &id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KMLParser::styleMapPair(const QString &id, QMap<QString, QPixmap> &icons)
|
||||||
|
{
|
||||||
|
QString key, url;
|
||||||
|
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
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::style(const QDir &dir, QMap<QString, QPixmap> &icons)
|
void KMLParser::style(const QDir &dir, QMap<QString, QPixmap> &icons)
|
||||||
{
|
{
|
||||||
QString id = _reader.attributes().value("id").toString();
|
QString id = _reader.attributes().value("id").toString();
|
||||||
@ -724,6 +757,8 @@ void KMLParser::document(const Ctx &ctx, QList<TrackData> &tracks,
|
|||||||
photoOverlay(ctx, waypoints, icons);
|
photoOverlay(ctx, waypoints, icons);
|
||||||
else if (_reader.name() == QLatin1String("Style"))
|
else if (_reader.name() == QLatin1String("Style"))
|
||||||
style(ctx.dir, icons);
|
style(ctx.dir, icons);
|
||||||
|
else if (_reader.name() == QLatin1String("StyleMap"))
|
||||||
|
styleMap(icons);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,10 @@ private:
|
|||||||
qreal number();
|
qreal number();
|
||||||
QDateTime time();
|
QDateTime time();
|
||||||
QString icon();
|
QString icon();
|
||||||
|
QString styleUrl();
|
||||||
void style(const QDir &dir, QMap<QString, QPixmap> &icons);
|
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,
|
void iconStyle(const QDir &dir, const QString &id,
|
||||||
QMap<QString, QPixmap> &icons);
|
QMap<QString, QPixmap> &icons);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user