aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/save-calendar/ChangeLog9
-rw-r--r--plugins/save-calendar/Makefile.am4
-rw-r--r--plugins/save-calendar/csv-format.c565
-rw-r--r--plugins/save-calendar/format-handler.h49
-rw-r--r--plugins/save-calendar/ical-format.c127
-rw-r--r--plugins/save-calendar/rdf-format.c384
-rw-r--r--plugins/save-calendar/save-calendar.c686
7 files changed, 1258 insertions, 566 deletions
diff --git a/plugins/save-calendar/ChangeLog b/plugins/save-calendar/ChangeLog
index c4b9052916..31a985e0e1 100644
--- a/plugins/save-calendar/ChangeLog
+++ b/plugins/save-calendar/ChangeLog
@@ -1,3 +1,12 @@
+2004-12-20 Philip Van Hoof <pvanhoof@gnome.org>
+
+ * Makefile.am: Code splitup, each format has it's own c-file
+ * csv-format.c: Added. Code splitup
+ * format-handler.h: Added. Code splitup
+ * ical-format.c: Added. Code splitup
+ * rdf-format.c: Added. Support for RDF files. Code splitup
+ * save-calendar.c: Support for RDF files. Code splitup
+
2004-11-30 Philip Van Hoof <pvanhoof@gnome.org>
* save-calendar.c: Support for CSV files
diff --git a/plugins/save-calendar/Makefile.am b/plugins/save-calendar/Makefile.am
index 5f2e8775b1..1e4efaf812 100644
--- a/plugins/save-calendar/Makefile.am
+++ b/plugins/save-calendar/Makefile.am
@@ -7,7 +7,7 @@ INCLUDES = \
plugin_DATA = org-gnome-save-calendar.eplug
plugin_LTLIBRARIES = liborg-gnome-save-calendar.la
-liborg_gnome_save_calendar_la_SOURCES = save-calendar.c
+liborg_gnome_save_calendar_la_SOURCES = save-calendar.c ical-format.c csv-format.c rdf-format.c
liborg_gnome_save_calendar_la_LDFLAGS = -module -avoid-version
-EXTRA_DIST = org-gnome-save-calendar.eplug.in \ No newline at end of file
+EXTRA_DIST = org-gnome-save-calendar.eplug.in
diff --git a/plugins/save-calendar/csv-format.c b/plugins/save-calendar/csv-format.c
new file mode 100644
index 0000000000..661f75a216
--- /dev/null
+++ b/plugins/save-calendar/csv-format.c
@@ -0,0 +1,565 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Philip Van Hoof <pvanhoof@gnome.org>
+ *
+ * Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <glib.h>
+#include <glib/gi18n.h>
+#ifdef USE_GTKFILECHOOSER
+# include <gtk/gtkfilechooser.h>
+# include <gtk/gtkfilechooserdialog.h>
+#else
+# include <gtk/gtkfilesel.h>
+#endif
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <calendar/gui/e-cal-popup.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <string.h>
+
+#include "format-handler.h"
+
+typedef struct _CsvConfig CsvConfig;
+struct _CsvConfig {
+ gchar *newline;
+ gchar *quote;
+ gchar *delimiter;
+ gboolean header;
+};
+
+static gboolean string_needsquotes (const char *value, CsvConfig *config);
+
+typedef struct _CsvPluginData CsvPluginData;
+struct _CsvPluginData
+{
+ GtkWidget *delimiter_entry, *newline_entry, *quote_entry, *header_check;
+};
+
+static void
+display_error_message (GtkWidget *parent, GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+
+enum { /* CSV helper enum */
+ ECALCOMPONENTTEXT,
+ ECALCOMPONENTATTENDEE,
+ CONSTCHAR
+};
+
+
+
+/* Some helpers for the csv stuff */
+static GString *
+add_list_to_csv (GString *line, GSList *list_in, CsvConfig *config, gint type)
+{
+
+ /*
+ * This one will write 'ECalComponentText' and 'const char' GSLists. It will
+ * put quotes around the complete written value if there's was only one value
+ * but it required having quotes and if there was more than one value (in which
+ * case delimiters are used to separate them, hence the need for the quotes).
+ */
+
+ if (list_in) {
+ gboolean needquotes = FALSE;
+ GSList *list = list_in;
+ GString *tmp = NULL;
+ gint cnt=0;
+ while (list) {
+ const char *str = NULL;
+ if (cnt == 0)
+ tmp = g_string_new ("");
+ if (cnt > 0)
+ needquotes = TRUE;
+ switch (type) {
+ case ECALCOMPONENTATTENDEE:
+ str = ((ECalComponentAttendee*)list->data)->value;
+ break;
+ case ECALCOMPONENTTEXT:
+ str = ((ECalComponentText*)list->data)->value;
+ break;
+ case CONSTCHAR:
+ default:
+ str = list->data;
+ break;
+ }
+ if (!needquotes)
+ needquotes = string_needsquotes (str, config);
+ if (str)
+ tmp = g_string_append (tmp, (const gchar*)str);
+ list = g_slist_next (list); cnt++;
+ if (list)
+ tmp = g_string_append (tmp, config->delimiter);
+ }
+
+ if (needquotes)
+ line = g_string_append (line, config->quote);
+ line = g_string_append_len (line, tmp->str, tmp->len);
+ g_string_free (tmp, TRUE);
+ if (needquotes)
+ line = g_string_append (line, config->quote);
+ }
+
+ line = g_string_append (line, config->delimiter);
+ return line;
+}
+
+static GString *
+add_nummeric_to_csv (GString *line, gint *nummeric, CsvConfig *config)
+{
+
+ /*
+ * This one will write {-1}..{00}..{01}..{99}
+ * it prepends a 0 if it's < 10 and > -1
+ */
+
+ if (nummeric)
+ g_string_append_printf (line, "%s%d", (*nummeric<10 && *nummeric>-1)?"0":"", *nummeric);
+
+ line = g_string_append (line, config->delimiter);
+ return line;
+}
+
+static GString *
+add_time_to_csv (GString *line, icaltimetype *time, CsvConfig *config)
+{
+ /*
+ * Perhaps we should check for quotes, delimiter and newlines in the
+ * resulting string: The translators can put it there!
+ *
+ * Or perhaps we shouldn't make this translatable?
+ * Or perhaps there is a library-function to do this?
+ */
+
+ if (time) {
+ g_string_append_printf (line, _("%s%d/%s%d/%s%d %s%d:%s%d:%s%d"),
+ (time->month < 10)?"0":"", time->month,
+ (time->day < 10)?"0":"", time->day,
+ (time->year < 10)?"0":"", time->year,
+ (time->hour < 10)?"0":"", time->hour,
+ (time->minute < 10)?"0":"", time->minute,
+ (time->second < 10)?"0":"", time->second);
+ }
+
+ line = g_string_append (line, config->delimiter);
+ return line;
+}
+
+static gboolean
+string_needsquotes (const char *value, CsvConfig *config)
+{
+
+ /* This is the actual need for quotes-checker */
+
+ /*
+ * These are the simple substring-checks
+ *
+ * Example: {Mom, can you please do that for me?}
+ * Will be written as {"Mom, can you please do that for me?"}
+ */
+
+ gboolean needquotes = strstr (value, config->delimiter) ? TRUE:FALSE;
+
+ if (!needquotes) {
+ needquotes = strstr (value, config->newline) ? TRUE:FALSE;
+ if (!needquotes)
+ needquotes = strstr (value, config->quote) ? TRUE:FALSE;
+ }
+
+
+ /*
+ * If the special-char is char+onespace (so like {, } {" }, {\n }) and it occurs
+ * the value that is going to be written
+ *
+ * In this case we don't trust the user . . . and are going to quote the string
+ * just to play save -- Quoting is always allowed in the CSV format. If you can
+ * avoid it, it's better to do so since a lot applications don't support CSV
+ * correctly! --.
+ *
+ * Example: {Mom,can you please do that for me?}
+ * This example will be written as {"Mom,can you please do that for me?"} because
+ * there's a {,} behind {Mom} and the delimiter is {, } (so we searched only the
+ * first character of {, } and didn't trust the user).
+ */
+
+
+ if (!needquotes) {
+ gint len = strlen (config->delimiter);
+ if ((len == 2) && (config->delimiter[1] = ' ')) {
+ needquotes = strchr (value, config->delimiter[0])?TRUE:FALSE;
+ if (!needquotes) {
+ gint len = strlen (config->newline);
+ if ((len == 2) && (config->newline[1] = ' ')) {
+ needquotes = strchr (value, config->newline[0])?TRUE:FALSE;
+ if (!needquotes) {
+ gint len = strlen (config->quote);
+ if ((len == 2) && (config->quote[1] = ' ')) {
+ needquotes = strchr
+ (value, config->quote[0])?TRUE:FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return needquotes;
+}
+
+static GString *
+add_string_to_csv (GString *line, const char *value, CsvConfig *config)
+{
+ /* Will add a string to the record and will check for the need for quotes */
+
+ if ((value) && (strlen(value)>0)) {
+ gboolean needquotes = string_needsquotes (value, config);
+
+ if (needquotes)
+ line = g_string_append (line, config->quote);
+ line = g_string_append (line, (const gchar*)value);
+ if (needquotes)
+ line = g_string_append (line, config->quote);
+ }
+ line = g_string_append (line, config->delimiter);
+ return line;
+}
+
+/* Convert what the user types to what he probably means */
+static gchar *
+userstring_to_systemstring (const gchar *userstring)
+{
+ const gchar *text = userstring;
+ gint i=0, len = strlen(text);
+ GString *str = g_string_new ("");
+ gchar *retval = NULL;
+
+ while (i < len) {
+ if (text[i] == '\\') {
+ switch (text[i+1]) {
+ case 'n':
+ str = g_string_append_c (str, '\n');
+ i++;
+ break;
+ case '\\':
+ str = g_string_append_c (str, '\\');
+ i++;
+ break;
+ case 'r':
+ str = g_string_append_c (str, '\r');
+ i++;
+ break;
+ case 't':
+ str = g_string_append_c (str, '\t');
+ i++;
+ break;
+ }
+ } else {
+ str = g_string_append_c (str, text[i]);
+ }
+
+ i++;
+ }
+
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+static void
+do_save_calendar_csv (FormatHandler *handler, EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri)
+{
+
+ /*
+ * According to some documentation about CSV, newlines 'are' allowed
+ * in CSV-files. But you 'do' have to put the value between quotes.
+ * The helper 'string_needsquotes' will check for that
+ *
+ * http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
+ * http://www.creativyst.com/cgi-bin/Prod/15/eg/csv2xml.pl
+ */
+
+ ESource *primary_source;
+ ECal *source_client;
+ GError *error = NULL;
+ GList *objects=NULL;
+ GnomeVFSResult result;
+ GnomeVFSHandle *handle;
+ GnomeVFSURI *uri;
+ GString *line = NULL;
+ CsvConfig *config = NULL;
+ CsvPluginData *d = handler->data;
+ const gchar *tmp = NULL;
+
+ if (!dest_uri)
+ return;
+
+ primary_source = e_source_selector_peek_primary_selection (target->selector);
+
+ /* open source client */
+ source_client = e_cal_new (primary_source, type);
+ if (!e_cal_open (source_client, TRUE, &error)) {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_object_unref (source_client);
+ g_error_free (error);
+ return;
+ }
+
+ config = g_new (CsvConfig, 1);
+
+ tmp = gtk_entry_get_text (GTK_ENTRY(d->delimiter_entry));
+ config->delimiter = userstring_to_systemstring (tmp?tmp:", ");
+ tmp = gtk_entry_get_text (GTK_ENTRY(d->newline_entry));
+ config->newline = userstring_to_systemstring (tmp?tmp:"\\n");
+ tmp = gtk_entry_get_text (GTK_ENTRY(d->quote_entry));
+ config->quote = userstring_to_systemstring (tmp?tmp:"\"");
+ config->header = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (d->header_check));
+
+ uri = gnome_vfs_uri_new (dest_uri);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_create (&handle, dest_uri, GNOME_VFS_OPEN_WRITE, TRUE, GNOME_VFS_PERM_USER_ALL);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ }
+
+ if (result == GNOME_VFS_OK && e_cal_get_object_list_as_comp (source_client, "#t", &objects, NULL)) {
+
+ if (config->header) {
+ line = g_string_new ("");
+ g_string_append_printf (line, _("Uid%sSummary%sDescription List%sCategories List%s"
+ "Comment List%sCompleted%sCreated%sContact List%s"
+ "Start%sEnd%sDue%sPercent Done%sPriority%sUrl%s"
+ "Attendees List%sLocation%sModified%s"),
+ config->delimiter, config->delimiter, config->delimiter, config->delimiter,
+ config->delimiter, config->delimiter, config->delimiter, config->delimiter,
+ config->delimiter, config->delimiter, config->delimiter, config->delimiter,
+ config->delimiter, config->delimiter, config->delimiter, config->delimiter,
+ config->newline);
+
+ gnome_vfs_write (handle, line->str, line->len, NULL);
+ g_string_free (line, TRUE);
+ }
+
+
+ while (objects != NULL) {
+ ECalComponent *comp = objects->data;
+ gchar *delimiter_temp = NULL;
+ const char *temp_constchar;
+ GSList *temp_list;
+ ECalComponentDateTime temp_dt;
+ struct icaltimetype *temp_time;
+ int *temp_int;
+ ECalComponentText temp_comptext;
+
+ line = g_string_new ("");
+
+ /* Getting the stuff */
+ e_cal_component_get_uid (comp, &temp_constchar);
+ line = add_string_to_csv (line, temp_constchar, config);
+
+ e_cal_component_get_summary (comp, &temp_comptext);
+ line = add_string_to_csv (line, &temp_comptext?temp_comptext.value:NULL, config);
+
+ e_cal_component_get_description_list (comp, &temp_list);
+ line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_categories_list (comp, &temp_list);
+ line = add_list_to_csv (line, temp_list, config, CONSTCHAR);
+ if (temp_list)
+ e_cal_component_free_categories_list (temp_list);
+
+ e_cal_component_get_comment_list (comp, &temp_list);
+ line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_completed (comp, &temp_time);
+ line = add_time_to_csv (line, temp_time, config);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_created (comp, &temp_time);
+ line = add_time_to_csv (line, temp_time, config);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_contact_list (comp, &temp_list);
+ line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_dtstart (comp, &temp_dt);
+ line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_dtend (comp, &temp_dt);
+ line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_due (comp, &temp_dt);
+ line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_percent (comp, &temp_int);
+ line = add_nummeric_to_csv (line, temp_int, config);
+
+ e_cal_component_get_priority (comp, &temp_int);
+ line = add_nummeric_to_csv (line, temp_int, config);
+
+ e_cal_component_get_url (comp, &temp_constchar);
+ line = add_string_to_csv (line, temp_constchar, config);
+
+ if (e_cal_component_has_attendees (comp)) {
+ e_cal_component_get_attendee_list (comp, &temp_list);
+ line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTATTENDEE);
+ if (temp_list)
+ e_cal_component_free_attendee_list (temp_list);
+ } else {
+ line = add_list_to_csv (line, NULL, config, ECALCOMPONENTATTENDEE);
+ }
+
+ e_cal_component_get_location (comp, &temp_constchar);
+ line = add_string_to_csv (line, temp_constchar, config);
+
+ e_cal_component_get_last_modified (comp, &temp_time);
+
+ /* Append a newline (record delimiter) */
+ delimiter_temp = config->delimiter;
+ config->delimiter = config->newline;
+
+ line = add_time_to_csv (line, temp_time, config);
+
+ /* And restore for the next record */
+ config->delimiter = delimiter_temp;
+
+ /* Important note!
+ * The documentation is not requiring this!
+ *
+ * if (temp_time) e_cal_component_free_icaltimetype (temp_time);
+ *
+ * Please uncomment and fix documentation if untrue
+ * http://www.gnome.org/projects/evolution/developer-doc/libecal/ECalComponent.html
+ * #e-cal-component-get-last-modified
+ */
+ gnome_vfs_write (handle, line->str, line->len, NULL);
+
+ /* It's written, so we can free it */
+ g_string_free (line, TRUE);
+
+ objects = g_list_next (objects);
+ }
+
+ gnome_vfs_close (handle);
+ }
+
+ g_object_unref (source_client);
+
+ g_free (config->delimiter);
+ g_free (config->quote);
+ g_free (config->newline);
+ g_free (config);
+
+ return;
+}
+
+
+
+
+
+static GtkWidget *
+create_options_widget (FormatHandler *handler)
+{
+ GtkWidget *table = gtk_table_new (4, 2, FALSE), *label = NULL,
+ *csv_options = gtk_expander_new (_("Advanced options for the CSV format")),
+ *vbox = gtk_vbox_new (FALSE, 0);
+ CsvPluginData *d = handler->data;
+
+ d->delimiter_entry = gtk_entry_new ();
+ d->newline_entry = gtk_entry_new ();
+ d->quote_entry = gtk_entry_new ();
+ d->header_check = gtk_check_button_new_with_label (_("Prepend a header"));
+
+ /* Advanced CSV options */
+ gtk_entry_set_text (GTK_ENTRY(d->delimiter_entry), ", ");
+ gtk_entry_set_text (GTK_ENTRY(d->quote_entry), "\"");
+ gtk_entry_set_text (GTK_ENTRY(d->newline_entry), "\\n");
+
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ label = gtk_label_new (_("Value delimiter:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ gtk_table_attach (GTK_TABLE (table), d->delimiter_entry, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ label = gtk_label_new (_("Record delimiter:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ gtk_table_attach (GTK_TABLE (table), d->newline_entry, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ label = gtk_label_new (_("Encapsulate values with:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ gtk_table_attach (GTK_TABLE (table), d->quote_entry, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), d->header_check, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
+ gtk_widget_show_all (vbox);
+
+ gtk_container_add (GTK_CONTAINER (csv_options), vbox);
+
+
+ return csv_options;
+}
+
+FormatHandler *csv_format_handler_new (void)
+{
+ FormatHandler *handler = g_new (FormatHandler, 1);
+
+ handler->isdefault = FALSE;
+ handler->combo_label = _("Comma separated value format (.csv)");
+ handler->filename_ext = ".csv";
+ handler->data = g_new (CsvPluginData, 1);
+ handler->options_widget = create_options_widget (handler);
+ handler->save = do_save_calendar_csv;
+
+ return handler;
+}
diff --git a/plugins/save-calendar/format-handler.h b/plugins/save-calendar/format-handler.h
new file mode 100644
index 0000000000..9ff29a118d
--- /dev/null
+++ b/plugins/save-calendar/format-handler.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Philip Van Hoof <pvanhoof@gnome.org>
+ *
+ * Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <calendar/gui/e-cal-popup.h>
+
+typedef struct _FormatHandler FormatHandler;
+
+struct _FormatHandler
+{
+ gboolean isdefault;
+ const gchar *combo_label;
+ const gchar *filename_ext;
+ GtkWidget *options_widget;
+
+ gpointer data;
+
+ void (*save) (FormatHandler *handler, EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri);
+};
+
+FormatHandler *csv_format_handler_new (void);
+FormatHandler *ical_format_handler_new (void);
+FormatHandler *rdf_format_handler_new (void);
diff --git a/plugins/save-calendar/ical-format.c b/plugins/save-calendar/ical-format.c
new file mode 100644
index 0000000000..680885161c
--- /dev/null
+++ b/plugins/save-calendar/ical-format.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Rodrigo Moya <rodrigo@novell.com>
+ * Philip Van Hoof <pvanhoof@gnome.org>
+ *
+ * Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <glib.h>
+#include <glib/gi18n.h>
+#ifdef USE_GTKFILECHOOSER
+# include <gtk/gtkfilechooser.h>
+# include <gtk/gtkfilechooserdialog.h>
+#else
+# include <gtk/gtkfilesel.h>
+#endif
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <calendar/gui/e-cal-popup.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <string.h>
+
+#include "format-handler.h"
+
+static void
+display_error_message (GtkWidget *parent, GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+static void
+do_save_calendar_ical (FormatHandler *handler, EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri)
+{
+ ESource *primary_source;
+ ECal *source_client, *dest_client;
+ GError *error = NULL;
+
+ primary_source = e_source_selector_peek_primary_selection (target->selector);
+
+ if (!dest_uri)
+ return;
+
+ /* open source client */
+ source_client = e_cal_new (primary_source, type);
+ if (!e_cal_open (source_client, TRUE, &error)) {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_object_unref (source_client);
+ g_error_free (error);
+ return;
+ }
+
+ /* open destination client */
+ error = NULL;
+ dest_client = e_cal_new_from_uri (dest_uri, type);
+ if (e_cal_open (dest_client, FALSE, &error)) {
+ GList *objects;
+
+ if (e_cal_get_object_list (source_client, "#t", &objects, NULL)) {
+ while (objects != NULL) {
+ icalcomponent *icalcomp = objects->data;
+
+ /* FIXME: deal with additions/modifications */
+
+ /* FIXME: This stores a directory with one file in it, the user expects only a file */
+
+ /* FIXME: It would be nice if this ical-handler would use gnome-vfs rather than e_cal_* */
+
+ error = NULL;
+ if (!e_cal_create_object (dest_client, icalcomp, NULL, &error)) {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_error_free (error);
+ }
+
+ /* remove item from the list */
+ objects = g_list_remove (objects, icalcomp);
+ icalcomponent_free (icalcomp);
+ }
+ }
+ } else {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_error_free (error);
+ }
+
+ /* terminate */
+ g_object_unref (source_client);
+ g_object_unref (dest_client);
+}
+
+FormatHandler *ical_format_handler_new (void)
+{
+ FormatHandler *handler = g_new (FormatHandler, 1);
+
+ handler->isdefault = TRUE;
+ handler->combo_label = _("iCalendar format (.ics)");
+ handler->filename_ext = ".ics";
+ handler->options_widget = NULL;
+ handler->save = do_save_calendar_ical;
+ handler->data = NULL;
+
+ return handler;
+}
diff --git a/plugins/save-calendar/rdf-format.c b/plugins/save-calendar/rdf-format.c
new file mode 100644
index 0000000000..efa038a1f2
--- /dev/null
+++ b/plugins/save-calendar/rdf-format.c
@@ -0,0 +1,384 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Philip Van Hoof <pvanhoof@gnome.org>
+ *
+ * Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <glib.h>
+#include <glib/gi18n.h>
+#ifdef USE_GTKFILECHOOSER
+# include <gtk/gtkfilechooser.h>
+# include <gtk/gtkfilechooserdialog.h>
+#else
+# include <gtk/gtkfilesel.h>
+#endif
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <calendar/gui/e-cal-popup.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xpath.h>
+#include <string.h>
+
+#include "format-handler.h"
+
+static void
+add_string_to_rdf (xmlNodePtr node, const gchar *tag, const char *value);
+
+/* Use { */
+
+/* #include <calendar/gui/calendar-config-keys.h> */
+/* #include <calendar/gui/calendar-config.h> */
+
+/* } or { */
+#define CALENDAR_CONFIG_PREFIX "/apps/evolution/calendar"
+#define CALENDAR_CONFIG_TIMEZONE CALENDAR_CONFIG_PREFIX "/display/timezone"
+
+GConfClient *config = NULL;
+
+static gchar *
+calendar_config_get_timezone (void)
+{
+ gchar *retval = NULL;
+
+ if (!config)
+ config = gconf_client_get_default ();
+
+ retval = gconf_client_get_string (config, CALENDAR_CONFIG_TIMEZONE, NULL);
+
+ if (!retval)
+ retval = g_strdup ("UTC");
+
+ return retval;
+}
+/* } */
+
+enum { /* XML helper enum */
+ ECALCOMPONENTTEXT,
+ ECALCOMPONENTATTENDEE,
+ CONSTCHAR
+};
+
+static void
+display_error_message (GtkWidget *parent, GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+/* Some helpers for the xml stuff */
+static void
+add_list_to_rdf (xmlNodePtr node, const gchar *tag, GSList *list_in, gint type)
+{
+ if (list_in) {
+ GSList *list = list_in;
+
+ while (list) {
+ const char *str = NULL;
+
+ switch (type) {
+ case ECALCOMPONENTATTENDEE:
+ str = ((ECalComponentAttendee*)list->data)->value;
+ break;
+ case ECALCOMPONENTTEXT:
+ str = ((ECalComponentText*)list->data)->value;
+ break;
+ case CONSTCHAR:
+ default:
+ str = list->data;
+ break;
+ }
+
+ add_string_to_rdf (node, tag, str);
+
+ list = g_slist_next (list);
+ }
+ }
+}
+
+static void
+add_nummeric_to_rdf (xmlNodePtr node, const gchar *tag, gint *nummeric)
+{
+ if (nummeric) {
+ gchar *value = g_strdup_printf ("%d", *nummeric);
+ xmlNodePtr cur_node = xmlNewChild (node, NULL, tag, value);
+ xmlSetProp (cur_node, "rdf:datatype", "http://www.w3.org/2001/XMLSchema#integer");
+ g_free (value);
+ }
+}
+
+static void
+add_time_to_rdf (xmlNodePtr node, const gchar *tag, icaltimetype *time)
+{
+ if (time) {
+ xmlNodePtr cur_node = NULL;
+ gchar *tmp = NULL;
+ gchar *str = g_strdup_printf ("%s%d-%s%d-%s%dT%s%d:%s%d:%s%d",
+ (time->year < 10)?"0":"", time->year,
+ (time->month < 10)?"0":"", time->month,
+ (time->day < 10)?"0":"", time->day,
+ (time->hour < 10)?"0":"", time->hour,
+ (time->minute < 10)?"0":"", time->minute,
+ (time->second < 10)?"0":"", time->second);
+ cur_node = xmlNewChild (node, NULL, tag, str);
+
+ /* Not sure about this property */
+ tmp = g_strdup_printf ("http://www.w3.org/2002/12/cal/tzd/%s#tz", calendar_config_get_timezone ());
+ xmlSetProp (cur_node, "rdf:datatype", tmp);
+ g_free (tmp);
+
+ g_free (str);
+ }
+}
+
+
+static void
+add_string_to_rdf (xmlNodePtr node, const gchar *tag, const char *value)
+{
+ if (value) {
+ xmlNodePtr cur_node = NULL;
+ cur_node = xmlNewChild (node, NULL, tag, value);
+ xmlSetProp (cur_node, "rdf:datatype", "http://www.w3.org/2001/XMLSchema#string");
+ }
+}
+
+
+
+
+static void
+do_save_calendar_rdf (FormatHandler *handler, EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri)
+{
+
+ /*
+ * According to some documentation about CSV, newlines 'are' allowed
+ * in CSV-files. But you 'do' have to put the value between quotes.
+ * The helper 'string_needsquotes' will check for that
+ *
+ * http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
+ * http://www.creativyst.com/cgi-bin/Prod/15/eg/csv2xml.pl
+ */
+
+ ESource *primary_source;
+ ECal *source_client;
+ GError *error = NULL;
+ GList *objects=NULL;
+ GnomeVFSResult result;
+ GnomeVFSHandle *handle;
+ GnomeVFSURI *uri;
+ gchar *temp = NULL;
+
+ if (!dest_uri)
+ return;
+
+ primary_source = e_source_selector_peek_primary_selection (target->selector);
+
+ /* open source client */
+ source_client = e_cal_new (primary_source, type);
+ if (!e_cal_open (source_client, TRUE, &error)) {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_object_unref (source_client);
+ g_error_free (error);
+ return;
+ }
+
+ uri = gnome_vfs_uri_new (dest_uri);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_create (&handle, dest_uri, GNOME_VFS_OPEN_WRITE, TRUE, GNOME_VFS_PERM_USER_ALL);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ }
+
+ if (result == GNOME_VFS_OK && e_cal_get_object_list_as_comp (source_client, "#t", &objects, NULL)) {
+ xmlBufferPtr buffer=xmlBufferCreate();
+ xmlDocPtr doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlNodePtr fnode = doc->children;
+
+ doc->children = xmlNewDocNode (doc, NULL, "rdf:RDF", NULL);
+ xmlSetProp (doc->children, "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ xmlSetProp (doc->children, "xmlns", "http://www.w3.org/2002/12/cal/ical#");
+
+ fnode = xmlNewChild (doc->children, NULL, "Vcalendar", NULL);
+
+ /* Should Evolution publicise these? */
+ xmlSetProp (fnode, "xmlns:x-wr", "http://www.w3.org/2002/12/cal/prod/Apple_Comp_628d9d8459c556fa#");
+ xmlSetProp (fnode, "xmlns:x-lic", "http://www.w3.org/2002/12/cal/prod/Apple_Comp_628d9d8459c556fa#");
+
+ /* Not sure if it's correct like this */
+ xmlNewChild (fnode, NULL, "prodid", "-//" PACKAGE_STRING "//iCal 1.0//EN");
+
+ /* Assuming GREGORIAN is the only supported calendar scale */
+ xmlNewChild (fnode, NULL, "calscale", "GREGORIAN");
+
+ temp = calendar_config_get_timezone ();
+ xmlNewChild (fnode, NULL, "x-wr:timezone", temp);
+ g_free (temp);
+
+ xmlNewChild (fnode, NULL, "method", "PUBLISH");
+
+ xmlNewChild (fnode, NULL, "x-wr:relcalid", e_source_peek_uid (primary_source));
+
+ xmlNewChild (fnode, NULL, "x-wr:calname", e_source_peek_name (primary_source));
+
+ /* Version of this RDF-format */
+ xmlNewChild (fnode, NULL, "version", "2.0");
+
+ while (objects != NULL) {
+ ECalComponent *comp = objects->data;
+ const char *temp_constchar;
+ gchar *tmp_str = NULL;
+ GSList *temp_list;
+ ECalComponentDateTime temp_dt;
+ struct icaltimetype *temp_time;
+ int *temp_int;
+ ECalComponentText temp_comptext;
+ xmlNodePtr c_node = xmlNewChild (fnode, NULL, "component", NULL);
+ xmlNodePtr node = xmlNewChild (c_node, NULL, "Vevent", NULL);
+
+ /* Getting the stuff */
+ e_cal_component_get_uid (comp, &temp_constchar);
+ tmp_str = g_strdup_printf ("#%s", temp_constchar);
+ xmlSetProp (node, "about", tmp_str);
+ g_free (tmp_str);
+ add_string_to_rdf (node, "uid",temp_constchar);
+
+ e_cal_component_get_summary (comp, &temp_comptext);
+ add_string_to_rdf (node, "summary",&temp_comptext?temp_comptext.value:NULL);
+
+ e_cal_component_get_description_list (comp, &temp_list);
+ add_list_to_rdf (node, "description", temp_list, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_categories_list (comp, &temp_list);
+ add_list_to_rdf (node, "categories", temp_list, CONSTCHAR);
+ if (temp_list)
+ e_cal_component_free_categories_list (temp_list);
+
+ e_cal_component_get_comment_list (comp, &temp_list);
+ add_list_to_rdf (node, "comment", temp_list, ECALCOMPONENTTEXT);
+
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_completed (comp, &temp_time);
+ add_time_to_rdf (node, "completed", temp_time);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_created (comp, &temp_time);
+ add_time_to_rdf (node, "created", temp_time);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_contact_list (comp, &temp_list);
+ add_list_to_rdf (node, "contact", temp_list, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_dtstart (comp, &temp_dt);
+ add_time_to_rdf (node, "dtstart", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_dtend (comp, &temp_dt);
+ add_time_to_rdf (node, "dtend", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_due (comp, &temp_dt);
+ add_time_to_rdf (node, "due", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_percent (comp, &temp_int);
+ add_nummeric_to_rdf (node, "percentComplete", temp_int);
+
+ e_cal_component_get_priority (comp, &temp_int);
+ add_nummeric_to_rdf (node, "priority", temp_int);
+
+ e_cal_component_get_url (comp, &temp_constchar);
+ add_string_to_rdf (node, "URL", temp_constchar);
+
+ if (e_cal_component_has_attendees (comp)) {
+ e_cal_component_get_attendee_list (comp, &temp_list);
+ add_list_to_rdf (node, "attendee", temp_list, ECALCOMPONENTATTENDEE);
+ if (temp_list)
+ e_cal_component_free_attendee_list (temp_list);
+ }
+
+ e_cal_component_get_location (comp, &temp_constchar);
+ add_string_to_rdf (node, "location", temp_constchar);
+
+ e_cal_component_get_last_modified (comp, &temp_time);
+ add_time_to_rdf (node, "lastModified",temp_time);
+
+
+ /* Important note!
+ * The documentation is not requiring this!
+ *
+ * if (temp_time) e_cal_component_free_icaltimetype (temp_time);
+ *
+ * Please uncomment and fix documentation if untrue
+ * http://www.gnome.org/projects/evolution/developer-doc/libecal/ECalComponent.html
+ * #e-cal-component-get-last-modified
+ */
+
+ objects = g_list_next (objects);
+ }
+
+ /* I used a buffer rather than xmlDocDump: I want gnome-vfs support */
+ xmlNodeDump (buffer, doc, doc->children, 2, 1);
+
+ gnome_vfs_write (handle, xmlBufferContent (buffer), xmlBufferLength (buffer), NULL);
+
+ xmlBufferFree (buffer);
+ xmlFreeDoc (doc);
+ gnome_vfs_close (handle);
+ }
+
+ g_object_unref (source_client);
+
+ return;
+}
+
+FormatHandler *rdf_format_handler_new (void)
+{
+ FormatHandler *handler = g_new (FormatHandler, 1);
+
+ handler->isdefault = FALSE;
+ handler->combo_label = _("RDF format (.rdf)");
+ handler->filename_ext = ".rdf";
+ handler->options_widget = NULL;
+ handler->save = do_save_calendar_rdf;
+
+ return handler;
+}
diff --git a/plugins/save-calendar/save-calendar.c b/plugins/save-calendar/save-calendar.c
index 7babaaffbe..d55a7d876f 100644
--- a/plugins/save-calendar/save-calendar.c
+++ b/plugins/save-calendar/save-calendar.c
@@ -44,6 +44,7 @@
#include <libgnomevfs/gnome-vfs.h>
#include <string.h>
+#include "format-handler.h"
enum { /* GtkComboBox enum */
DEST_NAME_COLUMN,
@@ -51,643 +52,200 @@ enum { /* GtkComboBox enum */
N_DEST_COLUMNS
};
-enum { /* CSV helper enum */
- ECALCOMPONENTTEXT,
- ECALCOMPONENTATTENDEE,
- CONSTCHAR
-};
-typedef struct _CsvConfig CsvConfig;
-struct _CsvConfig {
- gchar *newline;
- gchar *quote;
- gchar *delimiter;
- gboolean header;
-};
void org_gnome_save_calendar (EPlugin *ep, ECalPopupTargetSource *target);
void org_gnome_save_tasks (EPlugin *ep, ECalPopupTargetSource *target);
-static gboolean string_needsquotes (const char *value, CsvConfig *config);
-
-static void
-display_error_message (GtkWidget *parent, GError *error)
-{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- error->message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
-
-/* Some helpers for the csv stuff */
-static GString *
-add_list_to_csv (GString *line, GSList *list_in, CsvConfig *config, gint type)
-{
-
- /*
- * This one will write 'ECalComponentText' and 'const char' GSLists. It will
- * put quotes around the complete written value if there's was only one value
- * but it required having quotes and if there was more than one value (in which
- * case delimiters are used to separate them, hence the need for the quotes).
- */
-
- if (list_in) {
- gboolean needquotes = FALSE;
- GSList *list = list_in;
- GString *tmp = NULL;
- gint cnt=0;
- while (list) {
- const char *str = NULL;
- if (cnt == 0)
- tmp = g_string_new ("");
- if (cnt > 0)
- needquotes = TRUE;
- switch (type) {
- case ECALCOMPONENTATTENDEE:
- str = ((ECalComponentAttendee*)list->data)->value;
- break;
- case ECALCOMPONENTTEXT:
- str = ((ECalComponentText*)list->data)->value;
- break;
- case CONSTCHAR:
- default:
- str = list->data;
- break;
- }
- if (!needquotes)
- needquotes = string_needsquotes (str, config);
- if (str)
- tmp = g_string_append (tmp, (const gchar*)str);
- list = g_slist_next (list); cnt++;
- if (list)
- tmp = g_string_append (tmp, config->delimiter);
- }
-
- if (needquotes)
- line = g_string_append (line, config->quote);
- line = g_string_append_len (line, tmp->str, tmp->len);
- g_string_free (tmp, TRUE);
- if (needquotes)
- line = g_string_append (line, config->quote);
- }
-
- line = g_string_append (line, config->delimiter);
- return line;
-}
-
-static GString *
-add_nummeric_to_csv (GString *line, gint *nummeric, CsvConfig *config)
-{
-
- /*
- * This one will write {-1}..{00}..{01}..{99}
- * it prepends a 0 if it's < 10 and > -1
- */
-
- if (nummeric)
- g_string_append_printf (line, "%s%d", (*nummeric<10 && *nummeric>-1)?"0":"", *nummeric);
-
- line = g_string_append (line, config->delimiter);
- return line;
-}
-
-static GString *
-add_time_to_csv (GString *line, icaltimetype *time, CsvConfig *config)
-{
- /*
- * Perhaps we should check for quotes, delimiter and newlines in the
- * resulting string: The translators can put it there!
- *
- * Or perhaps we shouldn't make this translatable?
- * Or perhaps there is a library-function to do this?
- */
-
- if (time) {
- g_string_append_printf (line, _("%s%d/%s%d/%s%d %s%d:%s%d:%s%d"),
- (time->month < 10)?"0":"", time->month,
- (time->day < 10)?"0":"", time->day,
- (time->year < 10)?"0":"", time->year,
- (time->hour < 10)?"0":"", time->hour,
- (time->minute < 10)?"0":"", time->minute,
- (time->second < 10)?"0":"", time->second);
- }
-
- line = g_string_append (line, config->delimiter);
- return line;
-}
-
-static gboolean
-string_needsquotes (const char *value, CsvConfig *config)
-{
-
- /* This is the actual need for quotes-checker */
- /*
- * These are the simple substring-checks
- *
- * Example: {Mom, can you please do that for me?}
- * Will be written as {"Mom, can you please do that for me?"}
- */
- gboolean needquotes = strstr (value, config->delimiter) ? TRUE:FALSE;
-
- if (!needquotes) {
- needquotes = strstr (value, config->newline) ? TRUE:FALSE;
- if (!needquotes)
- needquotes = strstr (value, config->quote) ? TRUE:FALSE;
- }
-
-
- /*
- * If the special-char is char+onespace (so like {, } {" }, {\n }) and it occurs
- * the value that is going to be written
- *
- * In this case we don't trust the user . . . and are going to quote the string
- * just to play save -- Quoting is always allowed in the CSV format. If you can
- * avoid it, it's better to do so since a lot applications don't support CSV
- * correctly! --.
- *
- * Example: {Mom,can you please do that for me?}
- * This example will be written as {"Mom,can you please do that for me?"} because
- * there's a {,} behind {Mom} and the delimiter is {, } (so we searched only the
- * first character of {, } and didn't trust the user).
- */
-
-
- if (!needquotes) {
- gint len = strlen (config->delimiter);
- if ((len == 2) && (config->delimiter[1] = ' ')) {
- needquotes = strchr (value, config->delimiter[0])?TRUE:FALSE;
- if (!needquotes) {
- gint len = strlen (config->newline);
- if ((len == 2) && (config->newline[1] = ' ')) {
- needquotes = strchr (value, config->newline[0])?TRUE:FALSE;
- if (!needquotes) {
- gint len = strlen (config->quote);
- if ((len == 2) && (config->quote[1] = ' ')) {
- needquotes = strchr
- (value, config->quote[0])?TRUE:FALSE;
- }
- }
- }
- }
- }
- }
-
- return needquotes;
-}
-
-static GString *
-add_string_to_csv (GString *line, const char *value, CsvConfig *config)
-{
- /* Will add a string to the record and will check for the need for quotes */
-
- if ((value) && (strlen(value)>0)) {
- gboolean needquotes = string_needsquotes (value, config);
-
- if (needquotes)
- line = g_string_append (line, config->quote);
- line = g_string_append (line, (const gchar*)value);
- if (needquotes)
- line = g_string_append (line, config->quote);
- }
- line = g_string_append (line, config->delimiter);
- return line;
-}
-
-static void
-do_save_calendar_csv (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri, gpointer data)
-{
-
- /*
- * According to some documentation about CSV, newlines 'are' allowed
- * in CSV-files. But you 'do' have to put the value between quotes.
- * The helper 'string_needsquotes' will check for that
- *
- * http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
- * http://www.creativyst.com/cgi-bin/Prod/15/eg/csv2xml.pl
- */
-
- ESource *primary_source;
- ECal *source_client;
- GError *error = NULL;
- GList *objects=NULL;
- GnomeVFSResult result;
- GnomeVFSHandle *handle;
- GnomeVFSURI *uri;
- GString *line = NULL;
- CsvConfig *config = data;
-
- primary_source = e_source_selector_peek_primary_selection (target->selector);
-
- if (!dest_uri)
- return;
-
- /* open source client */
- source_client = e_cal_new (primary_source, type);
- if (!e_cal_open (source_client, TRUE, &error)) {
- display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
- g_object_unref (source_client);
- g_error_free (error);
- return;
- }
-
- uri = gnome_vfs_uri_new (dest_uri);
- result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
- if (result != GNOME_VFS_OK) {
- gnome_vfs_create (&handle, dest_uri, GNOME_VFS_OPEN_WRITE, TRUE, GNOME_VFS_PERM_USER_ALL);
- result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
- }
-
- if (result == GNOME_VFS_OK && e_cal_get_object_list_as_comp (source_client, "#t", &objects, NULL)) {
-
- if (config->header) {
- line = g_string_new ("");
- g_string_append_printf (line, _("Uid%sSummary%sDescription List%sCategories List%s"
- "Comment List%sCompleted%sCreated%sContact List%s"
- "Start%sEnd%sDue%sPercent Done%sPriority%sUrl%s"
- "Attendees List%sLocation%sModified%s"),
- config->delimiter, config->delimiter, config->delimiter, config->delimiter,
- config->delimiter, config->delimiter, config->delimiter, config->delimiter,
- config->delimiter, config->delimiter, config->delimiter, config->delimiter,
- config->delimiter, config->delimiter, config->delimiter, config->delimiter,
- config->newline);
-
- gnome_vfs_write (handle, line->str, line->len, NULL);
- g_string_free (line, TRUE);
- }
-
-
- while (objects != NULL) {
- ECalComponent *comp = objects->data;
- gchar *delimiter_temp = NULL;
- const char *temp_constchar;
- GSList *temp_list;
- ECalComponentDateTime temp_dt;
- struct icaltimetype *temp_time;
- int *temp_int;
- ECalComponentText temp_comptext;
-
- line = g_string_new ("");
-
- /* Getting the stuff */
- e_cal_component_get_uid (comp, &temp_constchar);
- line = add_string_to_csv (line, temp_constchar, config);
-
- e_cal_component_get_summary (comp, &temp_comptext);
- line = add_string_to_csv (line, &temp_comptext?temp_comptext.value:NULL, config);
-
- e_cal_component_get_description_list (comp, &temp_list);
- line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
- if (temp_list)
- e_cal_component_free_text_list (temp_list);
-
- e_cal_component_get_categories_list (comp, &temp_list);
- line = add_list_to_csv (line, temp_list, config, CONSTCHAR);
- if (temp_list)
- e_cal_component_free_categories_list (temp_list);
-
- e_cal_component_get_comment_list (comp, &temp_list);
- line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
- if (temp_list)
- e_cal_component_free_text_list (temp_list);
-
- e_cal_component_get_completed (comp, &temp_time);
- line = add_time_to_csv (line, temp_time, config);
- if (temp_time)
- e_cal_component_free_icaltimetype (temp_time);
-
- e_cal_component_get_created (comp, &temp_time);
- line = add_time_to_csv (line, temp_time, config);
- if (temp_time)
- e_cal_component_free_icaltimetype (temp_time);
-
- e_cal_component_get_contact_list (comp, &temp_list);
- line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTTEXT);
- if (temp_list)
- e_cal_component_free_text_list (temp_list);
-
- e_cal_component_get_dtstart (comp, &temp_dt);
- line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
- if (temp_dt.value)
- e_cal_component_free_datetime (&temp_dt);
-
- e_cal_component_get_dtend (comp, &temp_dt);
- line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
- if (temp_dt.value)
- e_cal_component_free_datetime (&temp_dt);
-
- e_cal_component_get_due (comp, &temp_dt);
- line = add_time_to_csv (line, temp_dt.value ? temp_dt.value : NULL, config);
- if (temp_dt.value)
- e_cal_component_free_datetime (&temp_dt);
-
- e_cal_component_get_percent (comp, &temp_int);
- line = add_nummeric_to_csv (line, temp_int, config);
-
- e_cal_component_get_priority (comp, &temp_int);
- line = add_nummeric_to_csv (line, temp_int, config);
-
- e_cal_component_get_url (comp, &temp_constchar);
- line = add_string_to_csv (line, temp_constchar, config);
-
- if (e_cal_component_has_attendees (comp)) {
- e_cal_component_get_attendee_list (comp, &temp_list);
- line = add_list_to_csv (line, temp_list, config, ECALCOMPONENTATTENDEE);
- if (temp_list)
- e_cal_component_free_attendee_list (temp_list);
- } else {
- line = add_list_to_csv (line, NULL, config, ECALCOMPONENTATTENDEE);
- }
-
- e_cal_component_get_location (comp, &temp_constchar);
- line = add_string_to_csv (line, temp_constchar, config);
-
- e_cal_component_get_last_modified (comp, &temp_time);
-
- /* Append a newline (record delimiter) */
- delimiter_temp = config->delimiter;
- config->delimiter = config->newline;
-
- line = add_time_to_csv (line, temp_time, config);
-
- /* And restore for the next record */
- config->delimiter = delimiter_temp;
-
- /* Important note!
- * The documentation is not requiring this!
- *
- * if (temp_time) e_cal_component_free_icaltimetype (temp_time);
- *
- * Please uncomment and fix documentation if untrue
- * http://www.gnome.org/projects/evolution/developer-doc/libecal/ECalComponent.html
- * #e-cal-component-get-last-modified
- */
- gnome_vfs_write (handle, line->str, line->len, NULL);
-
- /* It's written, so we can free it */
- g_string_free (line, TRUE);
-
- objects = g_list_next (objects);
- }
-
- gnome_vfs_close (handle);
- }
- g_object_unref (source_client);
-}
-
-static void
-do_save_calendar_ical (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri, gpointer data)
+static void
+extra_widget_foreach_hide (GtkWidget *widget, gpointer data)
{
- ESource *primary_source;
- ECal *source_client, *dest_client;
- GError *error = NULL;
-
- primary_source = e_source_selector_peek_primary_selection (target->selector);
-
- if (!dest_uri)
- return;
-
- /* open source client */
- source_client = e_cal_new (primary_source, type);
- if (!e_cal_open (source_client, TRUE, &error)) {
- display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
- g_object_unref (source_client);
- g_error_free (error);
- return;
- }
-
- /* open destination client */
- error = NULL;
- dest_client = e_cal_new_from_uri (dest_uri, type);
- if (e_cal_open (dest_client, FALSE, &error)) {
- GList *objects;
-
- if (e_cal_get_object_list (source_client, "#t", &objects, NULL)) {
- while (objects != NULL) {
- icalcomponent *icalcomp = objects->data;
-
- /* FIXME: deal with additions/modifications */
-
- /* FIXME: This stores a directory with one file in it, the user expects only a file */
-
- /* FIXME: It would be nice if this ical-handler would use gnome-vfs rather than e_cal_* */
-
- error = NULL;
- if (!e_cal_create_object (dest_client, icalcomp, NULL, &error)) {
- display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
- g_error_free (error);
- }
-
- /* remove item from the list */
- objects = g_list_remove (objects, icalcomp);
- icalcomponent_free (icalcomp);
- }
- }
- } else {
- display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
- g_error_free (error);
- }
-
- /* terminate */
- g_object_unref (source_client);
- g_object_unref (dest_client);
+ if (widget != data)
+ gtk_widget_hide (widget);
}
-
static void
on_type_combobox_changed (GtkComboBox *combobox, gpointer data)
{
- void (*handler) (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri, gpointer data);
+ FormatHandler *handler = NULL;
+ GtkWidget *extra_widget = data;
GtkTreeIter iter;
- GtkWidget *csv_options = data;
GtkTreeModel *model = gtk_combo_box_get_model (combobox);
+ gtk_container_foreach (GTK_CONTAINER (extra_widget),
+ extra_widget_foreach_hide, combobox);
+
gtk_combo_box_get_active_iter (combobox, &iter);
gtk_tree_model_get (model, &iter,
DEST_HANDLER, &handler, -1);
- if (handler == do_save_calendar_csv) {
- gtk_widget_show (csv_options);
- } else {
- gtk_widget_hide (csv_options);
- }
+
+ if (handler->options_widget)
+ {
+ gtk_widget_show (handler->options_widget);
+ }
+
}
-/* Convert what the user types to what he probably means */
-static gchar *
-userstring_to_systemstring (const gchar *userstring)
+static void
+format_handlers_foreach_free (gpointer data, gpointer user_data)
{
- const gchar *text = userstring;
- gint i=0, len = strlen(text);
- GString *str = g_string_new ("");
- gchar *retval = NULL;
-
- while (i < len) {
- if (text[i] == '\\') {
- switch (text[i+1]) {
- case 'n':
- str = g_string_append_c (str, '\n');
- i++;
- break;
- case '\\':
- str = g_string_append_c (str, '\\');
- i++;
- break;
- case 'r':
- str = g_string_append_c (str, '\r');
- i++;
- break;
- case 't':
- str = g_string_append_c (str, '\t');
- i++;
- break;
- }
- } else {
- str = g_string_append_c (str, text[i]);
- }
+ FormatHandler *handler = data;
- i++;
- }
+ if (handler->options_widget)
+ gtk_widget_destroy (handler->options_widget);
- retval = str->str;
- g_string_free (str, FALSE);
+ if (handler->data)
+ g_free (handler->data);
- return retval;
+ g_free (data);
}
static void
ask_destination_and_save (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type)
{
- void (*handler) (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri, gpointer data);
- gpointer data = NULL;
- CsvConfig *config = NULL;
+ FormatHandler *handler = NULL;
GtkWidget *extra_widget = gtk_vbox_new (FALSE, 0);
GtkComboBox *combo = GTK_COMBO_BOX(gtk_combo_box_new ());
- GtkTreeModel *model = GTK_TREE_MODEL (gtk_list_store_new (N_DEST_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER));
+ GtkTreeModel *model = GTK_TREE_MODEL (gtk_list_store_new
+ (N_DEST_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER));
GtkCellRenderer *renderer=NULL;
GtkListStore *store = GTK_LIST_STORE (model);
GtkTreeIter iter;
GtkWidget *dialog = NULL;
char *dest_uri = NULL;
- GtkWidget *header_check = gtk_check_button_new_with_label (_("Prepend a header")),
- *delimiter_entry = gtk_entry_new (),
- *newline_entry = gtk_entry_new (),
- *quote_entry = gtk_entry_new (),
- *table = gtk_table_new (4, 2, FALSE), *label = NULL,
- *csv_options = gtk_expander_new (_("Advanced options for the CSV format")),
- *vbox = gtk_vbox_new (FALSE, 0);
+ gboolean proceed = FALSE;
+
+ GList *format_handlers = NULL;
+
+ /* The available formathandlers */
+ format_handlers = g_list_append (format_handlers,
+ ical_format_handler_new ());
+ format_handlers = g_list_append (format_handlers,
+ csv_format_handler_new ());
+ format_handlers = g_list_append (format_handlers,
+ rdf_format_handler_new ());
+
/* The Type GtkComboBox */
+ gtk_box_pack_start (GTK_BOX (extra_widget), GTK_WIDGET (combo),
+ TRUE, TRUE, 0);
gtk_combo_box_set_model (combo, model);
+
+ gtk_list_store_clear (store);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo),
- renderer, "text", DEST_NAME_COLUMN, NULL);
+ renderer, "text", DEST_NAME_COLUMN, NULL);
+
+ while (format_handlers) {
+ FormatHandler *handler = format_handlers->data;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, DEST_NAME_COLUMN,
+ handler->combo_label, -1);
+ gtk_list_store_set (store, &iter, DEST_HANDLER, handler, -1);
+
+ if (handler->options_widget) {
+ gtk_box_pack_start (GTK_BOX (extra_widget),
+ GTK_WIDGET (handler->options_widget), TRUE, TRUE, 0);
+ gtk_widget_hide (handler->options_widget);
+ }
+
+ if (handler->isdefault) {
+ gtk_combo_box_set_active_iter (combo, &iter);
+ if (handler->options_widget)
+ gtk_widget_show (handler->options_widget);
+ }
+
+ format_handlers = g_list_next (format_handlers);
+ }
- gtk_box_pack_start (GTK_BOX (extra_widget), GTK_WIDGET (combo), TRUE, TRUE, 0);
- gtk_list_store_clear (store);
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, DEST_NAME_COLUMN, _("iCalendar format (.ics)"), -1);
- gtk_list_store_set (store, &iter, DEST_HANDLER, do_save_calendar_ical, -1);
- gtk_combo_box_set_active_iter (combo, &iter);
-
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, DEST_NAME_COLUMN, _("Comma separated value format (.csv)"), -1);
- gtk_list_store_set (store, &iter, DEST_HANDLER, do_save_calendar_csv, -1);
-
- /* Advanced CSV options */
- gtk_entry_set_text (GTK_ENTRY(delimiter_entry), ", ");
- gtk_entry_set_text (GTK_ENTRY(quote_entry), "\"");
- gtk_entry_set_text (GTK_ENTRY(newline_entry), "\\n");
-
- gtk_table_set_row_spacings (GTK_TABLE (table), 5);
- gtk_table_set_col_spacings (GTK_TABLE (table), 5);
- label = gtk_label_new (_("Value delimiter:"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
- (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach (GTK_TABLE (table), delimiter_entry, 1, 2, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- label = gtk_label_new (_("Record delimiter:"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
- (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach (GTK_TABLE (table), newline_entry, 1, 2, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- label = gtk_label_new (_("Encapsulate values with:"));
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
- (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach (GTK_TABLE (table), quote_entry, 1, 2, 2, 3,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- gtk_box_pack_start (GTK_BOX (extra_widget), GTK_WIDGET (csv_options), TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), header_check, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
- gtk_container_add (GTK_CONTAINER (csv_options), vbox);
- gtk_widget_show_all (vbox);
-
- g_signal_connect (G_OBJECT(combo), "changed", G_CALLBACK (on_type_combobox_changed), csv_options);
+
+ g_signal_connect (G_OBJECT(combo), "changed",
+ G_CALLBACK (on_type_combobox_changed), extra_widget);
#ifdef USE_GTKFILECHOOSER
+
dialog = gtk_file_chooser_dialog_new (_("Select destination file"),
NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE_AS, GTK_RESPONSE_OK,
NULL);
+
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra_widget);
#else
- /* I haven't tested this yet */
dialog = gtk_file_selection_new (_("Select destination file"));
gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (dialog)->main_vbox), extra_widget);
#endif
- gtk_widget_show_all (extra_widget);
+ gtk_widget_show (GTK_WIDGET(combo));
+ gtk_widget_show (extra_widget);
- /* The default is ical, so hide the new options for now */
- gtk_widget_hide (csv_options);
- if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) {
- gtk_widget_destroy (dialog);
- return;
- }
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ char *tmp = NULL;
- gtk_combo_box_get_active_iter (combo, &iter);
- gtk_tree_model_get (model, &iter, DEST_HANDLER, &handler, -1);
+ gtk_combo_box_get_active_iter (combo, &iter);
+ gtk_tree_model_get (model, &iter,
+ DEST_HANDLER, &handler, -1);
#ifdef USE_GTKFILECHOOSER
- dest_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+ dest_uri = gtk_file_chooser_get_uri
+ (GTK_FILE_CHOOSER (dialog));
#else
- dest_uri = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)));
+ dest_uri = g_strdup (gtk_file_selection_get_filename
+ (GTK_FILE_SELECTION (dialog)));
#endif
- if (handler == do_save_calendar_csv) {
- config = g_new (CsvConfig, 1);
+ tmp = strstr (dest_uri, handler->filename_ext);
- config->delimiter = userstring_to_systemstring (gtk_entry_get_text (GTK_ENTRY(delimiter_entry)));
- config->newline = userstring_to_systemstring (gtk_entry_get_text (GTK_ENTRY(newline_entry)));
- config->quote = userstring_to_systemstring (gtk_entry_get_text (GTK_ENTRY(quote_entry)));
- config->header = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (header_check));
+ if (tmp && *(tmp + strlen (handler->filename_ext)) == '\0') {
- data = config;
- }
+ proceed = TRUE;
- gtk_widget_destroy (dialog);
+ } else {
- handler (ep, target, type, dest_uri, data);
+ GtkWidget *warning =
+ gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ _("The suggested filename extension of this filetype (%s)"
+ " is unused in the chosen filename. Do you want to "
+ "continue?"), handler->filename_ext);
- if (handler == do_save_calendar_csv) {
- g_free (config->delimiter);
- g_free (config->quote);
- g_free (config->newline);
- g_free (config);
- }
+ if (gtk_dialog_run (GTK_DIALOG (warning)) == GTK_RESPONSE_YES)
+ proceed = TRUE;
+
+ gtk_widget_destroy (warning);
+
+ }
- g_free (dest_uri);
+ if (proceed)
+ {
+ handler->save (handler, ep, target, type, dest_uri);
+ /* Free the handlers */
+ g_list_foreach (format_handlers, format_handlers_foreach_free, NULL);
+ g_list_free (format_handlers);
+
+ /* Now we can destroy it */
+ gtk_widget_destroy (dialog);
+ g_free (dest_uri);
+ }
+
+ } else {
+ /* Free the handlers */
+ g_list_foreach (format_handlers, format_handlers_foreach_free, NULL);
+ g_list_free (format_handlers);
+
+ /* Now we can destroy it */
+ gtk_widget_destroy (dialog);
+ g_free (dest_uri);
+ }
}
void