summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2013-12-23 14:56:40 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-12-23 14:59:38 -0800
commit9405895285f90932bee9db439fe6a13234f65395 (patch)
tree31872978e42f3e8975299c59e0dbace14e928530
parentebffd75a79c2c0e331df09c584d8cf92736b2260 (diff)
downloadsubsurface-9405895285f90932bee9db439fe6a13234f65395.tar.gz
Improve GPS string handling
This adds support for two more GPS coordinate formats and also fixes a couple of issues with the previous implementation. We used to only support full degrees and decimal minutes. We now also support fully decimal and degrees, minutes and decimal seconds. The previous implementation would color the input field red if either it couldn't parse the string, or if it was able to parse it but it was the same as the previous location. That's misleading. The previous implementation also changed all gps coordinates to the new coordinates in a multi-dive edit - instead of just changing the ones that are the same as the master dive. Fixes #387 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--qt-ui/maintab.cpp7
-rw-r--r--qthelper.cpp54
-rw-r--r--qthelper.h2
3 files changed, 50 insertions, 13 deletions
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index 028627292..5d020268c 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -920,11 +920,12 @@ void MainTab::on_notes_textChanged()
void MainTab::on_coordinates_textChanged(const QString& text)
{
- bool gpsChanged = FALSE;
- EDIT_SELECTED_DIVES(gpsChanged |= gpsHasChanged(mydive, NULL, text));
+ bool gpsChanged = false;
+ bool parsed = false;
+ EDIT_SELECTED_DIVES(gpsChanged |= gpsHasChanged(mydive, current_dive, text, &parsed));
if (gpsChanged) {
markChangedWidget(ui.coordinates);
- } else {
+ } else if (!parsed) {
QPalette p;
p.setBrush(QPalette::Base, QColor(Qt::red).lighter());
ui.coordinates->setPalette(p);
diff --git a/qthelper.cpp b/qthelper.cpp
index ff9bf9492..36b3ef182 100644
--- a/qthelper.cpp
+++ b/qthelper.cpp
@@ -101,31 +101,67 @@ QString weight_string(int weight_in_grams)
bool parseGpsText(const QString& gps_text, double *latitude, double *longitude)
{
+ enum { SECONDS, MINUTES, DECIMAL } gpsStyle = DECIMAL;
+ int eastWest = 4;
+ QString regExp;
/* an empty string is interpreted as 0.0,0.0 and therefore "no gps location" */
if (gps_text.trimmed() == "") {
*latitude = 0.0;
*longitude = 0.0;
return true;
}
- QString regExp = QString("\\s*([NS%1%2])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)\\.(\\d+)[^EW%3%4]*([EW%6%7])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)\\.(\\d+)")
- .arg(tr("N")).arg(tr("S")).arg(tr("E")).arg(tr("W")).arg(tr("E")).arg(tr("W"));
+ // trying to parse all formats in one regexp might be possible, but it seems insane
+ // so handle the three formats we understand separately
+ if (gps_text.count(QChar('"')) == 2) {
+ gpsStyle = SECONDS;
+ regExp = QString("\\s*([NS%1%2])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)[\'\\s]+(\\d+)\\.(\\d+)[^EW%3%4]*"
+ "([EW%6%7])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)[\'\\s]+(\\d+)\\.(\\d+)")
+ .arg(tr("N")).arg(tr("S")).arg(tr("E")).arg(tr("W")).arg(tr("E")).arg(tr("W"));
+ } else if (gps_text.count(QChar('\'')) == 2) {
+ gpsStyle = MINUTES;
+ regExp = QString("\\s*([NS%1%2])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)\\.(\\d+)[^EW%3%4]*"
+ "([EW%6%7])\\s*(\\d+)[" UTF8_DEGREE "\\s]+(\\d+)\\.(\\d+)")
+ .arg(tr("N")).arg(tr("S")).arg(tr("E")).arg(tr("W")).arg(tr("E")).arg(tr("W"));
+ } else {
+ regExp = QString("\\s*([-NS%1%2]?)\\s*(\\d+)\\.(\\d+)[^-EW%3%4\\d]*([-EW%5%6]?)\\s*(\\d+)\\.(\\d+)")
+ .arg(tr("N")).arg(tr("S")).arg(tr("E")).arg(tr("W")).arg(tr("E")).arg(tr("W"));
+ }
QRegExp r(regExp);
- if (r.indexIn(gps_text) != 8) {
+ if (r.indexIn(gps_text) != -1) {
// qDebug() << "Hemisphere" << r.cap(1) << "deg" << r.cap(2) << "min" << r.cap(3) << "decimal" << r.cap(4);
// qDebug() << "Hemisphere" << r.cap(5) << "deg" << r.cap(6) << "min" << r.cap(7) << "decimal" << r.cap(8);
- *latitude = r.cap(2).toInt() + (r.cap(3) + QString(".") + r.cap(4)).toDouble() / 60.0;
- *longitude = r.cap(6).toInt() + (r.cap(7) + QString(".") + r.cap(8)).toDouble() / 60.0;
- if (r.cap(1) == "S" || r.cap(1) == tr("S"))
+ switch(gpsStyle) {
+ case SECONDS:
+ *latitude = r.cap(2).toInt() + r.cap(3).toInt() / 60.0 +
+ (r.cap(4) + QString(".") + r.cap(5)).toDouble() / 3600.0;
+ *longitude = r.cap(7).toInt() + r.cap(8).toInt() / 60.0 +
+ (r.cap(9) + QString(".") + r.cap(10)).toDouble() / 3600.0;
+ eastWest = 6;
+ break;
+ case MINUTES:
+ *latitude = r.cap(2).toInt() + (r.cap(3) + QString(".") + r.cap(4)).toDouble() / 60.0;
+ *longitude = r.cap(6).toInt() + (r.cap(7) + QString(".") + r.cap(8)).toDouble() / 60.0;
+ eastWest = 5;
+ break;
+ case DECIMAL:
+ default:
+ *latitude = (r.cap(2) + QString(".") + r.cap(3)).toDouble();
+ *longitude = (r.cap(5) + QString(".") + r.cap(6)).toDouble();
+ eastWest = 4;
+ break;
+ }
+ if (r.cap(1) == "S" || r.cap(1) == tr("S") || r.cap(1) == "-")
*latitude *= -1.0;
- if (r.cap(5) == "W" || r.cap(5) == tr("W"))
+ if (r.cap(eastWest) == "W" || r.cap(5) == tr("W") || r.cap(5) == "-")
*longitude *= -1.0;
// qDebug("%s -> %8.5f / %8.5f", gps_text.toLocal8Bit().data(), *latitude, *longitude);
return true;
}
+ qDebug() << "rejected";
return false;
}
-bool gpsHasChanged(struct dive *dive, struct dive *master, const QString& gps_text)
+bool gpsHasChanged(struct dive *dive, struct dive *master, const QString& gps_text, bool *parsed)
{
double latitude, longitude;
int latudeg, longudeg;
@@ -136,7 +172,7 @@ bool gpsHasChanged(struct dive *dive, struct dive *master, const QString& gps_te
master->longitude.udeg != dive->longitude.udeg))
return false;
- if (!parseGpsText(gps_text, &latitude, &longitude))
+ if (!(*parsed = parseGpsText(gps_text, &latitude, &longitude)))
return false;
latudeg = rint(1000000 * latitude);
diff --git a/qthelper.h b/qthelper.h
index 4b0939334..630a595e8 100644
--- a/qthelper.h
+++ b/qthelper.h
@@ -39,7 +39,7 @@ public:
};
QString weight_string(int weight_in_grams);
-bool gpsHasChanged(struct dive* dive, struct dive *master, const QString &gps_text);
+bool gpsHasChanged(struct dive* dive, struct dive *master, const QString &gps_text, bool *parsed);
QList<int> getDivesInTrip(dive_trip_t *trip);
#endif // QTHELPER_H