Re: [evolution-patches] Save-calendar plugin. saving to comma separated files
- From: Philip Van Hoof <spamfrommailing freax org>
- To: Rodrigo Moya <rodrigo novell com>
- Cc: Evolution Patches <evolution-patches lists ximian com>, Srinivasa Ragavan <sragavan novell com>, xkahn zoned net, JP Rosevear <jpr novell com>, bounty lists ximian com
- Subject: Re: [evolution-patches] Save-calendar plugin. saving to comma separated files
- Date: Wed, 01 Dec 2004 19:50:53 +0100
On Wed, 2004-12-01 at 19:03 +0100, Rodrigo Moya wrote:
> Apart from that, there are a lot of things to change to match the coding standards,
> mainly putting the { char on the same line as the statement, instead of in its own
> line.
Hi Rodrigo (and the others in CC),
I'll start using a diff-filenameing-sheme to avoid confusion
save-calendar.c.##.diff cvs
[freax lort save-calendar]$ cvs diff -u
> /home/freax/Documents/Programming/Patches/save-calendar.c.01.diff cvs
server: Diffing .
[freax lort save-calendar]$
vim /home/freax/Documents/Programming/Patches/save-calendar.c.01.diff
[freax lort save-calendar]$ pwd
/home/freax/cvs/gnome/evolution/plugins/save-calendar
[freax lort save-calendar]$ date
Wed Dec 1 19:46:22 CET 2004
[freax lort save-calendar]$
This new patch fixes the issues about the coding-style and fixes the
support for the Gtk+2.4 GtkFileSelection. Do note, however, that I
haven't yet tested this (I am not sure on which vbox/widget these extra
widgets should be packed).
--
Philip Van Hoof, Software Developer @ Cronos
home: me at freax dot org
gnome: pvanhoof at gnome dot org
work: philip dot vanhoof at cronos dot be
junk: philip dot vanhoof at gmail dot com
http://www.freax.be, http://www.freax.eu.org
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/plugins/save-calendar/ChangeLog,v
retrieving revision 1.5
diff -u -r1.5 ChangeLog
--- ChangeLog 1 Nov 2004 18:39:17 -0000 1.5
+++ ChangeLog 1 Dec 2004 18:44:59 -0000
@@ -1,3 +1,7 @@
+2004-11-30 Philip Van Hoof <pvanhoof gnome org
+
+ * save-calendar.c: Support for CSV files
+
2004-11-01 JP Rosevear <jpr novell com>
* Makefile.am: dist .eplug.in file
Index: save-calendar.c
===================================================================
RCS file: /cvs/gnome/evolution/plugins/save-calendar/save-calendar.c,v
retrieving revision 1.3
diff -u -r1.3 save-calendar.c
--- save-calendar.c 21 Oct 2004 11:21:42 -0000 1.3
+++ save-calendar.c 1 Dec 2004 18:45:00 -0000
@@ -36,13 +36,37 @@
#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>
+
+enum { /* GtkComboBox enum */
+ DEST_NAME_COLUMN,
+ DEST_HANDLER,
+ 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)
@@ -55,41 +79,361 @@
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 (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type)
+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;
- char *dest_uri;
- ECal *source_client, *dest_client;
- GtkWidget *dialog;
+ 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);
- /* ask the user for destination file */
-#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, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-#else
- dialog = gtk_file_selection_new (_("Select destination file"));
-#endif
+ if (!dest_uri)
+ return;
- if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) {
- gtk_widget_destroy (dialog);
+ /* 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;
}
-#ifdef USE_GTKFILECHOOSER
- 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)));
-#endif
- gtk_widget_destroy (dialog);
+ 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?temp_dt.value:NULL, config);
+ if (&temp_dt) e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_dtend (comp, &temp_dt);
+ line = add_time_to_csv (line, &temp_dt?temp_dt.value:NULL, config);
+ if (&temp_dt) e_cal_component_free_datetime (&temp_dt);
+
+
+ e_cal_component_get_due (comp, &temp_dt);
+ line = add_time_to_csv (line, &temp_dt?temp_dt.value:NULL, config);
+ if (&temp_dt) 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)
+{
+ 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;
@@ -98,7 +442,6 @@
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_free (dest_uri);
g_error_free (error);
return;
}
@@ -114,6 +457,11 @@
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);
@@ -133,17 +481,216 @@
/* terminate */
g_object_unref (source_client);
g_object_unref (dest_client);
+}
+
+
+static void
+on_type_combobox_changed (GtkComboBox *combobox, gpointer data)
+{
+ void (*handler) (EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri, gpointer data);
+ GtkTreeIter iter;
+ GtkWidget *csv_options = data;
+ GtkTreeModel *model = gtk_combo_box_get_model (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);
+ }
+}
+
+/* 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
+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;
+
+ 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));
+ 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);
+
+
+ /* The Type GtkComboBox */
+ gtk_combo_box_set_model (combo, model);
+ 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);
+
+ 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);
+
+#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);
+
+ /* 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;
+ }
+
+ 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));
+#else
+ 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);
+
+ 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));
+
+ data = config;
+ }
+
+ gtk_widget_destroy (dialog);
+
+ handler (ep, target, type, dest_uri, data);
+
+ if (handler == do_save_calendar_csv) {
+ g_free (config->delimiter);
+ g_free (config->quote);
+ g_free (config->newline);
+ g_free (config);
+ }
+
g_free (dest_uri);
}
void
org_gnome_save_calendar (EPlugin *ep, ECalPopupTargetSource *target)
{
- do_save_calendar (ep, target, E_CAL_SOURCE_TYPE_EVENT);
+ ask_destination_and_save (ep, target, E_CAL_SOURCE_TYPE_EVENT);
}
void
org_gnome_save_tasks (EPlugin *ep, ECalPopupTargetSource *target)
{
- do_save_calendar (ep, target, E_CAL_SOURCE_TYPE_TODO);
+ ask_destination_and_save (ep, target, E_CAL_SOURCE_TYPE_TODO);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]