nautilus-3.6.3/libnautilus-private/nautilus-mime-application-chooser.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found nautilus-mime-application-chooser.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /*
  4  *  nautilus-mime-application-chooser.c: an mime-application chooser
  5  *
  6  *  Copyright (C) 2004 Novell, Inc.
  7  *  Copyright (C) 2007, 2010 Red Hat, Inc.
  8  *
  9  *  The Gnome Library is free software; you can redistribute it and/or
 10  *  modify it under the terms of the GNU Library General Public License as
 11  *  published by the Free Software Foundation; either version 2 of the
 12  *  License, or (at your option) any later version.
 13  *
 14  *  The Gnome Library is distributed in the hope that it will be useful,
 15  *  but APPLICATIONOUT ANY WARRANTY; applicationout even the implied warranty of
 16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17  *  Library General Public License for more details.
 18  *
 19  *  You should have received a copy of the GNU Library General Public
 20  *  License along application the Gnome Library; see the file COPYING.LIB.  If not,
 21  *  write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 22  *  Boston, MA 02111-1307, USA.
 23  *
 24  *  Authors: Dave Camp <dave@novell.com>
 25  *           Alexander Larsson <alexl@redhat.com>
 26  *           Cosimo Cecchi <ccecchi@redhat.com>
 27  */
 28 
 29 #include <config.h>
 30 #include "nautilus-mime-application-chooser.h"
 31 
 32 #include "nautilus-file.h"
 33 #include "nautilus-signaller.h"
 34 #include <eel/eel-stock-dialogs.h>
 35 
 36 #include <string.h>
 37 #include <glib/gi18n-lib.h>
 38 #include <gdk-pixbuf/gdk-pixbuf.h>
 39 #include <gtk/gtk.h>
 40 #include <gio/gio.h>
 41 
 42 struct _NautilusMimeApplicationChooserDetails {
 43 	GList *files;
 44 
 45 	char *content_type;
 46 
 47 	GtkWidget *label;
 48 	GtkWidget *entry;
 49 	GtkWidget *set_as_default_button;
 50 	GtkWidget *open_with_widget;
 51 	GtkWidget *add_button;
 52 };
 53 
 54 enum {
 55 	PROP_CONTENT_TYPE = 1,
 56 	PROP_FILES,
 57 	NUM_PROPERTIES
 58 };
 59 
 60 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 61 
 62 G_DEFINE_TYPE (NautilusMimeApplicationChooser, nautilus_mime_application_chooser, GTK_TYPE_BOX);
 63 
 64 static void
 65 add_clicked_cb (GtkButton *button,
 66 		gpointer user_data)
 67 {
 68 	NautilusMimeApplicationChooser *chooser = user_data;
 69 	GAppInfo *info;
 70 	gchar *message;
 71 	GError *error = NULL;
 72 
 73 	info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget));
 74 
 75 	if (info == NULL)
 76 		return;
 77 
 78 	g_app_info_set_as_last_used_for_type (info, chooser->details->content_type, &error);
 79 
 80 	if (error != NULL) {
 81 		message = g_strdup_printf (_("Error while adding “%s”: %s"),
 82 					   g_app_info_get_display_name (info), error->message);
 83 		eel_show_error_dialog (_("Could not add application"),
 84 				       message,
 85 				       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (chooser))));
 86 		g_error_free (error);
 87 		g_free (message);
 88 	} else {		
 89 		gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget));
 90 		g_signal_emit_by_name (nautilus_signaller_get_current (), "mime_data_changed");
 91 	}
 92 
 93 	g_object_unref (info);
 94 }
 95 
 96 static void
 97 remove_clicked_cb (GtkMenuItem *item, 
 98 		   gpointer user_data)
 99 {
100 	NautilusMimeApplicationChooser *chooser = user_data;
101 	GError *error;
102 	GAppInfo *info;
103 
104 	info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget));
105 
106 	if (info) {
107 		error = NULL;
108 		if (!g_app_info_remove_supports_type (info,
109 						      chooser->details->content_type,
110 						      &error)) {
111 			eel_show_error_dialog (_("Could not forget association"),
112 					       error->message,
113 					       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (chooser))));
114 			g_error_free (error);
115 			
116 		}
117 
118 		gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget));
119 		g_object_unref (info);
120 	}
121 
122 	g_signal_emit_by_name (nautilus_signaller_get_current (), "mime_data_changed");
123 }
124 
125 static void
126 populate_popup_cb (GtkAppChooserWidget *widget,
127 		   GtkMenu *menu,
128 		   GAppInfo *app,
129 		   gpointer user_data)
130 {
131 	GtkWidget *item;
132 	NautilusMimeApplicationChooser *chooser = user_data;
133 
134 	if (g_app_info_can_remove_supports_type (app)) {
135 		item = gtk_menu_item_new_with_label (_("Forget association"));
136 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
137 		gtk_widget_show (item);
138 		
139 		g_signal_connect (item, "activate",
140 				  G_CALLBACK (remove_clicked_cb), chooser);
141 	}
142 }
143 
144 static void
145 reset_clicked_cb (GtkButton *button,
146                   gpointer   user_data)
147 {
148 	NautilusMimeApplicationChooser *chooser;
149 	
150 	chooser = NAUTILUS_MIME_APPLICATION_CHOOSER (user_data);
151 
152 	g_app_info_reset_type_associations (chooser->details->content_type);
153 	gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget));
154 
155 	g_signal_emit_by_name (nautilus_signaller_get_current (), "mime_data_changed");
156 }
157 
158 static void
159 set_as_default_clicked_cb (GtkButton *button,
160 			   gpointer user_data)
161 {
162 	NautilusMimeApplicationChooser *chooser = user_data;
163 	GAppInfo *info;
164 	GError *error = NULL;
165 	gchar *message = NULL;
166 
167 	info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget));
168 
169 	g_app_info_set_as_default_for_type (info, chooser->details->content_type,
170 					    &error);
171 
172 	if (error != NULL) {
173 		message = g_strdup_printf (_("Error while setting “%s” as default application: %s"),
174 					   g_app_info_get_display_name (info), error->message);
175 		eel_show_error_dialog (_("Could not set as default"),
176 				       message,
177 				       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (chooser))));
178 	}
179 
180 	g_object_unref (info);
181 
182 	gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget));
183 	g_signal_emit_by_name (nautilus_signaller_get_current (), "mime_data_changed");
184 }
185 
186 static gint
187 app_compare (gconstpointer a,
188 	     gconstpointer b)
189 {
190 	return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
191 }
192 
193 static gboolean
194 app_info_can_add (GAppInfo *info,
195 		  const gchar *content_type)
196 {
197 	GList *recommended, *fallback;
198 	gboolean retval = FALSE;
199 
200 	recommended = g_app_info_get_recommended_for_type (content_type);
201 	fallback = g_app_info_get_fallback_for_type (content_type);
202 
203 	if (g_list_find_custom (recommended, info, app_compare)) {
204 		goto out;
205 	}
206 
207 	if (g_list_find_custom (fallback, info, app_compare)) {
208 		goto out;
209 	}
210 
211 	retval = TRUE;
212 
213  out:
214 	g_list_free_full (recommended, g_object_unref);
215 	g_list_free_full (fallback, g_object_unref);
216 
217 	return retval;
218 }
219 
220 static void
221 application_selected_cb (GtkAppChooserWidget *widget,
222 			 GAppInfo *info,
223 			 gpointer user_data)
224 {
225 	NautilusMimeApplicationChooser *chooser = user_data;
226 	GAppInfo *default_app;
227 
228 	default_app = g_app_info_get_default_for_type (chooser->details->content_type, FALSE);
229 	if (default_app != NULL) {
230 		gtk_widget_set_sensitive (chooser->details->set_as_default_button,
231 					  !g_app_info_equal (info, default_app));
232 		g_object_unref (default_app);
233 	}
234 	gtk_widget_set_sensitive (chooser->details->add_button,
235 				  app_info_can_add (info, chooser->details->content_type));
236 }
237 
238 static void
239 nautilus_mime_application_chooser_apply_labels (NautilusMimeApplicationChooser *chooser)
240 {
241 	gchar *label, *extension = NULL, *description = NULL;
242 	gint num_files;
243 	NautilusFile *file;
244 
245 	num_files = g_list_length (chooser->details->files);
246 	file = chooser->details->files->data;
247 
248 	/* here we assume all files are of the same content type */
249 	if (g_content_type_is_unknown (chooser->details->content_type)) {
250 		extension = nautilus_file_get_extension (file);
251 
252 		/* Translators: the %s here is a file extension */
253 		description = g_strdup_printf (_("%s document"), extension);
254 	} else {
255 		description = g_content_type_get_description (chooser->details->content_type);
256 	}
257 
258 	if (num_files > 1) {
259 		/* Translators; %s here is a mime-type description */
260 		label = g_strdup_printf (_("Open all files of type “%s” with"),
261 					 description);
262 	} else {
263 		gchar *display_name;
264 		display_name = nautilus_file_get_display_name (file);
265 
266 		/* Translators: first %s is filename, second %s is mime-type description */
267 		label = g_strdup_printf (_("Select an application to open “%s” and other files of type “%s”"),
268 					 display_name, description);
269 
270 		g_free (display_name);
271 	}
272 
273 	gtk_label_set_markup (GTK_LABEL (chooser->details->label), label);
274 
275 	g_free (label);
276 	g_free (extension);
277 	g_free (description);
278 }
279 
280 static void
281 nautilus_mime_application_chooser_build_ui (NautilusMimeApplicationChooser *chooser)
282 {
283 	GtkWidget *box, *button;
284 	GAppInfo *info;
285 
286 	gtk_container_set_border_width (GTK_CONTAINER (chooser), 8);
287 	gtk_box_set_spacing (GTK_BOX (chooser), 0);
288 	gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE);
289 
290 	chooser->details->label = gtk_label_new ("");
291 	gtk_misc_set_alignment (GTK_MISC (chooser->details->label), 0.0, 0.5);
292 	gtk_label_set_line_wrap (GTK_LABEL (chooser->details->label), TRUE);
293 	gtk_label_set_line_wrap_mode (GTK_LABEL (chooser->details->label),
294 				      PANGO_WRAP_WORD_CHAR);
295 	gtk_box_pack_start (GTK_BOX (chooser), chooser->details->label, 
296 			    FALSE, FALSE, 0);
297 
298 	gtk_widget_show (chooser->details->label);
299 
300 	chooser->details->open_with_widget = gtk_app_chooser_widget_new (chooser->details->content_type);
301 	gtk_app_chooser_widget_set_show_default (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget),
302 						 TRUE);
303 	gtk_app_chooser_widget_set_show_fallback (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget),
304 						  TRUE);
305 	gtk_app_chooser_widget_set_show_other (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget),
306 					       TRUE);
307 	gtk_box_pack_start (GTK_BOX (chooser), chooser->details->open_with_widget,
308 			    TRUE, TRUE, 6);
309 	gtk_widget_show (chooser->details->open_with_widget);
310 
311 	box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
312 	gtk_box_set_spacing (GTK_BOX (box), 6);
313 	gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_END);
314 	gtk_box_pack_start (GTK_BOX (chooser), box, FALSE, FALSE, 6);
315 	gtk_widget_show (box);
316 
317 	button = gtk_button_new_with_label (_("Reset"));
318 	g_signal_connect (button, "clicked", 
319 			  G_CALLBACK (reset_clicked_cb),
320 			  chooser);
321 	gtk_widget_show (button);
322 	gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
323 	gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (box), button, TRUE);
324 
325 	button = gtk_button_new_from_stock (GTK_STOCK_ADD);
326 	g_signal_connect (button, "clicked", 
327 			  G_CALLBACK (add_clicked_cb),
328 			  chooser);
329 	gtk_widget_show (button);
330 	gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
331 	chooser->details->add_button = button;
332 
333 	button = gtk_button_new_with_label (_("Set as default"));
334 	g_signal_connect (button, "clicked",
335 			  G_CALLBACK (set_as_default_clicked_cb),
336 			  chooser);
337 	gtk_widget_show (button);
338 	gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
339 
340 	chooser->details->set_as_default_button = button;
341 
342 	/* initialize sensitivity */
343 	info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget));
344 	if (info != NULL) {
345 		application_selected_cb (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget),
346 					 info, chooser);
347 		g_object_unref (info);
348 	}
349 
350 	g_signal_connect (chooser->details->open_with_widget,
351 			  "application-selected",
352 			  G_CALLBACK (application_selected_cb),
353 			  chooser);
354 	g_signal_connect (chooser->details->open_with_widget,
355 			  "populate-popup",
356 			  G_CALLBACK (populate_popup_cb),
357 			  chooser);
358 }
359 
360 static void
361 nautilus_mime_application_chooser_init (NautilusMimeApplicationChooser *chooser)
362 {
363 	chooser->details = G_TYPE_INSTANCE_GET_PRIVATE (chooser, NAUTILUS_TYPE_MIME_APPLICATION_CHOOSER,
364 							NautilusMimeApplicationChooserDetails);
365 
366 	gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser),
367 					GTK_ORIENTATION_VERTICAL);
368 }
369 
370 static void
371 nautilus_mime_application_chooser_constructed (GObject *object)
372 {
373 	NautilusMimeApplicationChooser *chooser = NAUTILUS_MIME_APPLICATION_CHOOSER (object);
374 
375 	if (G_OBJECT_CLASS (nautilus_mime_application_chooser_parent_class)->constructed != NULL)
376 		G_OBJECT_CLASS (nautilus_mime_application_chooser_parent_class)->constructed (object);
377 
378 	nautilus_mime_application_chooser_build_ui (chooser);
379 	nautilus_mime_application_chooser_apply_labels (chooser);
380 }
381 
382 static void
383 nautilus_mime_application_chooser_finalize (GObject *object)
384 {
385 	NautilusMimeApplicationChooser *chooser;
386 
387 	chooser = NAUTILUS_MIME_APPLICATION_CHOOSER (object);
388 
389 	g_free (chooser->details->content_type);
390 	nautilus_file_list_free (chooser->details->files);
391 
392 	G_OBJECT_CLASS (nautilus_mime_application_chooser_parent_class)->finalize (object);
393 }
394 
395 static void
396 nautilus_mime_application_chooser_get_property (GObject *object,
397 						guint property_id,
398 						GValue *value,
399 						GParamSpec *pspec)
400 {
401 	NautilusMimeApplicationChooser *chooser = NAUTILUS_MIME_APPLICATION_CHOOSER (object);
402 
403 	switch (property_id) {
404 	case PROP_CONTENT_TYPE:
405 		g_value_set_string (value, chooser->details->content_type);
406 		break;
407 	default:
408 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
409 		break;
410 	}
411 }
412 
413 static void
414 nautilus_mime_application_chooser_set_property (GObject *object,
415 						guint property_id,
416 						const GValue *value,
417 						GParamSpec *pspec)
418 {
419 	NautilusMimeApplicationChooser *chooser = NAUTILUS_MIME_APPLICATION_CHOOSER (object);
420 
421 	switch (property_id) {
422 	case PROP_CONTENT_TYPE:
423 		chooser->details->content_type = g_value_dup_string (value);
424 		break;
425 	case PROP_FILES:
426 		chooser->details->files = nautilus_file_list_copy (g_value_get_pointer (value));
427 		break;
428 	default:
429 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
430 		break;
431 	}
432 }
433 
434 static void
435 nautilus_mime_application_chooser_class_init (NautilusMimeApplicationChooserClass *class)
436 {
437 	GObjectClass *gobject_class;
438 
439 	gobject_class = G_OBJECT_CLASS (class);
440 	gobject_class->set_property = nautilus_mime_application_chooser_set_property;
441 	gobject_class->get_property = nautilus_mime_application_chooser_get_property;
442 	gobject_class->finalize = nautilus_mime_application_chooser_finalize;
443 	gobject_class->constructed = nautilus_mime_application_chooser_constructed;
444 
445 	properties[PROP_CONTENT_TYPE] = g_param_spec_string ("content-type",
446 							     "Content type",
447 							     "Content type for this widget",
448 							     NULL,
449 							     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
450 							     G_PARAM_STATIC_STRINGS);
451 	properties[PROP_FILES] = g_param_spec_pointer ("files",
452 						       "Files",
453 						       "Files for this widget",
454 						       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
455 						       G_PARAM_STATIC_STRINGS);
456 
457 	g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
458 
459 	g_type_class_add_private (class, sizeof (NautilusMimeApplicationChooserDetails));
460 }
461 
462 GtkWidget *
463 nautilus_mime_application_chooser_new (GList *files,
464 				       const char *mime_type)
465 {
466 	GtkWidget *chooser;
467 
468 	chooser = g_object_new (NAUTILUS_TYPE_MIME_APPLICATION_CHOOSER,
469 				"files", files,
470 				"content-type", mime_type,
471 				NULL);
472 
473 	return chooser;
474 }