Get the location information in a separate thread

This makes Subsurface usable faster for those without a good internet
connection when they are opening an older data file.

While parsing, we are only feeding an vector of locations, after the
parsing is done, 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 patch.

Also, fixed two small memory leaks from the old imp.

[Dirk Hohndel: cleaned up the whitespace mess]

Signed-off-by: Tomaz Canabrava <tomaz.canabrava@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Tomaz Canabrava 2015-05-10 12:44:35 -03:00 committed by Dirk Hohndel
parent 412844c02b
commit 627de38c01
4 changed files with 87 additions and 26 deletions

View file

@ -1,6 +1,9 @@
// //
// infrastructure to deal with dive sites // infrastructure to deal with dive sites
// //
#include "divesitehelpers.h"
#include "divesite.h" #include "divesite.h"
#include "helpers.h" #include "helpers.h"
#include "usersurvey.h" #include "usersurvey.h"
@ -14,28 +17,60 @@
#include <QUrlQuery> #include <QUrlQuery>
#include <QEventLoop> #include <QEventLoop>
extern "C" void reverseGeoLookup(degrees_t latitude, degrees_t longitude, uint32_t uuid) struct GeoLoockupInfo {
{ degrees_t lat;
QNetworkRequest request; degrees_t lon;
QNetworkAccessManager *rgl = new QNetworkAccessManager(); uint32_t uuid;
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"); QVector<GeoLoockupInfo> geo_loockup_data;
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
QNetworkReply *reply = rgl->get(request); ReverseGeoLoockupThread* ReverseGeoLoockupThread::instance() {
QEventLoop loop; static ReverseGeoLoockupThread* self = new ReverseGeoLoockupThread();
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); return self;
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());
}
} }
ReverseGeoLoockupThread::ReverseGeoLoockupThread(QObject *obj) : QThread(obj)
{
}
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);
}

17
divesitehelpers.h Normal file
View file

@ -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

View file

@ -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 */ /* this is in qthelper.cpp, so including the .h file is a pain */
extern const char *printGPSCoords(int lat, int lon); 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) 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)) 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) static void add_dive_site(char *buffer, struct dive *dive)

View file

@ -32,6 +32,7 @@
#include "divelogimportdialog.h" #include "divelogimportdialog.h"
#include "divelogexportdialog.h" #include "divelogexportdialog.h"
#include "usersurvey.h" #include "usersurvey.h"
#include "divesitehelpers.h"
#ifndef NO_USERMANUAL #ifndef NO_USERMANUAL
#include "usermanual.h" #include "usermanual.h"
#endif #endif
@ -199,6 +200,10 @@ MainWindow::MainWindow() : QMainWindow(),
undoRedoActions.append(undoAction); undoRedoActions.append(undoAction);
undoRedoActions.append(redoAction); undoRedoActions.append(redoAction);
ui.menu_Edit->addActions(undoRedoActions); 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() MainWindow::~MainWindow()
@ -1292,7 +1297,7 @@ int MainWindow::file_save_as(void)
QString filename; QString filename;
const char *default_filename = existing_filename; const char *default_filename = existing_filename;
QFileDialog selection_dialog(this, tr("Save file as"), default_filename, QFileDialog selection_dialog(this, tr("Save file as"), default_filename,
tr("Subsurface XML files (*.ssrf *.xml *.XML)")); tr("Subsurface XML files (*.ssrf *.xml *.XML)"));
/* if the exit/cancel button is pressed return */ /* if the exit/cancel button is pressed return */
if (!selection_dialog.exec()) if (!selection_dialog.exec())
@ -1448,6 +1453,10 @@ void MainWindow::loadFiles(const QStringList fileNames)
addRecentFile(fileNames); addRecentFile(fileNames);
removeRecentFile(failedParses); removeRecentFile(failedParses);
// searches for geo lookup information in a thread so it doesn`t
// freezes the ui.
ReverseGeoLoockupThread::instance()->start();
refreshDisplay(); refreshDisplay();
ui.actionAutoGroup->setChecked(autogroup); ui.actionAutoGroup->setChecked(autogroup);
} }