subsurface/core/divesitehelpers.cpp
Berthold Stoeger 36b9e5e31e Cleanup: fold core/helpers.h into core/qthelper.h
helpers.h included qthelper.h and all functions declared in helpers.h
were defined in qthelper.h. Therefore fold the former into the latter,
since the split seems completely arbitrary.

While doing so, change the return-type of get_dc_nichname from
"const QString" to "QString".

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-06-04 08:50:10 -07:00

176 lines
6.4 KiB
C++

// SPDX-License-Identifier: GPL-2.0
//
// infrastructure to deal with dive sites
//
#include "divesitehelpers.h"
#include "divesite.h"
#include "subsurface-string.h"
#include "qthelper.h"
#include "membuffer.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrlQuery>
#include <QEventLoop>
#include <QTimer>
ReverseGeoLookupThread* ReverseGeoLookupThread::instance()
{
static ReverseGeoLookupThread* self = new ReverseGeoLookupThread();
return self;
}
ReverseGeoLookupThread::ReverseGeoLookupThread(QObject *obj) : QThread(obj)
{
}
void ReverseGeoLookupThread::run()
{
QNetworkRequest request;
QNetworkAccessManager *rgl = new QNetworkAccessManager();
QEventLoop loop;
QString geonamesURL("http://api.geonames.org/findNearbyPlaceNameJSON?lang=%1&lat=%2&lng=%3&radius=50&username=dirkhh");
QString geonamesOceanURL("http://api.geonames.org/oceanJSON?lang=%1&lat=%2&lng=%3&radius=50&username=dirkhh");
QTimer timer;
request.setRawHeader("Accept", "text/json");
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
struct dive_site *ds = &displayed_dive_site;
// first check the findNearbyPlaces API from geonames - that should give us country, state, city
request.setUrl(geonamesURL.arg(uiLanguage(NULL).section(QRegExp("[-_ ]"), 0, 0)).arg(ds->latitude.udeg / 1000000.0).arg(ds->longitude.udeg / 1000000.0));
QNetworkReply *reply = rgl->get(request);
timer.setSingleShot(true);
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
timer.start(5000); // 5 secs. timeout
loop.exec();
if (timer.isActive()) {
timer.stop();
if (reply->error() > 0) {
report_error("got error accessing geonames.org: %s", qPrintable(reply->errorString()));
goto clear_reply;
}
int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (v < 200 || v >= 300)
goto clear_reply;
QByteArray fullReply = reply->readAll();
QJsonParseError errorObject;
QJsonDocument jsonDoc = QJsonDocument::fromJson(fullReply, &errorObject);
if (errorObject.error != QJsonParseError::NoError) {
report_error("error parsing geonames.org response: %s", qPrintable(errorObject.errorString()));
goto clear_reply;
}
QJsonObject obj = jsonDoc.object();
QVariant geoNamesObject = obj.value("geonames").toVariant();
QVariantList geoNames = geoNamesObject.toList();
if (geoNames.count() > 0) {
QVariantMap firstData = geoNames.at(0).toMap();
int ri = 0, l3 = -1, lt = -1;
if (ds->taxonomy.category == NULL) {
ds->taxonomy.category = alloc_taxonomy();
} else {
// clear out the data (except for the ocean data)
int ocean;
if ((ocean = taxonomy_index_for_category(&ds->taxonomy, TC_OCEAN)) > 0) {
ds->taxonomy.category[0] = ds->taxonomy.category[ocean];
ds->taxonomy.nr = 1;
} else {
// ocean is -1 if there is no such entry, and we didn't copy above
// if ocean is 0, so the following gets us the correct count
ds->taxonomy.nr = ocean + 1;
}
}
// get all the data - OCEAN is special, so start at COUNTRY
for (int j = TC_COUNTRY; j < TC_NR_CATEGORIES; j++) {
if (firstData[taxonomy_api_names[j]].isValid()) {
ds->taxonomy.category[ri].category = j;
ds->taxonomy.category[ri].origin = taxonomy_origin::GEOCODED;
free((void *)ds->taxonomy.category[ri].value);
ds->taxonomy.category[ri].value = copy_qstring(firstData[taxonomy_api_names[j]].toString());
ri++;
}
}
ds->taxonomy.nr = ri;
l3 = taxonomy_index_for_category(&ds->taxonomy, TC_ADMIN_L3);
lt = taxonomy_index_for_category(&ds->taxonomy, TC_LOCALNAME);
if (l3 == -1 && lt != -1) {
// basically this means we did get a local name (what we call town), but just like most places
// we didn't get an adminName_3 - which in some regions is the actual city that town belongs to,
// then we copy the town into the city
ds->taxonomy.category[ri].value = copy_string(ds->taxonomy.category[lt].value);
ds->taxonomy.category[ri].origin = taxonomy_origin::GEOCOPIED;
ds->taxonomy.category[ri].category = TC_ADMIN_L3;
ds->taxonomy.nr++;
}
mark_divelist_changed(true);
} else {
report_error("geonames.org did not provide reverse lookup information");
qDebug() << "no reverse geo lookup; geonames returned\n" << fullReply;
}
} else {
report_error("timeout accessing geonames.org");
disconnect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
reply->abort();
}
// next check the oceans API to figure out the body of water
request.setUrl(geonamesOceanURL.arg(uiLanguage(NULL).section(QRegExp("[-_ ]"), 0, 0)).arg(ds->latitude.udeg / 1000000.0).arg(ds->longitude.udeg / 1000000.0));
reply = rgl->get(request);
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
timer.start(5000); // 5 secs. timeout
loop.exec();
if (timer.isActive()) {
timer.stop();
if (reply->error() > 0) {
report_error("got error accessing oceans API of geonames.org: %s", qPrintable(reply->errorString()));
goto clear_reply;
}
int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (v < 200 || v >= 300)
goto clear_reply;
QByteArray fullReply = reply->readAll();
QJsonParseError errorObject;
QJsonDocument jsonDoc = QJsonDocument::fromJson(fullReply, &errorObject);
if (errorObject.error != QJsonParseError::NoError) {
report_error("error parsing geonames.org response: %s", qPrintable(errorObject.errorString()));
goto clear_reply;
}
QJsonObject obj = jsonDoc.object();
QVariant oceanObject = obj.value("ocean").toVariant();
QVariantMap oceanName = oceanObject.toMap();
if (oceanName["name"].isValid()) {
int idx;
if (ds->taxonomy.category == NULL)
ds->taxonomy.category = alloc_taxonomy();
idx = taxonomy_index_for_category(&ds->taxonomy, TC_OCEAN);
if (idx == -1)
idx = ds->taxonomy.nr;
if (idx < TC_NR_CATEGORIES) {
ds->taxonomy.category[idx].category = TC_OCEAN;
ds->taxonomy.category[idx].origin = taxonomy_origin::GEOCODED;
ds->taxonomy.category[idx].value = copy_qstring(oceanName["name"].toString());
if (idx == ds->taxonomy.nr)
ds->taxonomy.nr++;
}
mark_divelist_changed(true);
}
} else {
report_error("timeout accessing geonames.org");
disconnect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
reply->abort();
}
clear_reply:
reply->deleteLater();
rgl->deleteLater();
}