evolution-3.6.4/plugins/save-calendar/save-calendar.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Rodrigo Moya <rodrigo@novell.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 /* This is prototype code only, this may, or may not, use undocumented
 24  * unstable or private internal function calls. */
 25 
 26 #ifdef HAVE_CONFIG_H
 27 #include <config.h>
 28 #endif
 29 
 30 #include <string.h>
 31 #include <glib/gi18n.h>
 32 
 33 #include <libevolution-utils/e-alert-dialog.h>
 34 #include <e-util/e-plugin.h>
 35 
 36 #include <shell/e-shell-sidebar.h>
 37 #include <shell/e-shell-view.h>
 38 #include <shell/e-shell-window.h>
 39 
 40 #include "format-handler.h"
 41 
 42 /* Plugin entry points */
 43 gboolean	calendar_save_as_init		(GtkUIManager *ui_manager,
 44 						 EShellView *shell_view);
 45 gboolean	memo_list_save_as_init		(GtkUIManager *ui_manager,
 46 						 EShellView *shell_view);
 47 gboolean	task_list_save_as_init		(GtkUIManager *ui_manager,
 48 						 EShellView *shell_view);
 49 
 50 gint e_plugin_lib_enable (EPlugin *ep, gint enable);
 51 
 52 gint
 53 e_plugin_lib_enable (EPlugin *ep,
 54                      gint enable)
 55 {
 56 	return 0;
 57 }
 58 
 59 enum {  /* GtkComboBox enum */
 60 	DEST_NAME_COLUMN,
 61 	DEST_HANDLER,
 62 	N_DEST_COLUMNS
 63 
 64 };
 65 
 66 static void
 67 extra_widget_foreach_hide (GtkWidget *widget,
 68                            gpointer data)
 69 {
 70 	if (widget != data)
 71 		gtk_widget_hide (widget);
 72 }
 73 
 74 static void
 75 on_type_combobox_changed (GtkComboBox *combobox,
 76                           gpointer data)
 77 {
 78 	FormatHandler *handler = NULL;
 79 	GtkWidget *extra_widget = data;
 80 	GtkTreeIter iter;
 81 	GtkTreeModel *model = gtk_combo_box_get_model (combobox);
 82 
 83 	gtk_container_foreach (
 84 		GTK_CONTAINER (extra_widget),
 85 		extra_widget_foreach_hide,
 86 		g_object_get_data (G_OBJECT (combobox), "format-box"));
 87 
 88 	gtk_combo_box_get_active_iter (combobox, &iter);
 89 
 90 	gtk_tree_model_get (
 91 		model, &iter,
 92 		DEST_HANDLER, &handler, -1);
 93 
 94 	if (handler->options_widget)
 95 	{
 96 		gtk_widget_show (handler->options_widget);
 97 	}
 98 
 99 }
100 
101 static void
102 format_handlers_foreach_free (gpointer data,
103                               gpointer user_data)
104 {
105 	FormatHandler *handler = data;
106 
107 	if (handler->options_widget)
108 		gtk_widget_destroy (handler->options_widget);
109 
110 	if (handler->data)
111 		g_free (handler->data);
112 
113 	g_free (data);
114 }
115 
116 static void
117 ask_destination_and_save (ESourceSelector *selector,
118                           ECalClientSourceType type)
119 {
120 	FormatHandler *handler = NULL;
121 
122 	GtkWidget *extra_widget = gtk_vbox_new (FALSE, 0);
123 	GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
124 	GtkLabel *label = GTK_LABEL (gtk_label_new_with_mnemonic (_("_Format:")));
125 	GtkComboBox *combo = GTK_COMBO_BOX (gtk_combo_box_new ());
126 	GtkTreeModel *model = GTK_TREE_MODEL (gtk_list_store_new
127 		(N_DEST_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER));
128 	GtkCellRenderer *renderer = NULL;
129 	GtkListStore *store = GTK_LIST_STORE (model);
130 	GtkTreeIter iter;
131 	GtkWidget *dialog = NULL;
132 	gchar *dest_uri = NULL;
133 
134 	GList *format_handlers = NULL;
135 
136 	/* The available formathandlers */
137 	format_handlers = g_list_append (format_handlers,
138 		ical_format_handler_new ());
139 	format_handlers = g_list_append (format_handlers,
140 		csv_format_handler_new ());
141 	format_handlers = g_list_append (format_handlers,
142 		rdf_format_handler_new ());
143 
144 	gtk_box_pack_start (GTK_BOX (extra_widget), GTK_WIDGET (hbox), FALSE, FALSE, 0);
145 	gtk_label_set_mnemonic_widget (label, GTK_WIDGET (combo));
146 
147 	gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (label), FALSE, FALSE, 0);
148 
149 	/* The Type GtkComboBox */
150 	gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (combo), TRUE, TRUE, 0);
151 	gtk_combo_box_set_model (combo, model);
152 
153 	gtk_list_store_clear (store);
154 	renderer = gtk_cell_renderer_text_new ();
155 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
156 	gtk_cell_layout_set_attributes (
157 		GTK_CELL_LAYOUT (combo),
158 		renderer, "text", DEST_NAME_COLUMN, NULL);
159 
160 	while (format_handlers) {
161 		handler = format_handlers->data;
162 		gtk_list_store_append (store, &iter);
163 		gtk_list_store_set (
164 			store, &iter, DEST_NAME_COLUMN,
165 			handler->combo_label, -1);
166 		gtk_list_store_set (store, &iter, DEST_HANDLER, handler, -1);
167 
168 		if (handler->options_widget) {
169 			gtk_box_pack_start (
170 				GTK_BOX (extra_widget),
171 				GTK_WIDGET (handler->options_widget), TRUE, TRUE, 0);
172 			gtk_widget_hide (handler->options_widget);
173 		}
174 
175 		if (handler->isdefault) {
176 			gtk_combo_box_set_active_iter (combo, &iter);
177 			if (handler->options_widget)
178 				gtk_widget_show (handler->options_widget);
179 		}
180 
181 		format_handlers = g_list_next (format_handlers);
182 	}
183 
184 	g_signal_connect (
185 		combo, "changed",
186 		G_CALLBACK (on_type_combobox_changed), extra_widget);
187 	g_object_set_data (G_OBJECT (combo), "format-box", hbox);
188 
189 	dialog = gtk_file_chooser_dialog_new (
190 		_("Select destination file"),
191 		NULL,
192 		GTK_FILE_CHOOSER_ACTION_SAVE,
193 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
194 		GTK_STOCK_SAVE_AS, GTK_RESPONSE_OK,
195 		NULL);
196 
197 	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
198 	gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra_widget);
199 	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
200 	gtk_widget_show (hbox);
201 	gtk_widget_show (GTK_WIDGET (label));
202 	gtk_widget_show (GTK_WIDGET (combo));
203 	gtk_widget_show (extra_widget);
204 
205 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
206 		gchar *tmp = NULL;
207 
208 		gtk_combo_box_get_active_iter (combo, &iter);
209 		gtk_tree_model_get (
210 			model, &iter,
211 			DEST_HANDLER, &handler, -1);
212 
213 	       dest_uri = gtk_file_chooser_get_uri
214 			(GTK_FILE_CHOOSER (dialog));
215 
216 		tmp = strstr (dest_uri, handler->filename_ext);
217 
218 		if (!(tmp && *(tmp + strlen (handler->filename_ext)) == '\0')) {
219 
220 			gchar *temp;
221 			temp = g_strconcat (dest_uri, handler->filename_ext, NULL);
222 			g_free (dest_uri);
223 			dest_uri = temp;
224 		}
225 
226 		handler->save (handler, selector, type, dest_uri);
227 	}
228 
229 	/* Free the handlers */
230 	g_list_foreach (format_handlers, format_handlers_foreach_free, NULL);
231 	g_list_free (format_handlers);
232 
233 	/* Now we can destroy it */
234 	gtk_widget_destroy (dialog);
235 	g_free (dest_uri);
236 
237 }
238 
239 /* Returns output stream for the uri, or NULL on any error.
240  * When done with the stream, just g_output_stream_close and g_object_unref it.
241  * It will ask for overwrite if file already exists.
242 */
243 GOutputStream *
244 open_for_writing (GtkWindow *parent,
245                   const gchar *uri,
246                   GError **error)
247 {
248 	GFile *file;
249 	GFileOutputStream *fostream;
250 	GError *err = NULL;
251 
252 	g_return_val_if_fail (uri != NULL, NULL);
253 
254 	file = g_file_new_for_uri (uri);
255 
256 	g_return_val_if_fail (file != NULL, NULL);
257 
258 	fostream = g_file_create (file, G_FILE_CREATE_NONE, NULL, &err);
259 
260 	if (err && err->code == G_IO_ERROR_EXISTS) {
261 		gint response;
262 		g_clear_error (&err);
263 
264 		response = e_alert_run_dialog_for_args (
265 			parent, E_ALERT_ASK_FILE_EXISTS_OVERWRITE,
266 			uri, NULL);
267 		if (response == GTK_RESPONSE_OK) {
268 			fostream = g_file_replace (
269 				file, NULL, FALSE, G_FILE_CREATE_NONE,
270 				NULL, &err);
271 
272 			if (err && fostream) {
273 				g_object_unref (fostream);
274 				fostream = NULL;
275 			}
276 		} else if (fostream) {
277 			g_object_unref (fostream);
278 			fostream = NULL;
279 		}
280 	}
281 
282 	g_object_unref (file);
283 
284 	if (error && err)
285 		*error = err;
286 	else if (err)
287 		g_error_free (err);
288 
289 	if (fostream)
290 		return G_OUTPUT_STREAM (fostream);
291 
292 	return NULL;
293 }
294 
295 static void
296 save_general (EShellView *shell_view,
297               ECalClientSourceType type)
298 {
299 	EShellSidebar *shell_sidebar;
300 	ESourceSelector *selector = NULL;
301 
302 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
303 	g_object_get (shell_sidebar, "selector", &selector, NULL);
304 	g_return_if_fail (selector != NULL);
305 
306 	ask_destination_and_save (selector, type);
307 
308 	g_object_unref (selector);
309 }
310 
311 static void
312 action_calendar_save_as_cb (GtkAction *action,
313                             EShellView *shell_view)
314 {
315 	save_general (shell_view, E_CAL_CLIENT_SOURCE_TYPE_EVENTS);
316 }
317 
318 static void
319 action_memo_list_save_as_cb (GtkAction *action,
320                              EShellView *shell_view)
321 {
322 	save_general (shell_view, E_CAL_CLIENT_SOURCE_TYPE_MEMOS);
323 }
324 
325 static void
326 action_task_list_save_as_cb (GtkAction *action,
327                              EShellView *shell_view)
328 {
329 	save_general (shell_view, E_CAL_CLIENT_SOURCE_TYPE_TASKS);
330 }
331 
332 gboolean
333 calendar_save_as_init (GtkUIManager *ui_manager,
334                        EShellView *shell_view)
335 {
336 	EShellWindow *shell_window;
337 	GtkActionGroup *action_group;
338 	GtkAction *action;
339 	const gchar *tooltip;
340 	const gchar *stock_id;
341 	const gchar *name;
342 
343 	shell_window = e_shell_view_get_shell_window (shell_view);
344 
345 	name = "calendar-save-as";
346 	tooltip = _("Save the selected calendar to disk");
347 	stock_id = GTK_STOCK_SAVE_AS;
348 	action = gtk_action_new (name, NULL, tooltip, stock_id);
349 
350 	name = "lockdown-save-to-disk";
351 	action_group = e_shell_window_get_action_group (shell_window, name);
352 	gtk_action_group_add_action (action_group, action);
353 
354 	g_signal_connect (
355 		action, "activate",
356 		G_CALLBACK (action_calendar_save_as_cb), shell_view);
357 
358 	g_object_unref (action);
359 
360 	return TRUE;
361 }
362 
363 gboolean
364 memo_list_save_as_init (GtkUIManager *ui_manager,
365                         EShellView *shell_view)
366 {
367 	EShellWindow *shell_window;
368 	GtkActionGroup *action_group;
369 	GtkAction *action;
370 	const gchar *tooltip;
371 	const gchar *stock_id;
372 	const gchar *name;
373 
374 	shell_window = e_shell_view_get_shell_window (shell_view);
375 
376 	name = "memo-list-save-as";
377 	tooltip = _("Save the selected memo list to disk");
378 	stock_id = GTK_STOCK_SAVE_AS;
379 	action = gtk_action_new (name, NULL, tooltip, stock_id);
380 
381 	name = "lockdown-save-to-disk";
382 	action_group = e_shell_window_get_action_group (shell_window, name);
383 	gtk_action_group_add_action (action_group, action);
384 
385 	g_signal_connect (
386 		action, "activate",
387 		G_CALLBACK (action_memo_list_save_as_cb), shell_view);
388 
389 	g_object_unref (action);
390 
391 	return TRUE;
392 }
393 
394 gboolean
395 task_list_save_as_init (GtkUIManager *ui_manager,
396                         EShellView *shell_view)
397 {
398 	EShellWindow *shell_window;
399 	GtkActionGroup *action_group;
400 	GtkAction *action;
401 	const gchar *tooltip;
402 	const gchar *stock_id;
403 	const gchar *name;
404 
405 	shell_window = e_shell_view_get_shell_window (shell_view);
406 
407 	name = "task-list-save-as";
408 	tooltip = _("Save the selected task list to disk");
409 	stock_id = GTK_STOCK_SAVE_AS;
410 	action = gtk_action_new (name, NULL, tooltip, stock_id);
411 
412 	name = "lockdown-save-to-disk";
413 	action_group = e_shell_window_get_action_group (shell_window, name);
414 	gtk_action_group_add_action (action_group, action);
415 
416 	g_signal_connect (
417 		action, "activate",
418 		G_CALLBACK (action_task_list_save_as_cb), shell_view);
419 
420 	g_object_unref (action);
421 
422 	return TRUE;
423 }