From 7f79ca2329b6c323136aff73ed10c47486872bbb Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabrava@gmail.com>
Date: Sun, 10 May 2015 12:44:35 -0300
Subject: [PATCH] Get the Location Information from a Thread

This makes subsurface usable faster for those without a good
internet connection when they are inporting an older dive.

while parsing, we are only feeding an vector of locations,
after the parsing is due, we traverse the vector searching
for the information on the web.

I need to also add a way to stop if there`s no internet
connection - but this will be another path.

Also, fixed two small memory leaks from the old imp.
Signed-off-by: Tomaz Canabrava <tomaz.canabrava@gmail.com>
---
 divesitehelpers.cpp  | 79 +++++++++++++++++++++++++++++++++++++---------------
 divesitehelpers.h    | 17 +++++++++++
 parse-xml.c          |  4 +--
 qt-ui/mainwindow.cpp |  9 ++++++
 4 files changed, 85 insertions(+), 24 deletions(-)
 create mode 100644 divesitehelpers.h

diff --git a/divesitehelpers.cpp b/divesitehelpers.cpp
index b29ca3f..6f5690a 100644
--- a/divesitehelpers.cpp
+++ b/divesitehelpers.cpp
@@ -1,6 +1,9 @@
 //
 // infrastructure to deal with dive sites
 //
+
+#include "divesitehelpers.h"
+
 #include "divesite.h"
 #include "helpers.h"
 #include "usersurvey.h"
@@ -14,28 +17,60 @@
 #include <QUrlQuery>
 #include <QEventLoop>
 
-extern "C" void reverseGeoLookup(degrees_t latitude, degrees_t longitude, uint32_t uuid)
+struct GeoLoockupInfo {
+    degrees_t lat;
+    degrees_t lon;
+    uint32_t uuid;
+};
+
+QVector<GeoLoockupInfo> geo_loockup_data;
+
+ReverseGeoLoockupThread* ReverseGeoLoockupThread::instance() {
+    static ReverseGeoLoockupThread* self = new ReverseGeoLoockupThread();
+    return self;
+}
+
+ReverseGeoLoockupThread::ReverseGeoLoockupThread(QObject *obj) : QThread(obj)
 {
-	QNetworkRequest request;
-	QNetworkAccessManager *rgl = new QNetworkAccessManager();
-	request.setUrl(QString("http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&accept-language=%1&lat=%2&lon=%3")
-		       .arg(uiLanguage(NULL)).arg(latitude.udeg / 1000000.0).arg(longitude.udeg / 1000000.0));
-	request.setRawHeader("Accept", "text/json");
-	request.setRawHeader("User-Agent", getUserAgent().toUtf8());
-	QNetworkReply *reply = rgl->get(request);
-	QEventLoop loop;
-	QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
-	loop.exec();
-	QJsonParseError errorObject;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &errorObject);
-	if (errorObject.error != QJsonParseError::NoError) {
-		qDebug() << errorObject.errorString();
-	} else {
-		QJsonObject obj = jsonDoc.object();
-		QJsonObject address = obj.value("address").toObject();
-		qDebug() << "found country:" << address.value("country").toString();
-		struct dive_site *ds = get_dive_site_by_uuid(uuid);
-		ds->notes = add_to_string(ds->notes, "countrytag: %s", address.value("country").toString().toUtf8().data());
-	}
 }
 
+void ReverseGeoLoockupThread::run() {
+    if (geo_loockup_data.isEmpty())
+        return;
+
+    QNetworkRequest request;
+    QNetworkAccessManager *rgl = new QNetworkAccessManager();
+    request.setRawHeader("Accept", "text/json");
+    request.setRawHeader("User-Agent", getUserAgent().toUtf8());
+    QEventLoop loop;
+    QString apiCall("http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&accept-language=%1&lat=%2&lon=%3");
+    Q_FOREACH (const GeoLoockupInfo& info, geo_loockup_data ) {
+        request.setUrl(apiCall.arg(uiLanguage(NULL)).arg(info.lat.udeg / 1000000.0).arg(info.lon.udeg / 1000000.0));
+        QNetworkReply *reply = rgl->get(request);
+        QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+        loop.exec();
+        QJsonParseError errorObject;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &errorObject);
+        if (errorObject.error != QJsonParseError::NoError) {
+            qDebug() << errorObject.errorString();
+        } else {
+            QJsonObject obj = jsonDoc.object();
+            QJsonObject address = obj.value("address").toObject();
+            qDebug() << "found country:" << address.value("country").toString();
+            struct dive_site *ds = get_dive_site_by_uuid(info.uuid);
+            ds->notes = add_to_string(ds->notes, "countrytag: %s", address.value("country").toString().toUtf8().data());
+        }
+
+        reply->deleteLater();
+    }
+    rgl->deleteLater();
+}
+
+extern "C" void add_geo_information_for_loockup(degrees_t latitude, degrees_t longitude, uint32_t uuid) {
+    GeoLoockupInfo info;
+    info.lat = latitude;
+    info.lon = longitude;
+    info.uuid = uuid;
+
+    geo_loockup_data.append(info);
+}
diff --git a/divesitehelpers.h b/divesitehelpers.h
new file mode 100644
index 0000000..8b83b98
--- /dev/null
+++ b/divesitehelpers.h
@@ -0,0 +1,17 @@
+#ifndef DIVESITEHELPERS_H
+#define DIVESITEHELPERS_H
+
+#include "units.h"
+#include <QThread>
+
+class ReverseGeoLoockupThread : public QThread {
+Q_OBJECT
+public:
+    static ReverseGeoLoockupThread *instance();
+    void run() Q_DECL_OVERRIDE;
+
+private:
+    ReverseGeoLoockupThread(QObject *parent = 0);
+};
+
+#endif // DIVESITEHELPERS_H
diff --git a/parse-xml.c b/parse-xml.c
index 819d3a8..9f748cd 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -1167,7 +1167,7 @@ static void gps_location(char *buffer, struct dive_site *ds)
 
 /* this is in qthelper.cpp, so including the .h file is a pain */
 extern const char *printGPSCoords(int lat, int lon);
-extern void reverseGeoLookup(degrees_t, degrees_t, uint32_t);
+extern void add_geo_information_for_loockup(degrees_t latitude, degrees_t longitude, uint32_t uuid);
 
 static void gps_in_dive(char *buffer, struct dive *dive)
 {
@@ -1206,7 +1206,7 @@ static void gps_in_dive(char *buffer, struct dive *dive)
 		}
 	}
 	if (ds && (!ds->notes || strstr(ds->notes, "countrytag:") == NULL))
-		reverseGeoLookup(latitude, longitude, dive->dive_site_uuid);
+		add_geo_information_for_loockup(latitude, longitude, dive->dive_site_uuid);
 }
 
 static void add_dive_site(char *buffer, struct dive *dive)
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp
index 970c0f7..47cfa55 100644
--- a/qt-ui/mainwindow.cpp
+++ b/qt-ui/mainwindow.cpp
@@ -32,6 +32,7 @@
 #include "divelogimportdialog.h"
 #include "divelogexportdialog.h"
 #include "usersurvey.h"
+#include "divesitehelpers.h"
 #ifndef NO_USERMANUAL
 #include "usermanual.h"
 #endif
@@ -199,6 +200,10 @@ MainWindow::MainWindow() : QMainWindow(),
 	undoRedoActions.append(undoAction);
 	undoRedoActions.append(redoAction);
 	ui.menu_Edit->addActions(undoRedoActions);
+
+    ReverseGeoLoockupThread *geoLoockup = ReverseGeoLoockupThread::instance();
+    connect(geoLoockup, SIGNAL(start()),information(), SLOT(setDisabled()));
+    connect(geoLoockup, SIGNAL(finished()), information(), SLOT(setEnabled()));
 }
 
 MainWindow::~MainWindow()
@@ -1448,6 +1453,10 @@ void MainWindow::loadFiles(const QStringList fileNames)
 	addRecentFile(fileNames);
 	removeRecentFile(failedParses);
 
+    // searches for geo lookup information in a thread so it doesn`t
+    // freezes the ui.
+    ReverseGeoLoockupThread::instance()->start();
+
 	refreshDisplay();
 	ui.actionAutoGroup->setChecked(autogroup);
 }
-- 
2.3.2 (Apple Git-55)

