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