No issues found
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 |
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 }