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., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, 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 "nemo-x-content-bar.h"
32 #include <libnemo-private/nemo-program-choosing.h>
33 
34 #define NEMO_X_CONTENT_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NEMO_TYPE_X_CONTENT_BAR, NemoXContentBarPrivate))
35 
36 struct NemoXContentBarPrivate
37 {
38 	GtkWidget *label;
39 	GtkWidget *button;
40 
41 	char *x_content_type;
42 	GMount *mount;
43 };
44 
45 enum {
46 	PROP_0,
47 	PROP_MOUNT,
48 	PROP_X_CONTENT_TYPE,
49 };
50 
51 enum {
52 	CONTENT_BAR_RESPONSE_APP = 1
53 };
54 
G_DEFINE_TYPE(NemoXContentBar,nemo_x_content_bar,GTK_TYPE_INFO_BAR)55 G_DEFINE_TYPE (NemoXContentBar, nemo_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 	NemoXContentBar *bar;
64 
65 	if (response_id != CONTENT_BAR_RESPONSE_APP) {
66 		return;
67 	}
68 
69 	bar = user_data;
70 
71 	if (bar->priv->x_content_type == NULL ||
72 	    bar->priv->mount == NULL)
73 		return;
74 
75  	default_app = g_app_info_get_default_for_type (bar->priv->x_content_type, FALSE);
76 	if (default_app != NULL) {
77 		nemo_launch_application_for_mount (default_app, bar->priv->mount,
78 						       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (bar))));
79 		g_object_unref (default_app);
80 	}
81 }
82 
83 static void
nemo_x_content_bar_set_x_content_type(NemoXContentBar * bar,const char * x_content_type)84 nemo_x_content_bar_set_x_content_type (NemoXContentBar *bar, const char *x_content_type)
85 {
86 	char *message;
87 	char *description;
88 	GAppInfo *default_app;
89 
90 	g_free (bar->priv->x_content_type);
91 	bar->priv->x_content_type = g_strdup (x_content_type);
92 
93 	description = g_content_type_get_description (x_content_type);
94 
95 	/* Customize greeting for well-known x-content types */
96 	if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
97 		message = g_strdup (_("These files are on an Audio CD."));
98 	} else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
99 		message = g_strdup (_("These files are on an Audio DVD."));
100 	} else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
101 		message = g_strdup (_("These files are on a Video DVD."));
102 	} else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
103 		message = g_strdup (_("These files are on a Video CD."));
104 	} else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
105 		message = g_strdup (_("These files are on a Super Video CD."));
106 	} else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
107 		message = g_strdup (_("These files are on a Photo CD."));
108 	} else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
109 		message = g_strdup (_("These files are on a Picture CD."));
110 	} else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
111 		message = g_strdup (_("The media contains digital photos."));
112 	} else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
113 		message = g_strdup (_("These files are on a digital audio player."));
114 	} else if (strcmp (x_content_type, "x-content/software") == 0) {
115 		message = g_strdup (_("The media contains software."));
116 	} else {
117 		/* fallback to generic greeting */
118 		message = g_strdup_printf (_("The media has been detected as \"%s\"."), description);
119 	}
120 
121 
122 	gtk_label_set_text (GTK_LABEL (bar->priv->label), message);
123 	gtk_widget_show (bar->priv->label);
124 
125 	/* TODO: We really need a GtkBrowserBackButton-ish widget here.. until then, we only
126 	 *       show the default application. */
127 
128  	default_app = g_app_info_get_default_for_type (x_content_type, FALSE);
129 	if (default_app != NULL) {
130 		char *button_text;
131 		const char *name;
132 		GIcon *icon;
133 		GtkWidget *image;
134 
135 		icon = g_app_info_get_icon (default_app);
136 		if (icon != NULL) {
137 			image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON);
138 		} else {
139 			image = NULL;
140 		}
141 
142 		name = g_app_info_get_display_name (default_app);
143 		button_text = g_strdup_printf (_("Open %s"), name);
144 
145 		gtk_button_set_image (GTK_BUTTON (bar->priv->button), image);
146 		gtk_button_set_label (GTK_BUTTON (bar->priv->button), button_text);
147 		gtk_widget_show (bar->priv->button);
148 		g_free (button_text);
149 		g_object_unref (default_app);
150 	} else {
151 		gtk_widget_hide (bar->priv->button);
152 	}
153 
154 	g_free (message);
155 	g_free (description);
156 }
157 
158 static void
nemo_x_content_bar_set_mount(NemoXContentBar * bar,GMount * mount)159 nemo_x_content_bar_set_mount (NemoXContentBar *bar, GMount *mount)
160 {
161 	if (bar->priv->mount != NULL) {
162 		g_object_unref (bar->priv->mount);
163 	}
164 	bar->priv->mount = mount != NULL ? g_object_ref (mount) : NULL;
165 }
166 
167 
168 static void
nemo_x_content_bar_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)169 nemo_x_content_bar_set_property (GObject      *object,
170 				     guint         prop_id,
171 				     const GValue *value,
172 				     GParamSpec   *pspec)
173 {
174 	NemoXContentBar *bar;
175 
176 	bar = NEMO_X_CONTENT_BAR (object);
177 
178 	switch (prop_id) {
179 	case PROP_MOUNT:
180 		nemo_x_content_bar_set_mount (bar, G_MOUNT (g_value_get_object (value)));
181 		break;
182 	case PROP_X_CONTENT_TYPE:
183 		nemo_x_content_bar_set_x_content_type (bar, g_value_get_string (value));
184 		break;
185 	default:
186 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187 		break;
188 	}
189 }
190 
191 static void
nemo_x_content_bar_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)192 nemo_x_content_bar_get_property (GObject    *object,
193 				     guint       prop_id,
194 				     GValue     *value,
195 				     GParamSpec *pspec)
196 {
197 	NemoXContentBar *bar = NEMO_X_CONTENT_BAR (object);
198 
199 	switch (prop_id) {
200 	case PROP_MOUNT:
201                 g_value_set_object (value, bar->priv->mount);
202 		break;
203 	case PROP_X_CONTENT_TYPE:
204                 g_value_set_string (value, bar->priv->x_content_type);
205 		break;
206 	default:
207 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
208 		break;
209 	}
210 }
211 
212 static void
nemo_x_content_bar_finalize(GObject * object)213 nemo_x_content_bar_finalize (GObject *object)
214 {
215 	NemoXContentBar *bar = NEMO_X_CONTENT_BAR (object);
216 
217 	g_free (bar->priv->x_content_type);
218 	if (bar->priv->mount != NULL)
219 		g_object_unref (bar->priv->mount);
220 
221         G_OBJECT_CLASS (nemo_x_content_bar_parent_class)->finalize (object);
222 }
223 
224 static void
nemo_x_content_bar_class_init(NemoXContentBarClass * klass)225 nemo_x_content_bar_class_init (NemoXContentBarClass *klass)
226 {
227 	GObjectClass *object_class;
228 
229 	object_class = G_OBJECT_CLASS (klass);
230 	object_class->get_property = nemo_x_content_bar_get_property;
231 	object_class->set_property = nemo_x_content_bar_set_property;
232 	object_class->finalize = nemo_x_content_bar_finalize;
233 
234 	g_type_class_add_private (klass, sizeof (NemoXContentBarPrivate));
235 
236         g_object_class_install_property (object_class,
237 					 PROP_MOUNT,
238 					 g_param_spec_object (
239 						 "mount",
240 						 "The GMount to run programs for",
241 						 "The GMount to run programs for",
242 						 G_TYPE_MOUNT,
243 						 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
244 
245         g_object_class_install_property (object_class,
246 					 PROP_X_CONTENT_TYPE,
247 					 g_param_spec_string (
248 						 "x-content-type",
249 						 "The x-content type for the cluebar",
250 						 "The x-content type for the cluebar",
251 						 NULL,
252 						 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
253 }
254 
255 static void
nemo_x_content_bar_init(NemoXContentBar * bar)256 nemo_x_content_bar_init (NemoXContentBar *bar)
257 {
258 	GtkWidget *content_area;
259 
260 	bar->priv = NEMO_X_CONTENT_BAR_GET_PRIVATE (bar);
261 	content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (bar));
262 
263 	bar->priv->label = gtk_label_new (NULL);
264 	gtk_style_context_add_class (gtk_widget_get_style_context (bar->priv->label),
265 				     "nemo-cluebar-label");
266 	gtk_label_set_ellipsize (GTK_LABEL (bar->priv->label), PANGO_ELLIPSIZE_END);
267 	gtk_container_add (GTK_CONTAINER (content_area), bar->priv->label);
268 
269 	bar->priv->button = gtk_info_bar_add_button (GTK_INFO_BAR (bar),
270 						     "",
271 						     CONTENT_BAR_RESPONSE_APP);
272 
273 	g_signal_connect (bar, "response",
274 			  G_CALLBACK (content_bar_response_cb),
275 			  bar);
276 }
277 
278 GtkWidget *
nemo_x_content_bar_new(GMount * mount,const char * x_content_type)279 nemo_x_content_bar_new (GMount *mount,
280 			    const char *x_content_type)
281 {
282 	return g_object_new (NEMO_TYPE_X_CONTENT_BAR,
283 			     "mount", mount,
284 			     "x-content-type", x_content_type,
285 			     NULL);
286 }
287