From 0ed630dd20575568a513a9e900035eaafec76ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 20 Jan 2025 23:27:44 +0100 Subject: [PATCH] Added support for geo URIs (RFC 5870) --- src/GUI/gui.cpp | 40 +++++++++++++++++++++++++++++ src/GUI/gui.h | 1 + src/data/data.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++ src/data/data.h | 1 + 4 files changed, 106 insertions(+) diff --git a/src/GUI/gui.cpp b/src/GUI/gui.cpp index 5102305e..627a0484 100644 --- a/src/GUI/gui.cpp +++ b/src/GUI/gui.cpp @@ -1069,6 +1069,16 @@ void GUI::openDir() bool GUI::openFile(const QString &fileName, bool tryUnknown, int &showError) { + QUrl url(fileName); + if (url.scheme() == "geo") { + if (loadURL(url, showError)) { + _fileActionGroup->setEnabled(true); + _reloadFileAction->setEnabled(false); + return true; + } else if (showError) + return false; + } + QFileInfo fi(fileName); QString canonicalFileName(fi.canonicalFilePath()); @@ -1099,6 +1109,36 @@ bool GUI::openFile(const QString &fileName, bool tryUnknown, int &showError) return true; } +bool GUI::loadURL(const QUrl &url, int &showError) +{ + Data data(url); + + if (data.isValid()) { + loadData(data); + return true; + } else { + if (showError) { + QString error = tr("Error loading geo URI:") + "\n" + url.toString() + + ": " + data.errorString(); + + if (showError > 1) { + QMessageBox message(QMessageBox::Critical, APP_NAME, error, + QMessageBox::Ok, this); + QCheckBox checkBox(tr("Don't show again")); + message.setCheckBox(&checkBox); + message.exec(); + if (checkBox.isChecked()) + showError = 0; + } else + QMessageBox::critical(this, APP_NAME, error); + } else + qWarning("%s: %s", qUtf8Printable(url.toString()), + qUtf8Printable(data.errorString())); + + return false; + } +} + bool GUI::loadFile(const QString &fileName, bool tryUnknown, int &showError) { Data data(fileName, tryUnknown); diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 3b3dd7cc..f8020de7 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -158,6 +158,7 @@ private: #endif // Q_OS_ANDROID bool openPOIFile(const QString &fileName); bool loadFile(const QString &fileName, bool tryUnknown, int &showError); + bool loadURL(const QUrl &url, int &showError); void loadData(const Data &data); bool loadMapNode(const TreeNode &node, MapAction *&action, const QList &existingActions, int &showError); diff --git a/src/data/data.cpp b/src/data/data.cpp index e9b7a888..c88bec56 100644 --- a/src/data/data.cpp +++ b/src/data/data.cpp @@ -2,6 +2,7 @@ #include #include #include "common/util.h" +#include "map/crs.h" #include "gpxparser.h" #include "tcxparser.h" #include "csvparser.h" @@ -154,6 +155,69 @@ Data::Data(const QString &fileName, bool tryUnknown) } } +Data::Data(const QUrl &url) +{ + bool caOk, cbOk, ccOk; + Coordinates c; + Projection proj; + + _valid = false; + + QStringList parts(url.path().split(';')); + if (parts.size() < 1) { + _errorString = "Syntax error"; + return; + } + QStringList coords(parts.at(0).split(',')); + if (coords.size() < 2 || coords.size() > 3) { + _errorString = "Syntax error"; + return; + } + double ca = coords.at(0).toDouble(&caOk); + double cb = coords.at(1).toDouble(&cbOk); + double cc = NAN; + if (!(caOk && cbOk)) { + _errorString = "Invalid coordinates"; + return; + } + if (coords.size() > 2) { + cc = coords.at(2).toDouble(&ccOk); + if (!ccOk) { + _errorString = "Invalid elevation"; + return; + } + } + + if (parts.size() > 1) { + QStringList crsp(parts.at(1).split('=')); + if (crsp.size() != 2) { + _errorString = "Syntax error"; + return; + } + if (!crsp.at(0).compare("crs", Qt::CaseInsensitive)) { + if (crsp.at(1).compare("wgs84", Qt::CaseInsensitive)) { + proj = CRS::projection(crsp.at(1)); + if (!proj.isValid()) { + _errorString = "Unknown CRS"; + return; + } + } + } + } + + c = proj.isValid() ? proj.xy2ll(PointD(ca, cb)) : Coordinates(cb, ca); + if (!c.isValid()) { + _errorString = "Invalid coordinates"; + return; + } + + Waypoint w(c); + w.setElevation(cc); + _waypoints.append(w); + + _valid = true; +} + QString Data::formats() { return diff --git a/src/data/data.h b/src/data/data.h index 257f6263..0e27bd9a 100644 --- a/src/data/data.h +++ b/src/data/data.h @@ -14,6 +14,7 @@ class Data { public: Data(const QString &fileName, bool tryUnknown = true); + Data(const QUrl &url); bool isValid() const {return _valid;} const QString &errorString() const {return _errorString;}