1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
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.
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.
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.
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.
36
#include <glib-object.h>
37
#include <glib/gi18n-lib.h>
41
#include "brasero-drive-selection.h"
42
#include "brasero-medium-monitor.h"
43
#include "brasero-drive.h"
44
#include "brasero-units.h"
46
typedef struct _BraseroDriveSelectionPrivate BraseroDriveSelectionPrivate;
47
struct _BraseroDriveSelectionPrivate
51
BraseroDriveType type;
56
#define BRASERO_DRIVE_SELECTION_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DRIVE_SELECTION, BraseroDriveSelectionPrivate))
61
} BraseroDriveSelectionSignalType;
64
static GtkBuildableIface *parent_buildable_iface;
66
static guint brasero_drive_selection_signals [LAST_SIGNAL] = { 0 };
83
brasero_drive_selection_buildable_init (GtkBuildableIface *iface)
85
parent_buildable_iface = g_type_interface_peek_parent (iface);
88
G_DEFINE_TYPE_WITH_CODE (BraseroDriveSelection, brasero_drive_selection, GTK_TYPE_COMBO_BOX, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, brasero_drive_selection_buildable_init));
91
brasero_drive_selection_set_current_drive (BraseroDriveSelection *self,
94
BraseroDriveSelectionPrivate *priv;
98
priv = BRASERO_DRIVE_SELECTION_PRIVATE (self);
100
model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
101
gtk_tree_model_get (model, iter,
106
gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
108
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
110
if (priv->active == drive)
114
g_object_unref (priv->active);
116
priv->active = drive;
119
g_object_ref (priv->active);
122
brasero_drive_selection_signals [CHANGED_SIGNAL],
128
brasero_drive_selection_changed (GtkComboBox *combo)
132
if (!gtk_combo_box_get_active_iter (combo, &iter))
135
brasero_drive_selection_set_current_drive (BRASERO_DRIVE_SELECTION (combo), &iter);
139
* brasero_drive_selection_set_active:
140
* @selector: a #BraseroDriveSelection
141
* @drive: a #BraseroDrive to set as the active one in the selector
143
* Sets the active drive. Emits the ::drive-changed signal.
145
* Return value: a #gboolean. TRUE if it succeeded, FALSE otherwise.
148
brasero_drive_selection_set_active (BraseroDriveSelection *selector,
151
BraseroDriveSelectionPrivate *priv;
152
gboolean result = FALSE;
156
g_return_val_if_fail (selector != NULL, FALSE);
157
g_return_val_if_fail (BRASERO_IS_DRIVE_SELECTION (selector), FALSE);
159
priv = BRASERO_DRIVE_SELECTION_PRIVATE (selector);
161
if (priv->active == drive)
164
model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
165
if (!gtk_tree_model_get_iter_first (model, &iter))
169
BraseroDrive *iter_drive;
171
gtk_tree_model_get (model, &iter,
172
DRIVE_COL, &iter_drive,
175
if (drive == iter_drive) {
177
g_object_unref (iter_drive);
179
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
180
brasero_drive_selection_set_current_drive (selector, &iter);
185
g_object_unref (iter_drive);
186
} while (gtk_tree_model_iter_next (model, &iter));
192
* brasero_drive_selection_get_active:
193
* @selector: a #BraseroDriveSelection
195
* Gets the active drive.
197
* Return value: a #BraseroDrive or NULL. Unref when it is not needed anymore.
200
brasero_drive_selection_get_active (BraseroDriveSelection *selector)
202
BraseroDriveSelectionPrivate *priv;
204
g_return_val_if_fail (selector != NULL, NULL);
205
g_return_val_if_fail (BRASERO_IS_DRIVE_SELECTION (selector), NULL);
207
priv = BRASERO_DRIVE_SELECTION_PRIVATE (selector);
211
return g_object_ref (priv->active);
215
brasero_drive_selection_update_no_disc_entry (BraseroDriveSelection *self,
221
icon = g_themed_icon_new_with_default_fallbacks ("drive-optical");
223
/* FIXME: that needs a string */
224
gtk_list_store_set (GTK_LIST_STORE (model), iter,
229
g_object_unref (icon);
231
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), iter);
232
brasero_drive_selection_set_current_drive (self, iter);
236
brasero_drive_selection_add_no_disc_entry (BraseroDriveSelection *self)
241
/* Nothing's available. Say it. Two cases here, either we're
242
* still probing drives or there isn't actually any available
244
model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
245
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
246
brasero_drive_selection_update_no_disc_entry (self, model, &iter);
250
* brasero_drive_selection_show_type:
251
* @selector: a #BraseroDriveSelection
252
* @type: a #BraseroDriveType
254
* Filters and displays drive corresponding to @type.
258
brasero_drive_selection_show_type (BraseroDriveSelection *selector,
259
BraseroDriveType type)
261
BraseroDriveSelectionPrivate *priv;
262
BraseroMediumMonitor *monitor;
268
g_return_if_fail (selector != NULL);
269
g_return_if_fail (BRASERO_IS_DRIVE_SELECTION (selector));
271
priv = BRASERO_DRIVE_SELECTION_PRIVATE (selector);
275
monitor = brasero_medium_monitor_get_default ();
276
list = brasero_medium_monitor_get_drives (monitor, type);
277
g_object_unref (monitor);
279
model = gtk_combo_box_get_model (GTK_COMBO_BOX (selector));
280
if (gtk_tree_model_get_iter_first (model, &iter)) {
286
gtk_tree_model_get (model, &iter,
291
/* That's the dummy line saying there isn't any
292
* available drive for whatever action it is */
293
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
297
node = g_slist_find (list, drive);
298
g_object_unref (drive);
301
if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter))
304
/* no more iter in the tree get out */
308
g_object_unref (node->data);
309
list = g_slist_delete_link (list, node);
310
} while (gtk_tree_model_iter_next (model, &iter));
314
/* add remaining drive */
315
for (item = list; item; item = item->next) {
318
GIcon *drive_icon = NULL;
322
drive_name = brasero_drive_get_display_name (drive);
324
if (!brasero_drive_is_fake (drive)) {
327
gdrive = brasero_drive_get_gdrive (drive);
329
drive_icon = g_drive_get_icon (gdrive);
330
g_object_unref (gdrive);
333
drive_icon = g_themed_icon_new_with_default_fallbacks ("drive-optical");
336
drive_icon = g_themed_icon_new_with_default_fallbacks ("iso-image-new");
338
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
339
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
341
NAME_COL, drive_name?drive_name:_("Unnamed CD/DVD Drive"),
342
ICON_COL, drive_icon,
345
g_object_unref (drive_icon);
347
g_slist_foreach (list, (GFunc) g_object_unref, NULL);
351
if (!gtk_tree_model_get_iter_first (model, &iter)) {
352
brasero_drive_selection_add_no_disc_entry (selector);
356
gtk_widget_set_sensitive (GTK_WIDGET (selector), TRUE);
357
if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector)) == -1) {
358
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
359
brasero_drive_selection_set_current_drive (selector, &iter);
364
brasero_drive_selection_drive_added_cb (BraseroMediumMonitor *monitor,
366
BraseroDriveSelection *self)
368
BraseroDriveSelectionPrivate *priv;
369
gchar *drive_name = NULL;
370
gboolean add = FALSE;
375
priv = BRASERO_DRIVE_SELECTION_PRIVATE (self);
377
if ((priv->type & BRASERO_DRIVE_TYPE_WRITER)
378
&& (brasero_drive_can_write (drive)))
380
else if (priv->type & BRASERO_DRIVE_TYPE_READER)
383
model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
386
/* Try to get the first iter (it shouldn't fail) */
387
if (!gtk_tree_model_get_iter_first (model, &iter)) {
388
brasero_drive_selection_add_no_disc_entry (self);
392
/* See if that's a real drive or not; if so, return. */
394
gtk_tree_model_get (model, &iter,
400
brasero_drive_selection_update_no_disc_entry (self, model, &iter);
404
/* remove warning message */
405
if (gtk_tree_model_get_iter_first (model, &iter)) {
408
gtk_tree_model_get (model, &iter,
412
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
414
g_object_unref (tmp);
417
if (!brasero_drive_is_fake (drive)) {
420
gdrive = brasero_drive_get_gdrive (drive);
422
drive_icon = g_drive_get_icon (gdrive);
423
g_object_unref (gdrive);
426
drive_icon = g_themed_icon_new_with_default_fallbacks ("drive-optical");
429
drive_icon = g_themed_icon_new_with_default_fallbacks ("iso-image-new");
431
drive_name = brasero_drive_get_display_name (drive);
433
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
434
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
436
NAME_COL, drive_name?drive_name:_("Unnamed CD/DVD Drive"),
437
ICON_COL, drive_icon,
440
g_object_unref (drive_icon);
442
gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
443
if (gtk_combo_box_get_active (GTK_COMBO_BOX (self)) == -1) {
444
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
445
brasero_drive_selection_set_current_drive (self, &iter);
450
brasero_drive_selection_drive_removed_cb (BraseroMediumMonitor *monitor,
452
BraseroDriveSelection *self)
457
model = gtk_combo_box_get_model (GTK_COMBO_BOX (self));
458
if (!gtk_tree_model_get_iter_first (model, &iter))
462
BraseroDrive *iter_drive;
464
gtk_tree_model_get (model, &iter,
465
DRIVE_COL, &iter_drive,
468
if (drive == iter_drive) {
469
g_object_unref (iter_drive);
470
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
474
/* Could be NULL if a message "there is no drive ..." is on */
476
g_object_unref (iter_drive);
478
} while (gtk_tree_model_iter_next (model, &iter));
480
if (!gtk_tree_model_get_iter_first (model, &iter)) {
481
brasero_drive_selection_add_no_disc_entry (self);
485
if (gtk_combo_box_get_active (GTK_COMBO_BOX (self)) == -1) {
486
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
487
brasero_drive_selection_set_current_drive (self, &iter);
492
brasero_drive_selection_init (BraseroDriveSelection *object)
495
GtkCellRenderer *renderer;
496
BraseroMediumMonitor *monitor;
497
BraseroDriveSelectionPrivate *priv;
499
priv = BRASERO_DRIVE_SELECTION_PRIVATE (object);
501
monitor = brasero_medium_monitor_get_default ();
502
priv->added_sig = g_signal_connect (monitor,
504
G_CALLBACK (brasero_drive_selection_drive_added_cb),
506
priv->removed_sig = g_signal_connect (monitor,
508
G_CALLBACK (brasero_drive_selection_drive_removed_cb),
511
g_object_unref (monitor);
513
/* get the list and fill the model */
514
model = gtk_list_store_new (NUM_COL,
519
gtk_combo_box_set_model (GTK_COMBO_BOX (object), GTK_TREE_MODEL (model));
520
g_object_unref (model);
522
renderer = gtk_cell_renderer_pixbuf_new ();
523
g_object_set (renderer, "follow-state", TRUE, NULL);
524
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, FALSE);
525
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer,
529
renderer = gtk_cell_renderer_text_new ();
530
g_object_set (renderer, "xpad", 8, NULL);
531
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, TRUE);
532
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer,
536
brasero_drive_selection_show_type (BRASERO_DRIVE_SELECTION (object),
537
BRASERO_DRIVE_TYPE_ALL_BUT_FILE);
542
brasero_drive_selection_finalize (GObject *object)
544
BraseroDriveSelectionPrivate *priv;
545
BraseroMediumMonitor *monitor;
547
priv = BRASERO_DRIVE_SELECTION_PRIVATE (object);
549
monitor = brasero_medium_monitor_get_default ();
551
g_signal_handler_disconnect (monitor, priv->added_sig);
552
g_signal_handler_disconnect (monitor, priv->removed_sig);
553
priv->removed_sig = 0;
556
g_object_unref (monitor);
558
G_OBJECT_CLASS (brasero_drive_selection_parent_class)->finalize (object);
562
brasero_drive_selection_set_property (GObject *object,
567
g_return_if_fail (BRASERO_IS_DRIVE_SELECTION (object));
571
case PROP_DRIVE_TYPE:
572
brasero_drive_selection_show_type (BRASERO_DRIVE_SELECTION (object),
573
g_value_get_uint (value));
576
brasero_drive_selection_set_active (BRASERO_DRIVE_SELECTION (object),
577
BRASERO_DRIVE (g_value_get_object (value)));
580
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
586
brasero_drive_selection_get_property (GObject *object,
591
BraseroDriveSelectionPrivate *priv;
593
g_return_if_fail (BRASERO_IS_DRIVE_SELECTION (object));
595
priv = BRASERO_DRIVE_SELECTION_PRIVATE (object);
599
case PROP_DRIVE_TYPE:
600
g_value_set_uint (value, priv->type);
603
g_value_set_object (value, brasero_drive_selection_get_active (BRASERO_DRIVE_SELECTION (object)));
606
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
612
brasero_drive_selection_class_init (BraseroDriveSelectionClass *klass)
614
GObjectClass* object_class = G_OBJECT_CLASS (klass);
615
GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (klass);
617
g_type_class_add_private (klass, sizeof (BraseroDriveSelectionPrivate));
619
object_class->finalize = brasero_drive_selection_finalize;
620
object_class->set_property = brasero_drive_selection_set_property;
621
object_class->get_property = brasero_drive_selection_get_property;
623
combo_class->changed = brasero_drive_selection_changed;
625
g_object_class_install_property (object_class, PROP_DRIVE,
626
g_param_spec_object ("Drive",
628
"The currently selected drive",
629
BRASERO_TYPE_DRIVE, G_PARAM_READWRITE));
631
g_object_class_install_property (object_class, PROP_DRIVE_TYPE,
632
g_param_spec_uint ("drive-type",
633
"The type of drives",
634
"The type of drives displayed",
635
0, BRASERO_DRIVE_TYPE_ALL,
636
BRASERO_DRIVE_TYPE_ALL_BUT_FILE,
639
* BraseroDriveSelection::drive-changed:
640
* @selector: the object which received the signal
641
* @drive: the drive which is now selected
643
* This signal gets emitted when the selected medium has changed
646
brasero_drive_selection_signals [CHANGED_SIGNAL] =
647
g_signal_new ("drive_changed",
648
BRASERO_TYPE_DRIVE_SELECTION,
649
G_SIGNAL_RUN_FIRST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
650
G_STRUCT_OFFSET (BraseroDriveSelectionClass, drive_changed),
653
g_cclosure_marshal_VOID__OBJECT,
660
* brasero_drive_selection_new:
662
* Creates a new #BraseroDriveSelection object
664
* Return value: a #GtkWidget. Unref when it is not needed anymore.
668
brasero_drive_selection_new (void)
670
return g_object_new (BRASERO_TYPE_DRIVE_SELECTION, NULL);