summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2015-07-02 07:03:03 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-07-02 07:03:03 -0700
commitf554c2d16cb5816b6b1a97b0349488bc70b512b0 (patch)
tree60811b1d64c2f37378ed20147f829cf74849d1dd
parent1d59b028c91ab7943cfece4a113948c61110dfc3 (diff)
parent0a0a6f07d5dbb2c24184d22c3c2cedf89ffdc7ac (diff)
downloadsubsurface-f554c2d16cb5816b6b1a97b0349488bc70b512b0.tar.gz
Merge branch 'taxonomy'
-rw-r--r--CMakeLists.txt1
-rw-r--r--divesite.c15
-rw-r--r--divesite.h2
-rw-r--r--divesitehelpers.cpp120
-rw-r--r--divesitehelpers.h1
-rw-r--r--icons/geocode.svg1010
-rw-r--r--load-git.c18
-rw-r--r--parse-xml.c24
-rw-r--r--pref.h5
-rw-r--r--qt-models/divelocationmodel.cpp4
-rw-r--r--qt-ui/maintab.cpp28
-rw-r--r--qt-ui/maintab.h1
-rw-r--r--qt-ui/maintab.ui66
-rw-r--r--qt-ui/preferences.cpp25
-rw-r--r--save-git.c8
-rw-r--r--save-xml.c15
-rw-r--r--subsurface.qrc1
-rw-r--r--subsurfacestartup.c4
-rw-r--r--taxonomy.c36
-rw-r--r--taxonomy.h39
20 files changed, 1358 insertions, 65 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58b61aea4..534e8e2b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -306,6 +306,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
configuredivecomputer.cpp
configuredivecomputerthreads.cpp
divesitehelpers.cpp
+ taxonomy.c
checkcloudconnection.cpp
windowtitleupdate.cpp
divelogexportlogic.cpp
diff --git a/divesite.c b/divesite.c
index 41d96de5d..cd8ee8a7d 100644
--- a/divesite.c
+++ b/divesite.c
@@ -169,6 +169,19 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy)
copy->notes = copy_string(orig->notes);
copy->description = copy_string(orig->description);
copy->uuid = orig->uuid;
+ copy->taxonomy.nr = orig->taxonomy.nr;
+ if (orig->taxonomy.category == NULL) {
+ free(copy->taxonomy.category);
+ copy->taxonomy.category = NULL;
+ } else {
+ if (copy->taxonomy.category == NULL)
+ copy->taxonomy.category = alloc_taxonomy();
+ for (int i = 0; i < NR_CATEGORIES; i++) {
+ free((void *)copy->taxonomy.category[i].value);
+ copy->taxonomy.category[i] = orig->taxonomy.category[i];
+ copy->taxonomy.category[i].value = copy_string(orig->taxonomy.category[i].value);
+ }
+ }
}
void clear_dive_site(struct dive_site *ds)
@@ -182,4 +195,6 @@ void clear_dive_site(struct dive_site *ds)
ds->latitude.udeg = 0;
ds->longitude.udeg = 0;
ds->uuid = 0;
+ ds->taxonomy.nr = 0;
+ free_taxonomy(ds->taxonomy.category);
}
diff --git a/divesite.h b/divesite.h
index 71f3c0de7..306272e96 100644
--- a/divesite.h
+++ b/divesite.h
@@ -2,6 +2,7 @@
#define DIVESITE_H
#include "units.h"
+#include "taxonomy.h"
#include <stdlib.h>
#ifdef __cplusplus
@@ -17,6 +18,7 @@ struct dive_site
degrees_t latitude, longitude;
char *description;
char *notes;
+ struct taxonomy_data taxonomy;
};
struct dive_site_table {
diff --git a/divesitehelpers.cpp b/divesitehelpers.cpp
index 62b48ba94..d635969da 100644
--- a/divesitehelpers.cpp
+++ b/divesitehelpers.cpp
@@ -41,54 +41,134 @@ void ReverseGeoLookupThread::run() {
QNetworkRequest request;
QNetworkAccessManager *rgl = new QNetworkAccessManager();
+ QEventLoop loop;
+ QString mapquestURL("http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&accept-language=%1&lat=%2&lon=%3");
+ QString geonamesURL("http://api.geonames.org/findNearbyPlaceNameJSON?language=%1&lat=%2&lng=%3&radius=50&username=dirkhh");
+ QString geonamesOceanURL("http://api.geonames.org/oceanJSON?language=%1&lat=%2&lng=%3&radius=50&username=dirkhh");
+ QString divelogsURL("https://www.divelogs.de/mapsearch_divespotnames.php?lat=%1&lng=%2&radius=50");
+ QTimer timer;
+
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");
+ connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+
Q_FOREACH (const GeoLookupInfo& info, geo_lookup_data ) {
- request.setUrl(apiCall.arg(uiLanguage(NULL)).arg(info.lat.udeg / 1000000.0).arg(info.lon.udeg / 1000000.0));
+ struct dive_site *ds = get_dive_site_by_uuid(info.uuid);
+
+ // first check the findNearbyPlaces API from geonames - that should give us country, state, city
+ request.setUrl(geonamesURL.arg(uiLanguage(NULL)).arg(info.lat.udeg / 1000000.0).arg(info.lon.udeg / 1000000.0));
QNetworkReply *reply = rgl->get(request);
- QTimer timer;
timer.setSingleShot(true);
-
- QEventLoop loop;
- connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
- timer.start(500); // 30 secs. timeout
+ timer.start(5000); // 5 secs. timeout
loop.exec();
if(timer.isActive()) {
timer.stop();
- if(reply->error() > 0)
+ if(reply->error() > 0) {
+ report_error("got error accessing geonames.org: %s", 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(reply->readAll(), &errorObject);
- if (errorObject.error != QJsonParseError::NoError)
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(fullReply, &errorObject);
+ if (errorObject.error != QJsonParseError::NoError) {
+ report_error("error parsing geonames.org response: %s", errorObject.errorString());
goto clear_reply;
-
+ }
QJsonObject obj = jsonDoc.object();
- QJsonObject address = obj.value("address").toObject();
-
- 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());
-
+ QVariant geoNamesObject = obj.value("geonames").toVariant();
+ QVariantList geoNames = geoNamesObject.toList();
+ if (geoNames.count() > 0) {
+ QVariantMap firstData = geoNames.at(0).toMap();
+ int ri = 0;
+ if (ds->taxonomy.category == NULL)
+ ds->taxonomy.category = alloc_taxonomy();
+ // get all the data - OCEAN is special, so start at COUNTRY
+ for (int j = COUNTRY; j < NR_CATEGORIES; j++) {
+ if (firstData[taxonomy_api_names[j]].isValid()) {
+ ds->taxonomy.category[ri].category = j;
+ ds->taxonomy.category[ri].origin = taxonomy::GEOCODED;
+ free((void*)ds->taxonomy.category[ri].value);
+ ds->taxonomy.category[ri].value = copy_string(qPrintable(firstData[taxonomy_api_names[j]].toString()));
+ ri++;
+ }
+ }
+ ds->taxonomy.nr = ri;
+ 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)).arg(info.lat.udeg / 1000000.0).arg(info.lon.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", 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", errorObject.errorString());
+ goto clear_reply;
+ }
+ QJsonObject obj = jsonDoc.object();
+ QVariant oceanObject = obj.value("ocean").toVariant();
+ QVariantMap oceanName = oceanObject.toMap();
+ if (oceanName["name"].isValid()) {
+ if (ds->taxonomy.category == NULL)
+ ds->taxonomy.category = alloc_taxonomy();
+ ds->taxonomy.category[ds->taxonomy.nr].category = OCEAN;
+ ds->taxonomy.category[ds->taxonomy.nr].origin = taxonomy::GEOCODED;
+ ds->taxonomy.category[ds->taxonomy.nr].value = copy_string(qPrintable(oceanName["name"].toString()));
+ 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:
+clear_reply:
reply->deleteLater();
}
rgl->deleteLater();
}
+void ReverseGeoLookupThread::lookup(dive_site *ds)
+{
+ if (!ds)
+ return;
+ GeoLookupInfo info;
+ info.lat = ds->latitude;
+ info.lon = ds->longitude;
+ info.uuid = ds->uuid;
+
+ geo_lookup_data.clear();
+ geo_lookup_data.append(info);
+ run();
+}
+
extern "C" void add_geo_information_for_lookup(degrees_t latitude, degrees_t longitude, uint32_t uuid) {
GeoLookupInfo info;
info.lat = latitude;
diff --git a/divesitehelpers.h b/divesitehelpers.h
index dad60be36..a08069bc0 100644
--- a/divesitehelpers.h
+++ b/divesitehelpers.h
@@ -8,6 +8,7 @@ class ReverseGeoLookupThread : public QThread {
Q_OBJECT
public:
static ReverseGeoLookupThread *instance();
+ void lookup(struct dive_site *ds);
void run() Q_DECL_OVERRIDE;
private:
diff --git a/icons/geocode.svg b/icons/geocode.svg
new file mode 100644
index 000000000..517e8788f
--- /dev/null
+++ b/icons/geocode.svg
@@ -0,0 +1,1010 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg3440"
+ sodipodi:version="0.32"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="geocode.svg"
+ version="1.1">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient4263"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4265" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6527">
+ <stop
+ style="stop-color:#346604;stop-opacity:1;"
+ offset="0"
+ id="stop6529" />
+ <stop
+ style="stop-color:#4e9a06;stop-opacity:1;"
+ offset="1"
+ id="stop6531" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6001">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6003" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6005" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4825">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4827" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4829" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4126">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4128" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.16494845;"
+ offset="1.0000000"
+ id="stop4130" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4114">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4116" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4118" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3962">
+ <stop
+ style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop3964" />
+ <stop
+ style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+ offset="0.15517241"
+ id="stop4134" />
+ <stop
+ style="stop-color:#4074ae;stop-opacity:1.0000000;"
+ offset="0.75000000"
+ id="stop4346" />
+ <stop
+ style="stop-color:#36486c;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop3966" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3962"
+ id="radialGradient3968"
+ gradientTransform="matrix(1.0056311,0,0,1.0056304,-1.7078855,0.3818364)"
+ cx="18.247644"
+ cy="15.716079"
+ fx="18.247644"
+ fy="15.716079"
+ r="29.993349"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4114"
+ id="radialGradient4120"
+ gradientTransform="scale(1.643990,0.608276)"
+ cx="15.115514"
+ cy="63.965388"
+ fx="15.115514"
+ fy="63.965388"
+ r="12.289036"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4126"
+ id="radialGradient4132"
+ gradientTransform="matrix(1.0056311,0,0,1.0056304,-1.7078855,0.3818364)"
+ cx="15.601279"
+ cy="12.142302"
+ fx="15.601279"
+ fy="12.142302"
+ r="43.526714"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4825"
+ id="radialGradient5983"
+ gradientUnits="userSpaceOnUse"
+ cx="12.071323"
+ cy="12.493138"
+ fx="12.071323"
+ fy="12.493138"
+ r="6.7175145" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4825"
+ id="radialGradient5985"
+ gradientUnits="userSpaceOnUse"
+ cx="12.071323"
+ cy="12.493138"
+ fx="12.071323"
+ fy="12.493138"
+ r="6.7175145" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4825"
+ id="radialGradient5987"
+ gradientUnits="userSpaceOnUse"
+ cx="12.071323"
+ cy="12.493138"
+ fx="12.071323"
+ fy="12.493138"
+ r="6.7175145" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4825"
+ id="radialGradient5989"
+ gradientUnits="userSpaceOnUse"
+ cx="12.071323"
+ cy="12.493138"
+ fx="12.071323"
+ fy="12.493138"
+ r="6.7175145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6001"
+ id="linearGradient6007"
+ x1="-25.176178"
+ y1="30.057165"
+ x2="-22.252472"
+ y2="21.041553"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6001"
+ id="linearGradient6011"
+ gradientUnits="userSpaceOnUse"
+ x1="-25.176178"
+ y1="30.057165"
+ x2="-22.113543"
+ y2="22.661524" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6001"
+ id="linearGradient6015"
+ gradientUnits="userSpaceOnUse"
+ x1="-22.822565"
+ y1="28.337734"
+ x2="-22.113543"
+ y2="22.661524" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6001"
+ id="linearGradient6019"
+ gradientUnits="userSpaceOnUse"
+ x1="-21.658581"
+ y1="15.649428"
+ x2="-21.962101"
+ y2="21.336346" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6533"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4126-4"
+ id="radialGradient3976"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.5,0,20)"
+ cx="23.857143"
+ cy="40"
+ fx="23.857143"
+ fy="40"
+ r="17.142857" />
+ <linearGradient
+ id="linearGradient4126-4"
+ inkscape:collect="always">
+ <stop
+ id="stop4128-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop4130-7"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ r="17.142857"
+ fy="40"
+ fx="23.857143"
+ cy="40"
+ cx="23.857143"
+ gradientTransform="matrix(1,0,0,0.5,0,20)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient6386"
+ xlink:href="#linearGradient4126-4"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6405"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6407"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6409"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6411"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6413"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6415"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6417"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6419"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6421"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6423"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6425"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6427"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6429"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6431"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6433"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6435"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6437"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6439"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6441"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6443"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6445"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6447"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6451"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6453"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6455"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6457"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6459"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6461"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6463"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6465"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6467"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6469"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6471"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6473"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6475"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6477"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6479"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6481"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6527"
+ id="radialGradient6483"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.95295618,-0.02665615,0.02617771,0.93591558,0.66318174,2.1792646)"
+ cx="37.17944"
+ cy="31.09733"
+ fx="37.17944"
+ fy="31.09733"
+ r="19.094028" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.17254902"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.70710678"
+ inkscape:cx="-8.1678924"
+ inkscape:cy="22.159373"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:window-width="1680"
+ inkscape:window-height="979"
+ inkscape:window-x="-4"
+ inkscape:window-y="0"
+ inkscape:showpageshadow="false"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid6369" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Tuomas Kuosmanen</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>internet</rdf:li>
+ <rdf:li>tools</rdf:li>
+ <rdf:li>applications</rdf:li>
+ <rdf:li>category</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ id="g4279"
+ transform="matrix(0.84505189,0,0,0.87570125,6.6573985,5.9718062)">
+ <ellipse
+ style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.6;fill:url(#radialGradient6386);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none"
+ id="path6548"
+ transform="matrix(1.070555,0,0,0.525,-1.5403842,22.5)"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true"
+ cx="23.857143"
+ cy="40"
+ rx="17.142857"
+ ry="8.5714283" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3214"
+ d="m 42.499998,23.999308 c 0,10.769899 -8.731089,19.50069 -19.499752,19.50069 -10.76965,0 -19.5002462,-8.73089 -19.5002462,-19.50069 C 3.4999998,13.229902 12.230596,4.5 23.000246,4.5 c 10.768663,0 19.499752,8.729902 19.499752,19.499308 l 0,0 z"
+ style="fill:url(#radialGradient3968);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1" />
+ <g
+ transform="matrix(0.98791378,0,0,0.98789128,-1.5861235,0.6160591)"
+ style="fill:url(#radialGradient6533);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="g4136">
+ <g
+ style="fill:url(#radialGradient6409);fill-opacity:1"
+ id="g4138">
+ <g
+ style="fill:url(#radialGradient6407);fill-opacity:1"
+ id="g4142">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6405);fill-opacity:1"
+ id="path4144"
+ d="M 43.879656,20.648284 43.5264,21.3316 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 0,1.0684 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 l 0,0.8223 -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 l 0,0.5762 -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 -0.9443,0 -0.7998,0.4941 -0.5098,0 0,-0.6582 -0.2168,-1.3184 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 -0.9824,0 -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 0.9453,0 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 -0.292,0 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 -0.4355,0 0,-1.4814 0.9453,-0.4941 0.7266,0 -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 0.8008,0 -0.2188,-0.5752 0.5098,-0.3291 0,0.6582 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 l 0,-0.7411 0.3633,-0.8228 -0.3633,0 -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 0,-0.4941 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 -0.9453,0 0.9453,0.9873 0.7266,-0.8223 0.157078,-0.282273 c 3.129549,2.868759 5.87898,6.664564 6.592678,11.694257 z" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6415);fill-opacity:1"
+ id="g4146">
+ <g
+ style="fill:url(#radialGradient6413);fill-opacity:1"
+ id="g4150">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6411);fill-opacity:1"
+ id="path4152"
+ d="m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6421);fill-opacity:1"
+ id="g4154">
+ <g
+ style="fill:url(#radialGradient6419);fill-opacity:1"
+ id="g4158">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6417);fill-opacity:1"
+ id="path4160"
+ d="m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 0,0.6582 -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6427);fill-opacity:1"
+ id="g4162">
+ <g
+ style="fill:url(#radialGradient6425);fill-opacity:1"
+ id="g4166">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6423);fill-opacity:1"
+ id="path4168"
+ d="m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6433);fill-opacity:1"
+ id="g4170">
+ <g
+ style="fill:url(#radialGradient6431);fill-opacity:1"
+ id="g4174">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6429);fill-opacity:1"
+ id="path4176"
+ d="m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 l -0.4355,0 0,0.4932 0.29,0.3291 0,0.7402" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6439);fill-opacity:1"
+ id="g4178">
+ <g
+ style="fill:url(#radialGradient6437);fill-opacity:1"
+ id="g4182">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6435);fill-opacity:1"
+ id="path4184"
+ d="m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 0,0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 0,-0.9053 -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 l -0.5093,0 -0.5083,0.6582 -0.5093,0.2461 -0.7271,-0.4102 -0.0728,-0.9053 0.1455,-0.9873 1.0908,-0.8223 0.8721,0 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 0.8716,0 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.703332,0.055478 -0.859632,0.094078 C 9.9867169,11.059151 6.5013568,14.983265 5.6916,22.2885 c 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 0,0.1328 -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6445);fill-opacity:1"
+ id="g4186">
+ <g
+ style="fill:url(#radialGradient6443);fill-opacity:1"
+ id="g4190">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6441);fill-opacity:1"
+ id="path4192"
+ d="m 16.7656,9.5649 0.7266,0.4937 0.582,0 0,-0.5757 -0.7266,-0.3291 -0.582,0.4111" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6451);fill-opacity:1"
+ id="g4194">
+ <g
+ style="fill:url(#radialGradient6449);fill-opacity:1"
+ id="g4198">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6447);fill-opacity:1"
+ id="path4200"
+ d="m 14.876,8.9072 -0.3638,0.9048 0.7271,0 0.3638,-0.8228 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6461);fill-opacity:1"
+ id="g4202">
+ <g
+ id="g4204"
+ style="opacity:0.75;fill:url(#radialGradient6455);fill-opacity:1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6453);fill-opacity:1"
+ d=""
+ id="path4206" />
+ </g>
+ <g
+ style="fill:url(#radialGradient6459);fill-opacity:1"
+ id="g4208">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6457);fill-opacity:1"
+ d=""
+ id="path4210" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6471);fill-opacity:1"
+ id="g4212">
+ <g
+ id="g4214"
+ style="opacity:0.75;fill:url(#radialGradient6465);fill-opacity:1">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6463);fill-opacity:1"
+ d=""
+ id="path4216" />
+ </g>
+ <g
+ style="fill:url(#radialGradient6469);fill-opacity:1"
+ id="g4218">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6467);fill-opacity:1"
+ d=""
+ id="path4220" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6477);fill-opacity:1"
+ id="g4222">
+ <g
+ style="fill:url(#radialGradient6475);fill-opacity:1"
+ id="g4226">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6473);fill-opacity:1"
+ id="path4228"
+ d="M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641" />
+ </g>
+ </g>
+ <g
+ style="fill:url(#radialGradient6483);fill-opacity:1"
+ id="g4230">
+ <g
+ style="fill:url(#radialGradient6481);fill-opacity:1"
+ id="g4234">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient6479);fill-opacity:1"
+ id="path4236"
+ d="m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514" />
+ </g>
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path4122"
+ d="m 41.509682,23.999343 c 0,10.222944 -8.287677,18.51034 -18.509448,18.51034 -10.222709,0 -18.5099181,-8.287489 -18.5099181,-18.51034 0,-10.222477 8.2872091,-18.5090269 18.5099181,-18.5090269 10.221771,0 18.509448,8.2865499 18.509448,18.5090269 l 0,0 z"
+ style="opacity:0.39560439;fill:none;stroke:url(#radialGradient4132);stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1" />
+ </g>
+ <g
+ id="g4273"
+ transform="matrix(1.4956472,0,0,1.3787502,153.00985,-30.324792)">
+ <circle
+ r="5"
+ cy="28"
+ cx="-80"
+ id="path3457"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3459"
+ d="m -84.122312,30.680358 c 3.979207,6.02077 3.979207,5.734066 3.979207,5.734066"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.9553436px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3461"
+ d="m -80.03025,36.522258 c 4.407011,-6.153274 4.407011,-6.153274 4.407011,-6.153274"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.04144919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4271"
+ d="m -80,25 c 0,6 0,6 0,6 l 0,-3 -3,0 6,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/load-git.c b/load-git.c
index 0610cd0d8..7cfad325f 100644
--- a/load-git.c
+++ b/load-git.c
@@ -300,6 +300,22 @@ static void parse_site_gps(char *line, struct membuffer *str, void *_ds)
ds->longitude = parse_degrees(line, &line);
}
+static void parse_site_geo(char *line, struct membuffer *str, void *_ds)
+{
+ fprintf(stderr, "line |%s| str |%s|\n", line, mb_cstring(str));
+ struct dive_site *ds = _ds;
+ if (ds->taxonomy.category == NULL)
+ ds->taxonomy.category = alloc_taxonomy();
+ int nr = ds->taxonomy.nr;
+ if (nr < NR_CATEGORIES) {
+ struct taxonomy *t = &ds->taxonomy.category[nr];
+ t->value = strdup(mb_cstring(str));
+ sscanf(line, "cat %d origin %d \"", &t->category, &t->origin);
+ fprintf(stderr, "found category %d origin %d value |%s|\n", t->category, t->origin, t->value);
+ ds->taxonomy.nr++;
+ }
+}
+
/* Parse key=val parts of samples and cylinders etc */
static char *parse_keyvalue_entry(void (*fn)(void *, const char *, const char *), void *fndata, char *line)
{
@@ -906,7 +922,7 @@ static void dive_parser(char *line, struct membuffer *str, void *_dive)
struct keyword_action site_action[] = {
#undef D
#define D(x) { #x, parse_site_ ## x }
- D(description), D(gps), D(name), D(notes)
+ D(description), D(geo), D(gps), D(name), D(notes)
};
static void site_parser(char *line, struct membuffer *str, void *_ds)
diff --git a/parse-xml.c b/parse-xml.c
index 4b6901f7f..879e31fd2 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -1431,6 +1431,8 @@ static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, cha
start_match("divesite", name, buf);
struct dive_site *ds = *ds_p;
+ if (ds->taxonomy.category == NULL)
+ ds->taxonomy.category = alloc_taxonomy();
if (MATCH("uuid", hex_value, &ds->uuid))
return;
@@ -1442,6 +1444,15 @@ static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, cha
return;
if (MATCH("gps", gps_location, ds))
return;
+ if (MATCH("cat.geo", get_index, (int *)&ds->taxonomy.category[ds->taxonomy.nr].category))
+ return;
+ if (MATCH("origin.geo", get_index, (int *)&ds->taxonomy.category[ds->taxonomy.nr].origin))
+ return;
+ if (MATCH("value.geo", utf8_string, &ds->taxonomy.category[ds->taxonomy.nr].value)) {
+ if (ds->taxonomy.nr < NR_CATEGORIES)
+ ds->taxonomy.nr++;
+ return;
+ }
nonmatch("divesite", name, buf);
}
@@ -1517,14 +1528,17 @@ static void dive_site_end(void)
if (!cur_dive_site)
return;
if (cur_dive_site->uuid) {
- uint32_t tmp = create_dive_site_with_gps(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude);
- struct dive_site *ds = get_dive_site_by_uuid(tmp);
- ds->uuid = cur_dive_site->uuid;
- ds->notes = cur_dive_site->notes;
- ds->description = cur_dive_site->description;
+ struct dive_site *ds = alloc_dive_site();
+ if (cur_dive_site->taxonomy.nr == 0) {
+ free(cur_dive_site->taxonomy.category);
+ cur_dive_site->taxonomy.category = NULL;
+ }
+ copy_dive_site(cur_dive_site, ds);
+
if (verbose > 3)
printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name);
}
+ free_taxonomy(cur_dive_site->taxonomy.category);
free(cur_dive_site);
cur_dive_site = NULL;
}
diff --git a/pref.h b/pref.h
index 03b28a98c..0470d0e3b 100644
--- a/pref.h
+++ b/pref.h
@@ -6,6 +6,7 @@ extern "C" {
#endif
#include "units.h"
+#include "taxonomy.h"
/* can't use 'bool' for the boolean values - different size in C and C++ */
typedef struct
@@ -28,9 +29,7 @@ typedef struct {
bool enable_geocoding;
bool parse_dive_without_gps;
bool tag_existing_dives;
- char *first_item;
- char *second_item;
- char *third_item;
+ enum taxonomy_category category[3];
} geocoding_prefs_t;
struct preferences {
diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp
index 53f518941..3d3c77616 100644
--- a/qt-models/divelocationmodel.cpp
+++ b/qt-models/divelocationmodel.cpp
@@ -116,6 +116,8 @@ GeoReferencingOptionsModel *GeoReferencingOptionsModel::instance() {
GeoReferencingOptionsModel::GeoReferencingOptionsModel(QObject *parent) : QStringListModel(parent)
{
QStringList list;
- list << "Country" << "State" << "District" << "Town" << "Suburb" << "Body of Water" << "Site Name";
+ int i;
+ for (i = 0; i < NR_CATEGORIES; i++)
+ list << taxonomy_category_names[i];
setStringList(list);
}
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index 144a43094..591f665d5 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -77,6 +77,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui.location->setCompleter(completer);
connect(ui.addDiveSite, SIGNAL(clicked()), this, SLOT(showDiveSiteSimpleEdit()));
+ connect(ui.geocodeButton, SIGNAL(clicked()), this, SLOT(reverseGeocode()));
QAction *action = new QAction(tr("Apply changes"), this);
connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
@@ -506,9 +507,26 @@ void MainTab::updateDiveInfo(bool clear)
if (!clear) {
struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid);
+ ui.geocodeButton->setVisible(ds && dive_site_has_gps_location(ds));
if (ds) {
+ // construct the location tags
+ QString locationTag;
+ if (ds->taxonomy.nr) {
+ locationTag = "<small><small>(tags: ";
+ QString connector = "";
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < NR_CATEGORIES; j++) {
+ if (ds->taxonomy.category[j].category == prefs.geocoding.category[i]) {
+ locationTag += connector + QString(ds->taxonomy.category[j].value);
+ connector = " / ";
+ break;
+ }
+ }
+ }
+ locationTag += ")</small></small>";
+ }
ui.location->setText(ds->name);
- ui.locationTags->setText(ds->description); // TODO: This should be three tags following davide's explanation.
+ ui.locationTags->setText(locationTag);
if (displayed_dive.dive_site_uuid)
copy_dive_site(get_dive_site_by_uuid(displayed_dive.dive_site_uuid), &displayed_dive_site);
} else {
@@ -546,6 +564,7 @@ void MainTab::updateDiveInfo(bool clear)
ui.watertemp->setVisible(false);
// rename the remaining fields and fill data from selected trip
ui.LocationLabel->setText(tr("Trip location"));
+ ui.locationTags->clear();
ui.location->setText(currentTrip->location);
ui.NotesLabel->setText(tr("Trip notes"));
ui.notes->setText(currentTrip->notes);
@@ -1538,3 +1557,10 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what)
weightModel->changed = true;
}
}
+
+void MainTab::reverseGeocode()
+{
+ ReverseGeoLookupThread *geoLookup = ReverseGeoLookupThread::instance();
+ geoLookup->lookup(&displayed_dive_site);
+ MainWindow::instance()->information()->updateDiveInfo();
+}
diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h
index c96acb28a..306aee66e 100644
--- a/qt-ui/maintab.h
+++ b/qt-ui/maintab.h
@@ -98,6 +98,7 @@ slots:
void disableGeoLookupEdition();
void setCurrentLocationIndex();
void showDiveSiteSimpleEdit();
+ void reverseGeocode();
private:
Ui::MainTab ui;
WeightModel *weightModel;
diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui
index 7ac703076..3318bf788 100644
--- a/qt-ui/maintab.ui
+++ b/qt-ui/maintab.ui
@@ -167,25 +167,38 @@
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>5</number>
+ </property>
+ <property name="rightMargin">
+ <number>5</number>
+ </property>
<property name="spacing">
<number>0</number>
</property>
<item>
- <widget class="QLabel" name="LocationLabel">
- <property name="text">
- <string>Location</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="locationTags">
- <property name="text">
- <string/>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="LocationLayout" stretch="0,1">
+ <item>
+ <widget class="QLabel" name="LocationLabel">
+ <property name="text">
+ <string>Location</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="locationTags">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
@@ -207,6 +220,17 @@
</widget>
</item>
<item>
+ <widget class="QToolButton" name="geocodeButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../subsurface.qrc">
+ <normaloff>:/geocode</normaloff>:/geocode</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QtWaitingSpinner" name="waitingSpinner" native="true"/>
</item>
</layout>
@@ -539,8 +563,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>449</width>
- <height>743</height>
+ <width>100</width>
+ <height>30</height>
</rect>
</property>
<layout class="QGridLayout" name="equipmentTabScrollAreaLayout">
@@ -634,8 +658,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>449</width>
- <height>743</height>
+ <width>286</width>
+ <height>300</height>
</rect>
</property>
<layout class="QGridLayout" name="diveInfoScrollAreaLayout">
@@ -975,8 +999,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>449</width>
- <height>743</height>
+ <width>297</width>
+ <height>177</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
diff --git a/qt-ui/preferences.cpp b/qt-ui/preferences.cpp
index c93460f9a..25638c991 100644
--- a/qt-ui/preferences.cpp
+++ b/qt-ui/preferences.cpp
@@ -241,9 +241,9 @@ void PreferencesDialog::setUiFromPrefs()
ui.enable_geocoding->setChecked( prefs.geocoding.enable_geocoding );
ui.parse_without_gps->setChecked(prefs.geocoding.parse_dive_without_gps);
ui.tag_existing_dives->setChecked(prefs.geocoding.tag_existing_dives);
- ui.first_item->setCurrentText(prefs.geocoding.first_item);
- ui.second_item->setCurrentText(prefs.geocoding.second_item);
- ui.third_item->setCurrentText(prefs.geocoding.third_item);
+ ui.first_item->setCurrentIndex(prefs.geocoding.category[0]);
+ ui.second_item->setCurrentIndex(prefs.geocoding.category[1]);
+ ui.third_item->setCurrentIndex(prefs.geocoding.category[2]);
}
void PreferencesDialog::restorePrefs()
@@ -288,6 +288,13 @@ void PreferencesDialog::rememberPrefs()
else \
prefs.field = default_prefs.field
+#define GET_ENUM(name, type, field) \
+ v = s.value(QString(name)); \
+ if (v.isValid()) \
+ prefs.field = (enum type)v.toInt(); \
+ else \
+ prefs.field = default_prefs.field
+
#define GET_INT_DEF(name, field, defval) \
v = s.value(QString(name)); \
if (v.isValid()) \
@@ -455,9 +462,9 @@ void PreferencesDialog::syncSettings()
s.setValue("enable_geocoding", ui.enable_geocoding->isChecked());
s.setValue("parse_dives_without_gps", ui.parse_without_gps->isChecked());
s.setValue("tag_existing_dives", ui.tag_existing_dives->isChecked());
- s.setValue("first_item", ui.first_item->currentText());
- s.setValue("second_item", ui.second_item->currentText());
- s.setValue("third_item", ui.third_item->currentText());
+ s.setValue("cat0", ui.first_item->currentIndex());
+ s.setValue("cat1", ui.second_item->currentIndex());
+ s.setValue("cat2", ui.third_item->currentIndex());
s.endGroup();
loadSettings();
@@ -603,9 +610,9 @@ void PreferencesDialog::loadSettings()
GET_BOOL("enable_geocoding", geocoding.enable_geocoding);
GET_BOOL("parse_dives_without_gps", geocoding.parse_dive_without_gps);
GET_BOOL("tag_existing_dives", geocoding.tag_existing_dives);
- GET_TXT("first_item", geocoding.first_item);
- GET_TXT("second_item", geocoding.second_item);
- GET_TXT("third_item", geocoding.third_item);
+ GET_ENUM("cat0", taxonomy_category, geocoding.category[0]);
+ GET_ENUM("cat1", taxonomy_category, geocoding.category[1]);
+ GET_ENUM("cat2", taxonomy_category, geocoding.category[2]);
s.endGroup();
}
diff --git a/save-git.c b/save-git.c
index a18ef8f84..ff82ca841 100644
--- a/save-git.c
+++ b/save-git.c
@@ -897,6 +897,14 @@ static void save_divesites(git_repository *repo, struct dir *tree)
show_utf8(&b, "description ", ds->description, "\n");
show_utf8(&b, "notes ", ds->notes, "\n");
show_gps(&b, ds->latitude, ds->longitude);
+ if (prefs.geocoding.enable_geocoding)
+ for (int j = 0; j < ds->taxonomy.nr; j++) {
+ struct taxonomy *t = &ds->taxonomy.category[j];
+ if (t->category != NONE) {
+ put_format(&b, "geo cat %d origin %d ", t->category, t->origin);
+ show_utf8(&b, "", t->value, "\n" );
+ }
+ }
blob_insert(repo, subdir, &b, mb_cstring(&site_file_name));
}
}
diff --git a/save-xml.c b/save-xml.c
index 988ede1bf..a81d4258d 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -539,7 +539,20 @@ void save_dives_buffer(struct membuffer *b, const bool select_only)
}
show_utf8(b, ds->description, " description='", "'", 1);
show_utf8(b, ds->notes, " notes='", "'", 1);
- put_format(b, "/>\n");
+ if (prefs.geocoding.enable_geocoding && ds->taxonomy.nr) {
+ put_format(b, ">\n");
+ for (int j = 0; j < ds->taxonomy.nr; j++) {
+ struct taxonomy *t = &ds->taxonomy.category[j];
+ if (t->category != NONE) {
+ put_format(b, "<geo cat='%d'", t->category);
+ put_format(b, " origin='%d'", t->origin);
+ show_utf8(b, t->value, " value='", "'/>\n", 1);
+ }
+ }
+ put_format(b, "</site>\n");
+ } else {
+ put_format(b, "/>\n");
+ }
}
put_format(b, "</divesites>\n<dives>\n");
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
diff --git a/subsurface.qrc b/subsurface.qrc
index a28c86ad6..349d9d7b2 100644
--- a/subsurface.qrc
+++ b/subsurface.qrc
@@ -78,5 +78,6 @@
<file alias="filter-close">icons/process-stop.svg</file>
<file alias="edit">icons/edit-circled.svg</file>
<file alias="satellite">icons/Emblem-earth.svg</file>
+ <file alias="geocode">icons/geocode.svg</file>
</qresource>
</RCC>
diff --git a/subsurfacestartup.c b/subsurfacestartup.c
index f5b0e7b4b..3005e7e04 100644
--- a/subsurfacestartup.c
+++ b/subsurfacestartup.c
@@ -74,9 +74,7 @@ struct preferences default_prefs = {
.enable_geocoding = false,
.parse_dive_without_gps = false,
.tag_existing_dives = false,
- .first_item = NULL,
- .second_item = NULL,
- .third_item = NULL
+ .category = { 0 }
}
};
diff --git a/taxonomy.c b/taxonomy.c
new file mode 100644
index 000000000..2c101962a
--- /dev/null
+++ b/taxonomy.c
@@ -0,0 +1,36 @@
+#include "taxonomy.h"
+#include "gettext.h"
+#include <stdlib.h>
+
+char *taxonomy_category_names[NR_CATEGORIES] = {
+ QT_TRANSLATE_NOOP("getTextFromC", "None"),
+ QT_TRANSLATE_NOOP("getTextFromC", "Ocean"),
+ QT_TRANSLATE_NOOP("getTextFromC", "Country"),
+ QT_TRANSLATE_NOOP("getTextFromC", "State"),
+ QT_TRANSLATE_NOOP("getTextFromC", "County"),
+ QT_TRANSLATE_NOOP("getTextFromC", "City")
+};
+
+// these are the names for geoname.org
+char *taxonomy_api_names[NR_CATEGORIES] = {
+ "none",
+ "name",
+ "countryName",
+ "adminName1",
+ "adminName2",
+ "toponymName"
+};
+
+struct taxonomy *alloc_taxonomy()
+{
+ return calloc(NR_CATEGORIES, sizeof(struct taxonomy));
+}
+
+void free_taxonomy(struct taxonomy *t)
+{
+ if (t) {
+ for (int i = 0; i < NR_CATEGORIES; i++)
+ free((void *)t[i].value);
+ free(t);
+ }
+}
diff --git a/taxonomy.h b/taxonomy.h
new file mode 100644
index 000000000..fef6364e2
--- /dev/null
+++ b/taxonomy.h
@@ -0,0 +1,39 @@
+#ifndef TAXONOMY_H
+#define TAXONOMY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum taxonomy_category {
+ NONE,
+ OCEAN,
+ COUNTRY,
+ ADMIN_L1,
+ ADMIN_L2,
+ LOCALNAME,
+ NR_CATEGORIES
+};
+
+extern char *taxonomy_category_names[NR_CATEGORIES];
+extern char *taxonomy_api_names[NR_CATEGORIES];
+
+struct taxonomy {
+ int category; /* the category for this tag: ocean, country, admin_l1, admin_l2, localname, etc */
+ const char *value; /* the value returned, parsed, or manually entered for that category */
+ enum { GEOCODED, PARSED, MANUAL } origin;
+};
+
+/* the data block contains 3 taxonomy structures - unused ones have a tag value of NONE */
+struct taxonomy_data {
+ int nr;
+ struct taxonomy *category;
+};
+
+struct taxonomy *alloc_taxonomy();
+void free_taxonomy(struct taxonomy *t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // TAXONOMY_H