summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--core/dive.h2
-rw-r--r--core/save-xml.c74
-rw-r--r--desktop-widgets/divelogexportdialog.cpp11
-rw-r--r--desktop-widgets/divelogexportdialog.ui284
5 files changed, 230 insertions, 142 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9e9ba1cb..5b803bc9c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
+- Desktop: Add export option for dive sites
- Import: Initial support for importing Mares log software
- Export option for profile data
- Desktop: Splitting of individual dive computers into distinct dives
diff --git a/core/dive.h b/core/dive.h
index 6e4940452..7a6cf4099 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -481,6 +481,8 @@ extern int save_dives_logic(const char *filename, bool select_only, bool anonymi
extern int save_dive(FILE *f, struct dive *dive, bool anonymize);
extern int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt, bool anonymize);
+extern int save_dive_sites_logic(const char *filename, bool select_only, bool anonymize);
+
struct membuffer;
extern void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize);
diff --git a/core/save-xml.c b/core/save-xml.c
index 50a490c80..02cb2bf87 100644
--- a/core/save-xml.c
+++ b/core/save-xml.c
@@ -21,6 +21,7 @@
#include "strndup.h"
#include "git-access.h"
#include "qthelper.h"
+#include "gettext.h"
/*
* We're outputting utf8 in xml.
@@ -590,15 +591,16 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi
put_format(b, " <autogroup state='1' />\n");
put_format(b, "</settings>\n");
- /* save the dive sites - to make the output consistent let's sort the table, first */
- sort_dive_site_table(&dive_site_table);
- purge_empty_dive_sites(&dive_site_table);
+ /* save the dive sites */
put_format(b, "<divesites>\n");
for (i = 0; i < dive_site_table.nr; i++) {
struct dive_site *ds = get_dive_site(i, &dive_site_table);
+ /* Don't export empty dive sites */
+ if (dive_site_is_empty(ds))
+ continue;
/* Only write used dive sites when exporting selected dives */
if (select_only && !is_dive_site_used(ds, true))
- continue;
+ continue;
put_format(b, "<site uuid='%8x'", ds->uuid);
show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize);
@@ -734,7 +736,7 @@ int save_dives_logic(const char *filename, const bool select_only, bool anonymiz
error = fclose(f);
}
if (error)
- report_error("Save failed (%s)", strerror(errno));
+ report_error(translate("gettextFromC", "Failed to save dives to %s (%s)"), filename, strerror(errno));
free_buffer(&buf);
return error;
@@ -798,3 +800,65 @@ int export_dives_xslt(const char *filename, const bool selected, const int units
return res;
}
+
+void save_dive_sites_buffer(struct membuffer *b, const bool select_only, bool anonymize)
+{
+ int i;
+ put_format(b, "<divesites program='subsurface' version='%d'>\n", DATAFORMAT_VERSION);
+
+ /* save the dive sites */
+ for (i = 0; i < dive_site_table.nr; i++) {
+ struct dive_site *ds = get_dive_site(i, &dive_site_table);
+ /* Don't export empty dive sites */
+ if (dive_site_is_empty(ds))
+ continue;
+ /* Only write used dive sites when exporting selected dives */
+ if (select_only && !is_dive_site_used(ds, true))
+ continue;
+
+ put_format(b, "<site uuid='%8x'", ds->uuid);
+ show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize);
+ put_location(b, &ds->location, " gps='", "'");
+ show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize);
+ put_format(b, ">\n");
+ show_utf8_blanked(b, ds->notes, " <notes>", " </notes>\n", 0, anonymize);
+ if (ds->taxonomy.nr) {
+ for (int j = 0; j < ds->taxonomy.nr; j++) {
+ struct taxonomy *t = &ds->taxonomy.category[j];
+ if (t->category != TC_NONE && t->value) {
+ put_format(b, " <geo cat='%d'", t->category);
+ put_format(b, " origin='%d'", t->origin);
+ show_utf8_blanked(b, t->value, " value='", "'/>\n", 1, anonymize);
+ }
+ }
+ }
+ put_format(b, "</site>\n");
+ }
+ put_format(b, "</divesites>\n");
+}
+
+int save_dive_sites_logic(const char *filename, const bool select_only, bool anonymize)
+{
+ struct membuffer buf = { 0 };
+ FILE *f;
+ int error = 0;
+
+ save_dive_sites_buffer(&buf, select_only, anonymize);
+
+ if (same_string(filename, "-")) {
+ f = stdout;
+ } else {
+ try_to_backup(filename);
+ error = -1;
+ f = subsurface_fopen(filename, "w");
+ }
+ if (f) {
+ flush_buffer(&buf, f);
+ error = fclose(f);
+ }
+ if (error)
+ report_error(translate("gettextFromC", "Failed to save divesites to %s (%s)"), filename, strerror(errno));
+
+ free_buffer(&buf);
+ return error;
+}
diff --git a/desktop-widgets/divelogexportdialog.cpp b/desktop-widgets/divelogexportdialog.cpp
index 87f2e5597..4fef543a0 100644
--- a/desktop-widgets/divelogexportdialog.cpp
+++ b/desktop-widgets/divelogexportdialog.cpp
@@ -91,6 +91,8 @@ void DiveLogExportDialog::showExplanation()
ui->description->setText(tr("HTML export of the dive locations, visualized on a world map."));
} else if (ui->exportSubsurfaceXML->isChecked()) {
ui->description->setText(tr("Subsurface native XML format."));
+ } else if (ui->exportSubsurfaceSitesXML->isChecked()) {
+ ui->description->setText(tr("Subsurface dive sites native XML format."));
} else if (ui->exportImageDepths->isChecked()) {
ui->description->setText(tr("Write depths of images to file."));
} else if (ui->exportTeX->isChecked()) {
@@ -166,6 +168,15 @@ void DiveLogExportDialog::on_buttonBox_accepted()
QByteArray bt = QFile::encodeName(filename);
save_dives_logic(bt.data(), ui->exportSelected->isChecked(), ui->anonymize->isChecked());
}
+ } else if (ui->exportSubsurfaceSitesXML->isChecked()) {
+ filename = QFileDialog::getSaveFileName(this, tr("Export Subsurface dive sites XML"), lastDir,
+ tr("Subsurface files") + " (*.xml)");
+ if (!filename.isNull() && !filename.isEmpty()) {
+ if (!filename.contains('.'))
+ filename.append(".xml");
+ QByteArray bt = QFile::encodeName(filename);
+ save_dive_sites_logic(bt.data(), ui->exportSelected->isChecked(), ui->anonymize->isChecked());
+ }
} else if (ui->exportImageDepths->isChecked()) {
filename = QFileDialog::getSaveFileName(this, tr("Save image depths"), lastDir);
if (!filename.isNull() && !filename.isEmpty())
diff --git a/desktop-widgets/divelogexportdialog.ui b/desktop-widgets/divelogexportdialog.ui
index 07b06378b..3b15f348e 100644
--- a/desktop-widgets/divelogexportdialog.ui
+++ b/desktop-widgets/divelogexportdialog.ui
@@ -56,34 +56,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
- <item row="2" column="0" colspan="2">
- <widget class="QLabel" name="description">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>50</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>50</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
<item row="3" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
@@ -97,6 +69,117 @@
</property>
</spacer>
</item>
+ <item row="0" column="1">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="exportSelection">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Selection</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QRadioButton" name="exportSelected">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Selected dives</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="exportAll">
+ <property name="text">
+ <string>All dives</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <widget class="QComboBox" name="CSVUnits_2">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>102</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <item>
+ <property name="text">
+ <string>Metric</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Imperial</string>
+ </property>
+ </item>
+ </widget>
+ <widget class="QCheckBox" name="anonymize">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>70</y>
+ <width>111</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Anonymize</string>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item row="0" column="0">
<widget class="QGroupBox" name="exportFormat">
<property name="title">
@@ -123,6 +206,16 @@
</widget>
</item>
<item>
+ <widget class="QRadioButton" name="exportSubsurfaceSitesXML">
+ <property name="text">
+ <string>Subsurface dive sites XML</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">exportGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
<widget class="QRadioButton" name="exportUDDF">
<property name="maximumSize">
<size>
@@ -244,115 +337,32 @@
</layout>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QWidget" name="widget" native="true">
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QGroupBox" name="exportSelection">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>100</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="title">
- <string>Selection</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QRadioButton" name="exportSelected">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Selected dives</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="exportAll">
- <property name="text">
- <string>All dives</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Options</string>
- </property>
- <widget class="QComboBox" name="CSVUnits_2">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>30</y>
- <width>102</width>
- <height>27</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string>Metric</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Imperial</string>
- </property>
- </item>
- </widget>
- <widget class="QCheckBox" name="anonymize">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>70</y>
- <width>111</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>Anonymize</string>
- </property>
- </widget>
- </widget>
- </item>
- </layout>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="description">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
</layout>