summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Miika Turkia <miika.turkia@gmail.com>2013-03-10 10:24:49 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-03-10 09:29:12 -0700
commit42ea5e351014994980fa0704784906b06a501eec (patch)
treeab5bc00c2627400214e5bce90866fa5448c63805
parent7c6ff9f957a1e7bfebb968cdc4bb96e2832ea4d8 (diff)
downloadsubsurface-42ea5e351014994980fa0704784906b06a501eec.tar.gz
.DLD generation for uploading to divelogs.de
This generates a .DLD file of selected dives to be uploaded to divelogs.de. The actual upload functionality along with sensible user interface is still to be implemented. However, the resulting file from this patch is tested to work (as far as I can tell) using upload API of divelogs.de. Signed-off-by: Miika Turkia <miika.turkia@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--dive.h8
-rw-r--r--divelist.c103
-rw-r--r--parse-xml.c2
-rw-r--r--xslt/commonTemplates.xsl26
4 files changed, 138 insertions, 1 deletions
diff --git a/dive.h b/dive.h
index 6eb9a385a..b6738d171 100644
--- a/dive.h
+++ b/dive.h
@@ -9,6 +9,9 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <libxml/tree.h>
+#ifdef XSLT
+#include <libxslt/transform.h>
+#endif
#include "sha1.h"
@@ -545,6 +548,11 @@ extern void show_yearly_stats(void);
extern void update_dive(struct dive *new_dive);
extern void save_dives(const char *filename);
extern void save_dives_logic(const char *filename, gboolean select_only);
+extern void save_dive(FILE *f, struct dive *dive);
+
+#ifdef XSLT
+extern xsltStylesheetPtr get_stylesheet(const char *name);
+#endif
extern timestamp_t utc_mktime(struct tm *tm);
extern void utc_mkdate(timestamp_t, struct tm *tm);
diff --git a/divelist.c b/divelist.c
index f8e9f1682..a426d67c3 100644
--- a/divelist.c
+++ b/divelist.c
@@ -17,6 +17,12 @@
#include <math.h>
#include <glib/gi18n.h>
#include <assert.h>
+#ifdef LIBZIP
+#include <zip.h>
+#endif
+#ifdef XSLT
+#include <libxslt/transform.h>
+#endif
#include "divelist.h"
#include "dive.h"
@@ -1965,6 +1971,94 @@ static void delete_dive_cb(GtkWidget *menuitem, GtkTreePath *path)
mark_divelist_changed(TRUE);
}
+#if defined(LIBZIP) && defined(XSLT)
+static void export_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path)
+{
+ int i;
+ struct dive *dive;
+ FILE *f;
+ char filename[PATH_MAX], *tempfile, *template;
+ size_t streamsize;
+ char *membuf;
+ xmlDoc *doc;
+ xsltStylesheetPtr xslt = NULL;
+ xmlDoc *transformed;
+ struct zip_source *s[dive_table.nr];
+ struct zip *zip;
+
+ /*
+ * Creating a temporary .DLD file to be eventually uploaded to
+ * divelogs.de. I wonder if this could be done in-memory.
+ */
+
+ template = strdup("/tmp/export.DLD-XXXXXX");
+ tempfile = mktemp(template);
+ zip = zip_open(tempfile, ZIP_CREATE, NULL);
+
+ if (!zip)
+ return;
+
+ if (!amount_selected)
+ return;
+
+ /* walk the dive list in chronological order */
+ for (i = 0; i < dive_table.nr; i++) {
+
+ dive = get_dive(i);
+ if (!dive)
+ continue;
+ if (!dive->selected)
+ continue;
+
+ /*
+ * Saving the dive is done into a memory buffer
+ */
+
+ f = open_memstream(&membuf, &streamsize);
+ if (!f)
+ return;
+ save_dive(f, dive);
+ fclose(f);
+
+ /*
+ * Parse the memory buffer into XML document and
+ * transform it to divelogs.de format, finally dumping
+ * the XML into a character buffer.
+ */
+
+ doc = xmlReadMemory(membuf, strlen(membuf), "divelog", NULL, 0);
+ if (!doc)
+ continue;
+
+ xslt = get_stylesheet("divelogs-export.xslt");
+ transformed = xsltApplyStylesheet(xslt, doc, NULL);
+ xsltFreeStylesheet(xslt);
+ xmlDocDumpMemory(transformed, (xmlChar **) &membuf, (int *)&streamsize);
+ xmlFreeDoc(doc);
+ xmlFreeDoc(transformed);
+
+ /*
+ * Save the XML document into a zip file.
+ */
+
+ snprintf(filename, PATH_MAX, "%d.xml", i + 1);
+ if ((s[i]=zip_source_buffer(zip, membuf, streamsize, 0)) == NULL || zip_add(zip, filename, s[i]) == -1)
+ fprintf(stderr, "failed to include dive %d\n", i);
+
+ }
+ zip_close(zip);
+
+ /*
+ * divelogs.de upload functionality should get rid of this
+ * message and use proper dialog to inform user of the success
+ * or failure of the upload
+ */
+
+ fprintf(stderr, "Created .DLD file %s\n", tempfile);
+ free(template);
+}
+#endif
+
static void merge_dive_index(int i, struct dive *a)
{
struct dive *b = get_dive(i+1);
@@ -2034,6 +2128,9 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int
char deleteplurallabel[] = N_("Delete dives");
char deletesinglelabel[] = N_("Delete dive");
char *deletelabel;
+#if defined(LIBZIP) && defined(XSLT)
+ char exportlabel[] = N_("Export dive(s)");
+#endif
GtkTreePath *path, *prevpath, *nextpath;
GtkTreeIter iter, previter, nextiter;
int idx, previdx, nextidx;
@@ -2101,6 +2198,12 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int
g_signal_connect(menuitem, "activate", G_CALLBACK(delete_selected_dives_cb), path);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+#if defined(LIBZIP) && defined(XSLT)
+ menuitem = gtk_menu_item_new_with_label(exportlabel);
+ g_signal_connect(menuitem, "activate", G_CALLBACK(export_selected_dives_cb), path);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+#endif
+
menuitem = gtk_menu_item_new_with_label(editlabel);
g_signal_connect(menuitem, "activate", G_CALLBACK(edit_selected_dives_cb), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
diff --git a/parse-xml.c b/parse-xml.c
index 76c470506..4cdc3d8ab 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -1827,7 +1827,7 @@ static xsltStylesheetPtr try_get_stylesheet(const char *path, int len, const cha
return ret;
}
-static xsltStylesheetPtr get_stylesheet(const char *name)
+xsltStylesheetPtr get_stylesheet(const char *name)
{
const char *path, *next;
diff --git a/xslt/commonTemplates.xsl b/xslt/commonTemplates.xsl
index a9aa44279..cd4ee993e 100644
--- a/xslt/commonTemplates.xsl
+++ b/xslt/commonTemplates.xsl
@@ -98,4 +98,30 @@
</xsl:choose>
</xsl:template>
+ <xsl:template name="time2sec">
+ <xsl:param name="time"/>
+
+ <xsl:value-of select="substring-before($time, ':') * 60 + substring-before(substring-after($time, ':'), ' ')"/>
+ </xsl:template>
+
+ <!-- Calculate sum of all parameters, and strip any unit following the
+ value -->
+ <xsl:template name="sum">
+ <xsl:param name="values"/>
+ <xsl:param name="sum" select="'0'"/>
+
+ <xsl:variable name="value" select="substring-before($values[1], ' ')"/>
+ <xsl:choose>
+ <xsl:when test="count($values) = 1">
+ <xsl:value-of select="format-number($value + $sum, '#.#')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="sum">
+ <xsl:with-param name="values" select="$values[position() &gt; 1]"/>
+ <xsl:with-param name="sum" select="$sum + $value"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
</xsl:stylesheet>