1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Libbrasero-media
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  * Libbrasero-media 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  * The Libbrasero-media authors hereby grant permission for non-GPL compatible
12  * GStreamer plugins to be used and distributed together with GStreamer
13  * and Libbrasero-media. This permission is above and beyond the permissions granted
14  * by the GPL license by which Libbrasero-media is covered. If you modify this code
15  * you may extend this exception to your version of the code, but you are not
16  * obligated to do so. If you do not wish to do so, delete this exception
17  * statement from your version.
18  *
19  * Libbrasero-media is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to:
26  * 	The Free Software Foundation, Inc.,
27  * 	51 Franklin Street, Fifth Floor
28  * 	Boston, MA  02110-1301, USA.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #  include <config.h>
33 #endif
34 
35 #include <glib.h>
36 #include <glib-object.h>
37 #include <glib/gi18n-lib.h>
38 
39 #include <gtk/gtk.h>
40 
41 #include "brasero-medium-selection.h"
42 #include "brasero-medium-selection-priv.h"
43 #include "brasero-medium.h"
44 #include "brasero-volume.h"
45 #include "brasero-medium-monitor.h"
46 #include "brasero-units.h"
47 
48 typedef struct _BraseroMediumSelectionPrivate BraseroMediumSelectionPrivate;
49 struct _BraseroMediumSelectionPrivate
50 {
51 	BraseroMedium *active;
52 
53 	BraseroMediaType type;
54 	gulong added_sig;
55 	gulong removed_sig;
56 };
57 
58 #define BRASERO_MEDIUM_SELECTION_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM_SELECTION, BraseroMediumSelectionPrivate))
59 
60 typedef enum {
61 	CHANGED_SIGNAL,
62 	LAST_SIGNAL
63 } BraseroMediumSelectionSignalType;
64 
65 static guint brasero_medium_selection_signals [LAST_SIGNAL] = { 0 };
66 
67 enum {
68 	PROP_0,
69 	PROP_MEDIUM,
70 	PROP_MEDIA_TYPE
71 };
72 
73 enum {
74 	MEDIUM_COL,
75 	NAME_COL,
76 	ICON_COL,
77 	USED_COL,
78 	VISIBLE_PROGRESS_COL,
79 	VISIBLE_TEXT_COL,
80 	NUM_COL
81 };
82 
83 /* GtkBuildable */
84 static GtkBuildableIface *parent_buildable_iface;
85 
86 static void
brasero_medium_selection_buildable_init(GtkBuildableIface * iface)87 brasero_medium_selection_buildable_init (GtkBuildableIface *iface)
88 {
89 	parent_buildable_iface = g_type_interface_peek_parent (iface);
90 }
91 
92 G_DEFINE_TYPE_WITH_CODE (BraseroMediumSelection,
93                          brasero_medium_selection,
94                          GTK_TYPE_COMBO_BOX,
95                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, brasero_medium_selection_buildable_init));
96 
97 void
brasero_medium_selection_foreach(BraseroMediumSelection * selection,BraseroMediumSelectionFunc function,gpointer callback_data)98 brasero_medium_selection_foreach (BraseroMediumSelection *selection,
99 				  BraseroMediumSelectionFunc function,
100 				  gpointer callback_data)
101 {
102 	GtkTreeModel *model;
103 	GtkTreeIter iter;
104 
105 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (selection));
106 
107 	if (!gtk_tree_model_get_iter_first (model, &iter))
108 		return;
109 
110 	do {
111 		BraseroMedium *medium;
112 
113 		medium = NULL;
114 		gtk_tree_model_get (model, &iter,
115 				    MEDIUM_COL, &medium,
116 				    -1);
117 
118 		/* The following can happen when there isn't any medium */
119 		if (!medium)
120 			return;
121 
122 		if (!function (medium, callback_data)) {
123 			g_object_unref (medium);
124 			break;
125 		}
126 
127 		g_object_unref (medium);
128 	} while (gtk_tree_model_iter_next (model, &iter));
129 }
130 
131 static gchar *
brasero_medium_selection_get_medium_string(BraseroMediumSelection * self,BraseroMedium * medium)132 brasero_medium_selection_get_medium_string (BraseroMediumSelection *self,
133 					    BraseroMedium *medium)
134 {
135 	gchar *label;
136 	gint64 size = 0;
137 	gchar *size_string;
138 	gchar *medium_name;
139 	BraseroMedia media;
140 	BraseroMediumSelectionClass *klass;
141 
142 	klass = BRASERO_MEDIUM_SELECTION_GET_CLASS (self);
143 	if (klass->format_medium_string) {
144 		gchar *label;
145 
146 		label = klass->format_medium_string (self, medium);
147 		if (label)
148 			return label;
149 	}
150 
151 	medium_name = brasero_volume_get_name (BRASERO_VOLUME (medium));
152 	if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_FILE)
153 		return medium_name;
154 
155 	media = brasero_medium_get_status (medium);
156 	if (media & BRASERO_MEDIUM_BLANK) {
157 		/* NOTE for translators, the first %s is the medium name */
158 		label = g_strdup_printf (_("%s: empty"), medium_name);
159 		g_free (medium_name);
160 
161 		return label;
162 	}
163 
164 	brasero_medium_get_data_size (medium,
165 				      &size,
166 				      NULL);
167 
168 	/* format the size */
169 	if (media & BRASERO_MEDIUM_HAS_DATA) {
170 		size_string = g_format_size (size);
171 		/* NOTE for translators: the first %s is the medium name, the
172 		 * second %s is the space (kio, gio) used by data on the disc.
173 		 */
174 		label = g_strdup_printf (_("%s: %s"),
175 					 medium_name,
176 					 size_string);
177 	}
178 	else {
179 		size_string = brasero_units_get_time_string_from_size (size,
180 								       TRUE,
181 								       TRUE);
182 		/* NOTE for translators: the first %s is the medium name, the
183 		 * second %s is the space (time) used by data on the disc.
184 		 * I really don't know if I should set this string as
185 		 * translatable. */
186 		label = g_strdup_printf (_("%s: %s"),
187 					 medium_name,
188 					 size_string);
189 	}
190 
191 	g_free (medium_name);
192 	g_free (size_string);
193 
194 	return label;
195 }
196 
197 void
brasero_medium_selection_update_used_space(BraseroMediumSelection * selector,BraseroMedium * medium_arg,guint used_space)198 brasero_medium_selection_update_used_space (BraseroMediumSelection *selector,
199 					    BraseroMedium *medium_arg,
200 					    guint used_space)
201 {
202 	GtkTreeModel *model;
203 	GtkTreeIter iter;
204 
205 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
206 	if (!gtk_tree_model_get_iter_first (model, &iter))
207 		return;
208 
209 	do {
210 		BraseroMedium *medium;
211 
212 		medium = NULL;
213 		gtk_tree_model_get (model, &iter,
214 				    MEDIUM_COL, &medium,
215 				    -1);
216 
217 		if (medium == medium_arg) {
218 			g_object_unref (medium);
219 
220 			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
221 					    USED_COL, used_space,
222 					    VISIBLE_PROGRESS_COL, (gboolean) (used_space > 0),
223 					    VISIBLE_TEXT_COL, (gboolean) (used_space <= 0),
224 					    -1);
225 			break;
226 		}
227 
228 		g_object_unref (medium);
229 	} while (gtk_tree_model_iter_next (model, &iter));
230 }
231 
232 static void
brasero_medium_selection_set_show_used_space(BraseroMediumSelection * selector)233 brasero_medium_selection_set_show_used_space (BraseroMediumSelection *selector)
234 {
235 	GtkCellRenderer *renderer;
236 
237 	gtk_cell_layout_clear (GTK_CELL_LAYOUT (selector));
238 
239 	renderer = gtk_cell_renderer_pixbuf_new ();
240 	g_object_set (renderer, "follow-state", TRUE, NULL);
241 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (selector), renderer, FALSE);
242 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (selector), renderer,
243 					"gicon", ICON_COL,
244 					NULL);
245 
246 	renderer = gtk_cell_renderer_progress_new ();
247 	g_object_set (renderer, "xpad", 4, "text-xalign", 0.0, NULL);
248 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (selector), renderer, TRUE);
249 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (selector), renderer,
250 					"text", NAME_COL,
251 					"value", USED_COL,
252 					"visible", VISIBLE_PROGRESS_COL,
253 					NULL);
254 
255 	renderer = gtk_cell_renderer_text_new ();
256 	g_object_set (renderer, "xpad", 4, NULL);
257 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (selector), renderer, TRUE);
258 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (selector), renderer,
259 					"markup", NAME_COL,
260 					"visible", VISIBLE_TEXT_COL,
261 					NULL);
262 }
263 
264 void
brasero_medium_selection_update_media_string(BraseroMediumSelection * self)265 brasero_medium_selection_update_media_string (BraseroMediumSelection *self)
266 {
267 	GtkTreeModel *model;
268 	GtkTreeIter iter;
269 
270 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
271 	if (!gtk_tree_model_get_iter_first (model, &iter))
272 		return;
273 
274 	do {
275 		BraseroMedium *medium;
276 		gchar *label;
277 
278 		medium = NULL;
279 		gtk_tree_model_get (model, &iter,
280 				    MEDIUM_COL, &medium,
281 				    -1);
282 		if (!medium)
283 			continue;
284 
285 		label = brasero_medium_selection_get_medium_string (self, medium);
286 		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
287 				    NAME_COL, label,
288 				    -1);
289 
290 		g_object_unref (medium);
291 		g_free (label);
292 	} while (gtk_tree_model_iter_next (model, &iter));
293 }
294 
295 static void
brasero_medium_selection_set_current_medium(BraseroMediumSelection * self,GtkTreeIter * iter)296 brasero_medium_selection_set_current_medium (BraseroMediumSelection *self,
297 					     GtkTreeIter *iter)
298 {
299 	BraseroMediumSelectionPrivate *priv;
300 	BraseroMedium *medium = NULL;
301 	GtkTreeModel *model;
302 
303 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (self);
304 
305 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
306 	gtk_tree_model_get (model, iter,
307 			    MEDIUM_COL, &medium,
308 			    -1);
309 	if (medium)
310 		gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
311 	else
312 		gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
313 
314 	if (priv->active == medium) {
315 		if (medium)
316 			g_object_unref (medium);
317 
318 		return;
319 	}
320 
321 	if (priv->active)
322 		g_object_unref (priv->active);
323 
324 	/* NOTE: no need to ref priv->active as medium was
325 	 * already reffed in gtk_tree_model_get () */
326 	priv->active = medium;
327 	g_signal_emit (self,
328 		       brasero_medium_selection_signals [CHANGED_SIGNAL],
329 		       0,
330 		       priv->active);
331 }
332 
333 static void
brasero_drive_selection_set_tooltip(BraseroMediumSelection * self)334 brasero_drive_selection_set_tooltip (BraseroMediumSelection *self)
335 {
336 	BraseroMedium *medium;
337 	gchar *tooltip;
338 
339 	medium = brasero_medium_selection_get_active (self);
340 	if (medium) {
341 		tooltip = brasero_medium_get_tooltip (medium);
342 		g_object_unref (medium);
343 	}
344 	else
345 		tooltip = NULL;
346 
347 	gtk_widget_set_tooltip_text (GTK_WIDGET (self), tooltip);
348 	g_free (tooltip);
349 }
350 
351 static void
brasero_medium_selection_changed(GtkComboBox * combo)352 brasero_medium_selection_changed (GtkComboBox *combo)
353 {
354 	GtkTreeIter iter;
355 
356 	if (!gtk_combo_box_get_active_iter (combo, &iter))
357 		return;
358 
359 	brasero_medium_selection_set_current_medium (BRASERO_MEDIUM_SELECTION (combo), &iter);
360 	brasero_drive_selection_set_tooltip (BRASERO_MEDIUM_SELECTION (combo));
361 }
362 
363 /**
364  * brasero_medium_selection_set_active:
365  * @selector: a #BraseroMediumSelection
366  * @medium: a #BraseroMedium to set as the active one in the selector
367  *
368  * Sets the active medium. Emits the ::medium-changed signal.
369  *
370  * Return value: a #gboolean. TRUE if it succeeded, FALSE otherwise.
371  **/
372 gboolean
brasero_medium_selection_set_active(BraseroMediumSelection * selector,BraseroMedium * medium)373 brasero_medium_selection_set_active (BraseroMediumSelection *selector,
374 				     BraseroMedium *medium)
375 {
376 	BraseroMediumSelectionPrivate *priv;
377 	gboolean result = FALSE;
378 	GtkTreeModel *model;
379 	GtkTreeIter iter;
380 
381 	g_return_val_if_fail (selector != NULL, FALSE);
382 	g_return_val_if_fail (BRASERO_IS_MEDIUM_SELECTION (selector), FALSE);
383 
384 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (selector);
385 	if (priv->active == medium)
386 		return TRUE;
387 
388 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
389 	if (!gtk_tree_model_get_iter_first (model, &iter))
390 		return FALSE;
391 
392 	do {
393 		BraseroMedium *iter_medium;
394 
395 		gtk_tree_model_get (model, &iter,
396 				    MEDIUM_COL, &iter_medium,
397 				    -1);
398 
399 		if (medium == iter_medium) {
400 			if (iter_medium)
401 				g_object_unref (iter_medium);
402 
403 			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
404 			brasero_medium_selection_set_current_medium (selector, &iter);
405 			result = TRUE;
406 			break;
407 		}
408 
409 		if (iter_medium)
410 			g_object_unref (iter_medium);
411 	} while (gtk_tree_model_iter_next (model, &iter));
412 
413 	return result;
414 }
415 
416 /**
417  * brasero_medium_selection_get_active:
418  * @selector: a #BraseroMediumSelection
419  *
420  * Gets the active medium.
421  *
422  * Return value: a #BraseroMedium or NULL. Unref when it is not needed anymore.
423  **/
424 BraseroMedium *
brasero_medium_selection_get_active(BraseroMediumSelection * selector)425 brasero_medium_selection_get_active (BraseroMediumSelection *selector)
426 {
427 	BraseroMediumSelectionPrivate *priv;
428 
429 	g_return_val_if_fail (selector != NULL, NULL);
430 	g_return_val_if_fail (BRASERO_IS_MEDIUM_SELECTION (selector), NULL);
431 
432 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (selector);
433 	if (!priv->active)
434 		return NULL;
435 
436 	return g_object_ref (priv->active);
437 }
438 
439 static void
brasero_medium_selection_update_no_disc_entry(BraseroMediumSelection * self,GtkTreeModel * model,GtkTreeIter * iter)440 brasero_medium_selection_update_no_disc_entry (BraseroMediumSelection *self,
441 					       GtkTreeModel *model,
442 					       GtkTreeIter *iter)
443 {
444 	BraseroMediumMonitor *monitor;
445 	GIcon *icon;
446 
447 	monitor = brasero_medium_monitor_get_default ();
448 	if (brasero_medium_monitor_is_probing (monitor)) {
449 		icon = g_themed_icon_new_with_default_fallbacks ("image-loading");
450 		gtk_list_store_set (GTK_LIST_STORE (model), iter,
451 				    NAME_COL, _("Searching for available discs"),
452 				    ICON_COL, icon,
453 				    VISIBLE_TEXT_COL, TRUE,
454 				    VISIBLE_PROGRESS_COL, FALSE,
455 				    -1);
456 	}
457 	else {
458 		icon = g_themed_icon_new_with_default_fallbacks ("drive-optical");
459 		gtk_list_store_set (GTK_LIST_STORE (model), iter,
460 				    NAME_COL, _("No disc available"),
461 				    ICON_COL, icon,
462 				    VISIBLE_TEXT_COL, TRUE,
463 				    VISIBLE_PROGRESS_COL, FALSE,
464 				    -1);
465 	}
466 
467 	g_object_unref (icon);
468 	g_object_unref (monitor);
469 
470 	gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), iter);
471 	brasero_medium_selection_set_current_medium (self, iter);
472 }
473 
474 static void
brasero_medium_selection_add_no_disc_entry(BraseroMediumSelection * self)475 brasero_medium_selection_add_no_disc_entry (BraseroMediumSelection *self)
476 {
477 	GtkTreeIter iter;
478 	GtkTreeModel *model;
479 
480 	/* Nothing's available. Say it. Two cases here, either we're
481 	 * still probing drives or there isn't actually any available
482 	 * medium. */
483 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
484 	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
485 	brasero_medium_selection_update_no_disc_entry (self, model, &iter);
486 }
487 
488 /**
489  * brasero_medium_selection_show_media_type:
490  * @selector: a #BraseroMediumSelection
491  * @type: a #BraseroMediaType
492  *
493  * Filters and displays media corresponding to @type.
494  **/
495 void
brasero_medium_selection_show_media_type(BraseroMediumSelection * selector,BraseroMediaType type)496 brasero_medium_selection_show_media_type (BraseroMediumSelection *selector,
497 					  BraseroMediaType type)
498 {
499 	BraseroMediumSelectionPrivate *priv;
500 	BraseroMediumMonitor *monitor;
501 	GtkTreeModel *model;
502 	GtkTreeIter iter;
503 	GSList *list;
504 	GSList *item;
505 
506 	g_return_if_fail (selector != NULL);
507 	g_return_if_fail (BRASERO_IS_MEDIUM_SELECTION (selector));
508 
509 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (selector);
510 
511 	priv->type = type;
512 
513 	monitor = brasero_medium_monitor_get_default ();
514 	list = brasero_medium_monitor_get_media (monitor, type);
515 	g_object_unref (monitor);
516 
517 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
518 	if (gtk_tree_model_get_iter_first (model, &iter)) {
519 		/* First filter */
520 		do {
521 			GSList *node;
522 			BraseroMedium *medium;
523 
524 			gtk_tree_model_get (model, &iter,
525 					    MEDIUM_COL, &medium,
526 					    -1);
527 
528 			if (!medium) {
529 				/* That's the dummy line saying there isn't any
530 				 * available medium for whatever action it is */
531 				gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
532 				break;
533 			}
534 
535 			node = g_slist_find (list, medium);
536 			g_object_unref (medium);
537 
538 			if (!node) {
539 				if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter))
540 					continue;
541 
542 				/* no more iter in the tree get out */
543 				break;
544 			}
545 
546 			g_object_unref (node->data);
547 			list = g_slist_delete_link (list, node);
548 		} while (gtk_tree_model_iter_next (model, &iter));
549 	}
550 
551 	if (list) {
552 		/* add remaining media */
553 		for (item = list; item; item = item->next) {
554 			gchar *medium_name;
555 			GIcon *medium_icon;
556 			BraseroMedium *medium;
557 
558 			medium = item->data;
559 
560 			gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter,
561 			                                   -1,
562 			                                   MEDIUM_COL, medium,
563 			                                   -1);
564 
565 			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
566 
567 			medium_name = brasero_medium_selection_get_medium_string (selector, medium);
568 			medium_icon = brasero_volume_get_icon (BRASERO_VOLUME (medium));
569 			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
570 					    NAME_COL, medium_name,
571 					    ICON_COL, medium_icon,
572 					    VISIBLE_TEXT_COL, TRUE,
573 					    VISIBLE_PROGRESS_COL, FALSE,
574 					    -1);
575 			g_free (medium_name);
576 			g_object_unref (medium_icon);
577 		}
578 		g_slist_foreach (list, (GFunc) g_object_unref, NULL);
579 		g_slist_free (list);
580 	}
581 
582 	if (!gtk_tree_model_get_iter_first (model, &iter)) {
583 		brasero_medium_selection_add_no_disc_entry (selector);
584 		return;
585 	}
586 
587 	gtk_widget_set_sensitive (GTK_WIDGET (selector), TRUE);
588 	if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector)) == -1) {
589 		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
590 		brasero_medium_selection_set_current_medium (selector, &iter);
591 	}
592 }
593 
594 /**
595  * brasero_medium_selection_get_media_num:
596  * @selector: a #BraseroMediumSelection
597  * @type: a #BraseroMediaType
598  *
599  * Returns the number of media being currently displayed and available.
600  *
601  * Return value: a #guint
602  **/
603 guint
brasero_medium_selection_get_media_num(BraseroMediumSelection * selector)604 brasero_medium_selection_get_media_num (BraseroMediumSelection *selector)
605 {
606 	GtkTreeModel *model;
607 	GtkTreeIter iter;
608 	int num = 0;
609 
610 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
611 	if (!gtk_tree_model_get_iter_first (model, &iter))
612 		return 0;
613 
614 	do {
615 		BraseroMedium *medium;
616 
617 		medium = NULL;
618 		gtk_tree_model_get (model, &iter,
619 				    MEDIUM_COL, &medium,
620 				    -1);
621 		if (!medium)
622 			continue;
623 
624 		g_object_unref (medium);
625 		num ++;
626 
627 	} while (gtk_tree_model_iter_next (model, &iter));
628 
629 	return num;
630 }
631 
632 static void
brasero_medium_selection_medium_added_cb(BraseroMediumMonitor * monitor,BraseroMedium * medium,BraseroMediumSelection * self)633 brasero_medium_selection_medium_added_cb (BraseroMediumMonitor *monitor,
634 					  BraseroMedium *medium,
635 					  BraseroMediumSelection *self)
636 {
637 	BraseroMediumSelectionPrivate *priv;
638 	gboolean add = FALSE;
639 	GtkTreeModel *model;
640 	BraseroDrive *drive;
641 	gchar *medium_name;
642 	GIcon *medium_icon;
643 	GtkTreeIter iter;
644 
645 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (self);
646 
647 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
648 
649 	/* Make sure it's not already in our list */
650 	if (gtk_tree_model_get_iter_first (model, &iter)) {
651 		do {
652 			BraseroMedium *tmp;
653 
654 			tmp = NULL;
655 			gtk_tree_model_get (model, &iter,
656 					    MEDIUM_COL, &tmp,
657 					    -1);
658 			if (tmp == medium)
659 				return;
660 
661 		} while (gtk_tree_model_iter_next (model, &iter));
662 	}
663 
664 	/* Make sure it does fit the types of media to display */
665 	drive = brasero_medium_get_drive (medium);
666 	if ((priv->type & BRASERO_MEDIA_TYPE_CD) == priv->type
667 	&& (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD))
668 		add = TRUE;
669 
670 	if ((priv->type & BRASERO_MEDIA_TYPE_ANY_IN_BURNER)
671 	&&  (brasero_drive_can_write (drive))) {
672 		if ((priv->type & BRASERO_MEDIA_TYPE_CD)) {
673 			if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD)
674 				add = TRUE;
675 		}
676 		else
677 			add = TRUE;
678 	}
679 
680 	if ((priv->type & BRASERO_MEDIA_TYPE_AUDIO)
681 	&&  (brasero_medium_get_status (medium) & BRASERO_MEDIUM_HAS_AUDIO)) {
682 		if ((priv->type & BRASERO_MEDIA_TYPE_CD)) {
683 			if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD)
684 				add = TRUE;
685 		}
686 		else
687 			add = TRUE;
688 	}
689 
690 	if ((priv->type & BRASERO_MEDIA_TYPE_DATA)
691 	&&  (brasero_medium_get_status (medium) & BRASERO_MEDIUM_HAS_DATA)) {
692 		if ((priv->type & BRASERO_MEDIA_TYPE_CD)) {
693 			if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD)
694 				add = TRUE;
695 		}
696 		else
697 			add = TRUE;
698 	}
699 
700 	if (priv->type & BRASERO_MEDIA_TYPE_WRITABLE) {
701 		if (brasero_medium_can_be_written (medium)) {
702 			if ((priv->type & BRASERO_MEDIA_TYPE_CD)) {
703 				if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD)
704 					add = TRUE;
705 			}
706 			else
707 				add = TRUE;
708 		}
709 	}
710 
711 	if (priv->type & BRASERO_MEDIA_TYPE_REWRITABLE) {
712 		if (brasero_medium_can_be_rewritten (medium)) {
713 			if ((priv->type & BRASERO_MEDIA_TYPE_CD)) {
714 				if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_CD)
715 					add = TRUE;
716 			}
717 			else
718 				add = TRUE;
719 		}
720 	}
721 
722 	if (!add) {
723 		BraseroMedium *tmp;
724 
725 		/* Try to get the first iter (it shouldn't fail) */
726 		if (!gtk_tree_model_get_iter_first (model, &iter)) {
727 			brasero_medium_selection_add_no_disc_entry (self);
728 			return;
729 		}
730 
731 		/* See if that's a real medium or not; if so, return. */
732 		tmp = NULL;
733 		gtk_tree_model_get (model, &iter,
734 				    MEDIUM_COL, &tmp,
735 				    -1);
736 		if (tmp) {
737 			g_object_unref (tmp);
738 			return;
739 		}
740 
741 		brasero_medium_selection_update_no_disc_entry (self, model, &iter);
742 		return;
743 	}
744 
745 	/* remove warning message */
746 	if (gtk_tree_model_get_iter_first (model, &iter)) {
747 		BraseroMedium *tmp;
748 
749 		gtk_tree_model_get (model, &iter,
750 				    MEDIUM_COL, &tmp,
751 				    -1);
752 		if (!tmp)
753 			gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
754 		else
755 			g_object_unref (tmp);
756 	}
757 
758 	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter,
759 	                                   -1,
760 	                                   MEDIUM_COL, medium,
761 	                                   -1);
762 
763 	medium_name = brasero_medium_selection_get_medium_string (self, medium);
764 	medium_icon = brasero_volume_get_icon (BRASERO_VOLUME (medium));
765 	gtk_list_store_set (GTK_LIST_STORE (model), &iter,
766 			    NAME_COL, medium_name,
767 			    ICON_COL, medium_icon,
768 			    VISIBLE_TEXT_COL, TRUE,
769 			    VISIBLE_PROGRESS_COL, FALSE,
770 			    -1);
771 	g_free (medium_name);
772 	g_object_unref (medium_icon);
773 
774 	gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
775 	if (gtk_combo_box_get_active (GTK_COMBO_BOX (self)) == -1) {
776 		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
777 		brasero_medium_selection_set_current_medium (self, &iter);
778 	}
779 }
780 
781 static void
brasero_medium_selection_medium_removed_cb(BraseroMediumMonitor * monitor,BraseroMedium * medium,BraseroMediumSelection * self)782 brasero_medium_selection_medium_removed_cb (BraseroMediumMonitor *monitor,
783 					    BraseroMedium *medium,
784 					    BraseroMediumSelection *self)
785 {
786 	GtkTreeModel *model;
787 	GtkTreeIter iter;
788 
789 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
790 	if (!gtk_tree_model_get_iter_first (model, &iter))
791 		return;
792 
793 	do {
794 		BraseroMedium *iter_medium;
795 
796 		gtk_tree_model_get (model, &iter,
797 				    MEDIUM_COL, &iter_medium,
798 				    -1);
799 
800 		if (medium == iter_medium) {
801 			g_object_unref (iter_medium);
802 			gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
803 			break;
804 		}
805 
806 		/* Could be NULL if a message "there is no medium ..." is on */
807 		if (iter_medium)
808 			g_object_unref (iter_medium);
809 
810 	} while (gtk_tree_model_iter_next (model, &iter));
811 
812 	if (!gtk_tree_model_get_iter_first (model, &iter)) {
813 		brasero_medium_selection_add_no_disc_entry (self);
814 		return;
815 	}
816 
817 	if (gtk_combo_box_get_active (GTK_COMBO_BOX (self)) == -1) {
818 		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
819 		brasero_medium_selection_set_current_medium (self, &iter);
820 	}
821 }
822 
823 static void
brasero_medium_selection_constructed(GObject * object)824 brasero_medium_selection_constructed (GObject *object)
825 {
826 	G_OBJECT_CLASS (brasero_medium_selection_parent_class)->constructed (object);
827 
828 	brasero_medium_selection_set_show_used_space (BRASERO_MEDIUM_SELECTION (object));
829 }
830 
831 static void
brasero_medium_selection_init(BraseroMediumSelection * object)832 brasero_medium_selection_init (BraseroMediumSelection *object)
833 {
834 	GtkListStore *model;
835 	BraseroMediumMonitor *monitor;
836 	BraseroMediumSelectionPrivate *priv;
837 
838 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (object);
839 
840 	monitor = brasero_medium_monitor_get_default ();
841 	priv->added_sig = g_signal_connect (monitor,
842 					    "medium-added",
843 					    G_CALLBACK (brasero_medium_selection_medium_added_cb),
844 					    object);
845 	priv->removed_sig = g_signal_connect (monitor,
846 					      "medium-removed",
847 					      G_CALLBACK (brasero_medium_selection_medium_removed_cb),
848 					      object);
849 	g_object_unref (monitor);
850 
851 	/* get the list and fill the model */
852 	model = gtk_list_store_new (NUM_COL,
853 				    G_TYPE_OBJECT,
854 				    G_TYPE_STRING,
855 				    G_TYPE_ICON,
856 				    G_TYPE_UINT,
857 				    G_TYPE_BOOLEAN,
858 				    G_TYPE_BOOLEAN);
859 
860 	gtk_combo_box_set_model (GTK_COMBO_BOX (object), GTK_TREE_MODEL (model));
861 	g_object_unref (model);
862 }
863 
864 static void
brasero_medium_selection_finalize(GObject * object)865 brasero_medium_selection_finalize (GObject *object)
866 {
867 	BraseroMediumSelectionPrivate *priv;
868 	BraseroMediumMonitor *monitor;
869 
870 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (object);
871 
872 	monitor = brasero_medium_monitor_get_default ();
873 
874 	g_signal_handler_disconnect (monitor, priv->added_sig);
875 	g_signal_handler_disconnect (monitor, priv->removed_sig);
876 	priv->removed_sig = 0;
877 	priv->added_sig = 0;
878 
879 	g_object_unref (monitor);
880 
881 	G_OBJECT_CLASS (brasero_medium_selection_parent_class)->finalize (object);
882 }
883 
884 static void
brasero_medium_selection_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)885 brasero_medium_selection_set_property (GObject *object,
886 				       guint prop_id,
887 				       const GValue *value,
888 				       GParamSpec *pspec)
889 {
890 	g_return_if_fail (BRASERO_IS_MEDIUM_SELECTION (object));
891 
892 	switch (prop_id)
893 	{
894 	case PROP_MEDIA_TYPE:
895 		brasero_medium_selection_show_media_type (BRASERO_MEDIUM_SELECTION (object),
896 							  g_value_get_uint (value));
897 		break;
898 	case PROP_MEDIUM:
899 		brasero_medium_selection_set_active (BRASERO_MEDIUM_SELECTION (object),
900 						     BRASERO_MEDIUM (g_value_get_object (value)));
901 		break;
902 	default:
903 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
904 		break;
905 	}
906 }
907 
908 static void
brasero_medium_selection_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)909 brasero_medium_selection_get_property (GObject *object,
910 				       guint prop_id,
911 				       GValue *value,
912 				       GParamSpec *pspec)
913 {
914 	BraseroMediumSelectionPrivate *priv;
915 
916 	g_return_if_fail (BRASERO_IS_MEDIUM_SELECTION (object));
917 
918 	priv = BRASERO_MEDIUM_SELECTION_PRIVATE (object);
919 
920 	switch (prop_id)
921 	{
922 	case PROP_MEDIA_TYPE:
923 		g_value_set_uint (value, priv->type);
924 		break;
925 	case PROP_MEDIUM:
926 		g_value_set_object (value, brasero_medium_selection_get_active (BRASERO_MEDIUM_SELECTION (object)));
927 		break;
928 	default:
929 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
930 		break;
931 	}
932 }
933 
934 static void
brasero_medium_selection_class_init(BraseroMediumSelectionClass * klass)935 brasero_medium_selection_class_init (BraseroMediumSelectionClass *klass)
936 {
937 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
938 	GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (klass);
939 
940 	g_type_class_add_private (klass, sizeof (BraseroMediumSelectionPrivate));
941 
942 	object_class->constructed = brasero_medium_selection_constructed;
943 	object_class->finalize = brasero_medium_selection_finalize;
944 	object_class->set_property = brasero_medium_selection_set_property;
945 	object_class->get_property = brasero_medium_selection_get_property;
946 
947 	combo_class->changed = brasero_medium_selection_changed;
948 
949 	g_object_class_install_property (object_class, PROP_MEDIUM,
950 					 g_param_spec_object ("medium",
951 							      "Selected medium",
952 							      "The currently selected medium",
953 							      BRASERO_TYPE_MEDIUM, G_PARAM_READWRITE));
954 
955 	g_object_class_install_property (object_class, PROP_MEDIA_TYPE,
956 					 g_param_spec_uint ("media-type",
957 							    "The type of media",
958 							    "The type of media displayed",
959 							    0, BRASERO_MEDIA_TYPE_ALL,
960 							    BRASERO_MEDIA_TYPE_NONE,
961 							    G_PARAM_READWRITE));
962 	/**
963  	* BraseroMediumSelection::medium-changed:
964  	* @monitor: the object which received the signal
965   	* @medium: the new selected medium
966 	*
967  	* This signal gets emitted when the selected medium has changed.
968  	**/
969 	brasero_medium_selection_signals [CHANGED_SIGNAL] =
970 	    g_signal_new ("medium_changed",
971 			  BRASERO_TYPE_MEDIUM_SELECTION,
972 			  G_SIGNAL_RUN_FIRST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
973 			  G_STRUCT_OFFSET (BraseroMediumSelectionClass, medium_changed),
974 			  NULL,
975 			  NULL,
976 			  g_cclosure_marshal_VOID__OBJECT,
977 			  G_TYPE_NONE,
978 			  1,
979 			  BRASERO_TYPE_MEDIUM);
980 }
981 
982 /**
983  * brasero_medium_selection_new:
984  *
985  * Creates a new #BraseroMediumSelection object
986  *
987  * Return value: a #GtkWidget. Unref when it is not needed anymore.
988  **/
989 GtkWidget *
brasero_medium_selection_new(void)990 brasero_medium_selection_new (void)
991 {
992 	return g_object_new (BRASERO_TYPE_MEDIUM_SELECTION, NULL);
993 }
994