nautilus-3.6.3/src/nautilus-x-content-bar.c

No issues found

  1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2 /*
  3  * Copyright (C) 2008 Red Hat, Inc.
  4  * Copyright (C) 2006 Paolo Borelli <pborelli@katamail.com>
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * This program is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program; if not, write to the Free Software
 18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 19  *
 20  * Authors: David Zeuthen <davidz@redhat.com>
 21  *          Paolo Borelli <pborelli@katamail.com>
 22  *
 23  */
 24 
 25 #include "config.h"
 26 
 27 #include <glib/gi18n.h>
 28 #include <gtk/gtk.h>
 29 #include <string.h>
 30 
 31 #include "nautilus-x-content-bar.h"
 32 #include <libnautilus-private/nautilus-icon-info.h>
 33 #include <libnautilus-private/nautilus-program-choosing.h>
 34 
 35 #define NAUTILUS_X_CONTENT_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_X_CONTENT_BAR, NautilusXContentBarPrivate))
 36 
 37 struct NautilusXContentBarPrivate
 38 {
 39 	GtkWidget *label;
 40 
 41 	char **x_content_types;
 42 	GMount *mount;
 43 };
 44 
 45 enum {
 46 	PROP_0,
 47 	PROP_MOUNT,
 48 	PROP_X_CONTENT_TYPES,
 49 };
 50 
 51 enum {
 52 	CONTENT_BAR_RESPONSE_APP = 1
 53 };
 54 
 55 G_DEFINE_TYPE (NautilusXContentBar, nautilus_x_content_bar, GTK_TYPE_INFO_BAR)
 56 
 57 static void
 58 content_bar_response_cb (GtkInfoBar *infobar,
 59 			 gint response_id,
 60 			 gpointer user_data)
 61 {
 62 	GAppInfo *default_app;
 63 	NautilusXContentBar *bar = user_data;
 64 
 65 	if (response_id < 0) {
 66 		return;
 67 	}
 68 
 69 	if (bar->priv->x_content_types == NULL ||
 70 	    bar->priv->mount == NULL)
 71 		return;
 72 
 73 	/* FIXME */
 74  	default_app = g_app_info_get_default_for_type (bar->priv->x_content_types[response_id], FALSE);
 75 	if (default_app != NULL) {
 76 		nautilus_launch_application_for_mount (default_app, bar->priv->mount,
 77 						       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (bar))));
 78 		g_object_unref (default_app);
 79 	}
 80 }
 81 
 82 static char *
 83 get_message_for_x_content_type (const char *x_content_type)
 84 {
 85 	char *message;
 86 	char *description;
 87 
 88 	description = g_content_type_get_description (x_content_type);
 89 
 90 	/* Customize greeting for well-known x-content types */
 91 	/* translators: these describe the contents of removable media */
 92 	if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
 93 		message = g_strdup (_("Audio CD"));
 94 	} else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
 95 		message = g_strdup (_("Audio DVD"));
 96 	} else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
 97 		message = g_strdup (_("Video DVD"));
 98 	} else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
 99 		message = g_strdup (_("Video CD"));
100 	} else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
101 		message = g_strdup (_("Super Video CD"));
102 	} else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
103 		message = g_strdup (_("Photo CD"));
104 	} else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
105 		message = g_strdup (_("Picture CD"));
106 	} else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
107 		message = g_strdup (_("Contains digital photos"));
108 	} else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
109 		message = g_strdup (_("Contains music"));
110 	} else if (strcmp (x_content_type, "x-content/unix-software") == 0) {
111 		message = g_strdup (_("Contains software"));
112 	} else {
113 		/* fallback to generic greeting */
114 		message = g_strdup_printf (_("Detected as “%s”"), description);
115 	}
116 
117 	g_free (description);
118 
119 	return message;
120 }
121 
122 static char *
123 get_message_for_two_x_content_types (char **x_content_types)
124 {
125 	char *message;
126 
127 	g_assert (x_content_types[0] != NULL);
128 	g_assert (x_content_types[1] != NULL);
129 
130 	/* few combinations make sense */
131 	if (strcmp (x_content_types[0], "x-content/image-dcf") == 0
132 	    || strcmp (x_content_types[1], "x-content/image-dcf") == 0) {
133 
134 		/* translators: these describe the contents of removable media */
135 		if (strcmp (x_content_types[0], "x-content/audio-player") == 0) {
136 			message = g_strdup (_("Contains music and photos"));
137 		} else if (strcmp (x_content_types[1], "x-content/audio-player") == 0) {
138 			message = g_strdup (_("Contains photos and music"));
139 		} else {
140 			message = g_strdup (_("Contains digital photos"));
141 		}
142 	} else {
143 		message = get_message_for_x_content_type (x_content_types[0]);
144 	}
145 
146 	return message;
147 }
148 
149 static void
150 nautilus_x_content_bar_set_x_content_types (NautilusXContentBar *bar, const char **x_content_types)
151 {
152 	char *message = NULL;
153 	guint num_types;
154 	guint n;
155 	GPtrArray *types;
156 	GPtrArray *apps;
157 	GAppInfo *default_app;
158 
159 	g_strfreev (bar->priv->x_content_types);
160 
161 	types = g_ptr_array_new ();
162 	apps = g_ptr_array_new ();
163 	g_ptr_array_set_free_func (apps, g_object_unref);
164 	for (n = 0; x_content_types[n] != NULL; n++) {
165 		if (g_str_has_prefix (x_content_types[n], "x-content/blank-"))
166 			continue;
167 
168 		if (g_content_type_is_a (x_content_types[n], "x-content/win32-software"))
169 			continue;
170 
171 		default_app = g_app_info_get_default_for_type (x_content_types[n], FALSE);
172 		if (default_app == NULL)
173 			continue;
174 
175 		g_ptr_array_add (types, g_strdup (x_content_types[n]));
176 		g_ptr_array_add (apps, default_app);
177 	}
178 
179 	num_types = types->len;
180 	g_ptr_array_add (types, NULL);
181 
182 	bar->priv->x_content_types = (char **) g_ptr_array_free (types, FALSE);
183 
184 	switch (num_types) {
185 	case 0:
186 		message = NULL;
187 		break;
188 	case 1:
189 		message = get_message_for_x_content_type (bar->priv->x_content_types[0]);
190 		break;
191 	case 2:
192 		message = get_message_for_two_x_content_types (bar->priv->x_content_types);
193 		break;
194 	default:
195 		message = g_strdup (_("Open with:"));
196 		break;
197 	}
198 
199 	if (message == NULL) {
200 		g_ptr_array_free (apps, TRUE);
201 		gtk_widget_destroy (GTK_WIDGET (bar));
202 		return;
203 	}
204 
205 	gtk_label_set_text (GTK_LABEL (bar->priv->label), message);
206 	g_free (message);
207 
208 	gtk_widget_show (bar->priv->label);
209 
210 	for (n = 0; bar->priv->x_content_types[n] != NULL; n++) {
211 		const char *name;
212 		GIcon *icon;
213 		GtkWidget *image;
214 		GtkWidget *button;
215 
216 		/* TODO: We really need a GtkBrowserBackButton-ish widget here.. until then, we only
217 		 *       show the default application. */
218 
219 		default_app = g_ptr_array_index (apps, n);
220 		icon = g_app_info_get_icon (default_app);
221 		if (icon != NULL) {
222 			image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON);
223 		} else {
224 			image = NULL;
225 		}
226 
227 		name = g_app_info_get_name (default_app);
228 		button = gtk_info_bar_add_button (GTK_INFO_BAR (bar),
229 						  name,
230 						  n);
231 
232 		gtk_button_set_image (GTK_BUTTON (button), image);
233 		gtk_button_set_always_show_image (GTK_BUTTON (button), TRUE);
234 		gtk_button_set_label (GTK_BUTTON (button), name);
235 		gtk_widget_show (button);
236 	}
237 
238 	g_ptr_array_free (apps, TRUE);
239 }
240 
241 static void
242 nautilus_x_content_bar_set_mount (NautilusXContentBar *bar, GMount *mount)
243 {
244 	if (bar->priv->mount != NULL) {
245 		g_object_unref (bar->priv->mount);
246 	}
247 	bar->priv->mount = mount != NULL ? g_object_ref (mount) : NULL;
248 }
249 
250 
251 static void
252 nautilus_x_content_bar_set_property (GObject      *object,
253 				     guint         prop_id,
254 				     const GValue *value,
255 				     GParamSpec   *pspec)
256 {
257 	NautilusXContentBar *bar;
258 
259 	bar = NAUTILUS_X_CONTENT_BAR (object);
260 
261 	switch (prop_id) {
262 	case PROP_MOUNT:
263 		nautilus_x_content_bar_set_mount (bar, G_MOUNT (g_value_get_object (value)));
264 		break;
265 	case PROP_X_CONTENT_TYPES:
266 		nautilus_x_content_bar_set_x_content_types (bar, g_value_get_boxed (value));
267 		break;
268 	default:
269 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270 		break;
271 	}
272 }
273 
274 static void
275 nautilus_x_content_bar_get_property (GObject    *object,
276 				     guint       prop_id,
277 				     GValue     *value,
278 				     GParamSpec *pspec)
279 {
280 	NautilusXContentBar *bar;
281 
282 	bar = NAUTILUS_X_CONTENT_BAR (object);
283 
284 	switch (prop_id) {
285 	case PROP_MOUNT:
286                 g_value_set_object (value, bar->priv->mount);
287 		break;
288 	case PROP_X_CONTENT_TYPES:
289 		g_value_set_boxed (value, &bar->priv->x_content_types);
290 		break;
291 	default:
292 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
293 		break;
294 	}
295 }
296 
297 static void
298 nautilus_x_content_bar_finalize (GObject *object)
299 {
300 	NautilusXContentBar *bar = NAUTILUS_X_CONTENT_BAR (object);
301 
302 	g_strfreev (bar->priv->x_content_types);
303 	if (bar->priv->mount != NULL)
304 		g_object_unref (bar->priv->mount);
305 
306         G_OBJECT_CLASS (nautilus_x_content_bar_parent_class)->finalize (object);
307 }
308 
309 static void
310 nautilus_x_content_bar_class_init (NautilusXContentBarClass *klass)
311 {
312 	GObjectClass *object_class;
313 
314 	object_class = G_OBJECT_CLASS (klass);
315 	object_class->get_property = nautilus_x_content_bar_get_property;
316 	object_class->set_property = nautilus_x_content_bar_set_property;
317 	object_class->finalize = nautilus_x_content_bar_finalize;
318 
319 	g_type_class_add_private (klass, sizeof (NautilusXContentBarPrivate));
320 
321         g_object_class_install_property (object_class,
322 					 PROP_MOUNT,
323 					 g_param_spec_object (
324 						 "mount",
325 						 "The GMount to run programs for",
326 						 "The GMount to run programs for",
327 						 G_TYPE_MOUNT,
328 						 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
329 
330         g_object_class_install_property (object_class,
331 					 PROP_X_CONTENT_TYPES,
332 					 g_param_spec_boxed ("x-content-types",
333 							     "The x-content types for the cluebar",
334 							     "The x-content types for the cluebar",
335 							     G_TYPE_STRV,
336 							     G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
337 }
338 
339 static void
340 nautilus_x_content_bar_init (NautilusXContentBar *bar)
341 {
342 	GtkWidget *content_area;
343 	GtkWidget *action_area;
344 	PangoAttrList *attrs;
345 
346 	bar->priv = NAUTILUS_X_CONTENT_BAR_GET_PRIVATE (bar);
347 	content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (bar));
348 	action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (bar));
349 
350 	gtk_orientable_set_orientation (GTK_ORIENTABLE (action_area), GTK_ORIENTATION_HORIZONTAL);
351 
352 	attrs = pango_attr_list_new ();
353 	pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
354 	bar->priv->label = gtk_label_new (NULL);
355 	gtk_label_set_attributes (GTK_LABEL (bar->priv->label), attrs);
356 	pango_attr_list_unref (attrs);
357 
358 	gtk_label_set_ellipsize (GTK_LABEL (bar->priv->label), PANGO_ELLIPSIZE_END);
359 	gtk_container_add (GTK_CONTAINER (content_area), bar->priv->label);
360 
361 	g_signal_connect (bar, "response",
362 			  G_CALLBACK (content_bar_response_cb),
363 			  bar);
364 }
365 
366 GtkWidget *
367 nautilus_x_content_bar_new (GMount *mount,
368 			    const char **x_content_types)
369 {
370 	return g_object_new (NAUTILUS_TYPE_X_CONTENT_BAR,
371 			     "message-type", GTK_MESSAGE_QUESTION,
372 			     "mount", mount,
373 			     "x-content-types", x_content_types,
374 			     NULL);
375 }