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, " \n"); put_format(b, "\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, "\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, "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, "\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, "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, " ", " \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, " category); + put_format(b, " origin='%d'", t->origin); + show_utf8_blanked(b, t->value, " value='", "'/>\n", 1, anonymize); + } + } + } + put_format(b, "\n"); + } + put_format(b, "\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 @@ 0 - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 16777215 - 50 - - - - - - - true - - - @@ -97,6 +69,117 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 100 + + + + + 16777215 + 16777215 + + + + Selection + + + + + + true + + + Selected dives + + + true + + + + + + + All dives + + + + + + + + + + true + + + Options + + + + false + + + + 10 + 30 + 102 + 27 + + + + + Metric + + + + + Imperial + + + + + + + 10 + 70 + 111 + 20 + + + + Anonymize + + + + + + + @@ -122,6 +205,16 @@ + + + + Subsurface dive sites XML + + + exportGroup + + + @@ -244,115 +337,32 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 100 - - - - - 16777215 - 16777215 - - - - Selection - - - - - - true - - - Selected dives - - - true - - - - - - - All dives - - - - - - - - - - true - - - Options - - - - false - - - - 10 - 30 - 102 - 27 - - - - - Metric - - - - - Imperial - - - - - - - 10 - 70 - 111 - 20 - - - - Anonymize - - - - - + + + + + 0 + 0 + + + + + 0 + 50 + + + + + 16777215 + 50 + + + + + + + true +