source: trunk/third/nautilus-cd-burner/bacon-cd-selection.c @ 21565

Revision 21565, 12.2 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21564, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 2002-2004 Bastien Nocera <hadess@hadess.net>
4 *
5 * bacon-cd-selection.c
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * Authors: Bastien Nocera <hadess@hadess.net>
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <glib.h>
29#include <glib/gi18n.h>
30
31#include <string.h>
32
33#include <gtk/gtkmenu.h>
34#include <gtk/gtkcombobox.h>
35#include <gtk/gtkliststore.h>
36#include <gtk/gtkcelllayout.h>
37#include <gtk/gtkcellrenderertext.h>
38
39#include "bacon-cd-selection.h"
40#include "cd-drive.h"
41
42/* Signals */
43enum {
44        DEVICE_CHANGED,
45        LAST_SIGNAL
46};
47
48/* Arguments */
49enum {
50        PROP_0,
51        PROP_DEVICE,
52        PROP_FILE_IMAGE,
53        PROP_RECORDERS_ONLY,
54};
55
56struct BaconCdSelectionPrivate {
57        GList *cdroms;
58        gboolean have_file_image;
59        gboolean show_recorders_only;
60};
61
62static void bacon_cd_selection_init (BaconCdSelection *bcs);
63
64static void bacon_cd_selection_set_property (GObject *object, guint property_id,
65                const GValue *value, GParamSpec *pspec);
66static void bacon_cd_selection_get_property (GObject *object, guint property_id,
67                GValue *value, GParamSpec *pspec);
68
69static void bacon_cd_selection_finalize (GObject *object);
70
71static GtkWidgetClass *parent_class = NULL;
72
73static int bcs_table_signals[LAST_SIGNAL] = { 0 };
74
75static CDDrive *
76get_drive (BaconCdSelection *bcs, int nr)
77{
78        GList *item;
79
80        item = g_list_nth (bcs->priv->cdroms, nr);
81        if (item == NULL)
82                return NULL;
83        else
84                return item->data;
85}
86
87G_DEFINE_TYPE(BaconCdSelection, bacon_cd_selection, GTK_TYPE_COMBO_BOX)
88
89static void
90bacon_cd_selection_class_init (BaconCdSelectionClass *klass)
91{
92        GObjectClass *object_class;
93        GtkWidgetClass *widget_class;
94
95        object_class = (GObjectClass *) klass;
96        widget_class = (GtkWidgetClass *) klass;
97
98        parent_class = gtk_type_class (gtk_combo_box_get_type ());
99
100        /* GObject */
101        object_class->set_property = bacon_cd_selection_set_property;
102        object_class->get_property = bacon_cd_selection_get_property;
103        object_class->finalize = bacon_cd_selection_finalize;
104
105        /* Properties */
106        g_object_class_install_property (object_class, PROP_DEVICE,
107                        g_param_spec_string ("device", NULL, NULL,
108                                NULL, G_PARAM_READWRITE));
109        g_object_class_install_property (object_class, PROP_FILE_IMAGE,
110                        g_param_spec_boolean ("file-image", NULL, NULL,
111                                FALSE, G_PARAM_READWRITE));
112        g_object_class_install_property (object_class, PROP_RECORDERS_ONLY,
113                        g_param_spec_boolean ("show-recorders-only", NULL, NULL,
114                                FALSE, G_PARAM_READWRITE));
115
116        /* Signals */
117        bcs_table_signals[DEVICE_CHANGED] =
118                g_signal_new ("device-changed",
119                                G_TYPE_FROM_CLASS (object_class),
120                                G_SIGNAL_RUN_LAST,
121                                G_STRUCT_OFFSET (BaconCdSelectionClass,
122                                        device_changed),
123                                NULL, NULL,
124                                g_cclosure_marshal_VOID__STRING,
125                                G_TYPE_NONE, 1, G_TYPE_STRING);
126}
127
128static void
129combo_device_changed (GtkComboBox *combo, gpointer user_data)
130{
131        BaconCdSelection *bcs = (BaconCdSelection *) user_data;
132        CDDrive *drive;
133        int i;
134
135        i = gtk_combo_box_get_active (GTK_COMBO_BOX (bcs));
136        /* No selection */
137        if (i < 0) {
138                g_signal_emit (G_OBJECT (bcs),
139                                bcs_table_signals[DEVICE_CHANGED],
140                                0, NULL);
141                return;
142        }
143        drive = get_drive (bcs, i);
144        if (drive == NULL)
145                return;
146
147        g_signal_emit (G_OBJECT (bcs),
148                       bcs_table_signals[DEVICE_CHANGED],
149                       0, drive->device);
150}
151
152static void
153cdrom_combo_box (BaconCdSelection *bcs, gboolean show_recorders_only, gboolean show_file_image)
154{
155        GList *l;
156        CDDrive *cdrom;
157
158        bcs->priv->cdroms = scan_for_cdroms (show_recorders_only, show_file_image);
159
160        for (l = bcs->priv->cdroms; l != NULL; l = l->next)
161        {
162                cdrom = l->data;
163
164                if (cdrom->display_name == NULL) {
165                        g_warning ("cdrom->display_name != NULL failed");
166                }
167
168                gtk_combo_box_append_text (GTK_COMBO_BOX (bcs),
169                                cdrom->display_name
170                                ? cdrom->display_name : _("Unnamed CDROM"));
171        }
172        gtk_combo_box_set_active (GTK_COMBO_BOX (bcs), 0);
173
174        if (bcs->priv->cdroms == NULL) {
175                gtk_widget_set_sensitive (GTK_WIDGET (bcs), FALSE);
176        }
177}
178
179static void
180bacon_cd_selection_init (BaconCdSelection *bcs)
181{
182        bcs->priv = g_new0 (BaconCdSelectionPrivate, 1);
183 
184        GtkCellRenderer *cell;
185        GtkListStore *store;
186
187  store = gtk_list_store_new (1, G_TYPE_STRING);
188        gtk_combo_box_set_model (GTK_COMBO_BOX (bcs),
189                        GTK_TREE_MODEL (store));
190
191        cell = gtk_cell_renderer_text_new ();
192        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (bcs), cell, TRUE);
193        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (bcs), cell,
194                        "text", 0,
195                        NULL);
196
197        cdrom_combo_box (bcs, FALSE, FALSE);
198
199        g_signal_connect (G_OBJECT (bcs), "changed",
200                        G_CALLBACK (combo_device_changed), bcs);
201}
202
203static void
204bacon_cd_selection_finalize (GObject *object)
205{
206        GList *l;
207        BaconCdSelection *bcs = (BaconCdSelection *) object;
208
209        g_return_if_fail (bcs != NULL);
210        g_return_if_fail (BACON_IS_CD_SELECTION (bcs));
211
212        l = bcs->priv->cdroms;
213        while (l != NULL)
214        {
215                CDDrive *cdrom = l->data;
216
217                l = g_list_remove (l, cdrom);
218                cd_drive_free (cdrom);
219        }
220
221        g_free (bcs->priv);
222        bcs->priv = NULL;
223
224        if (G_OBJECT_CLASS (parent_class)->finalize != NULL) {
225                (* G_OBJECT_CLASS (parent_class)->finalize) (object);
226        }
227}
228
229GtkWidget *
230bacon_cd_selection_new (void)
231{
232  return GTK_WIDGET(g_object_new (bacon_cd_selection_get_type (), NULL));
233}
234
235static void
236bacon_cd_selection_set_have_file_image (BaconCdSelection *bcs,
237                gboolean have_file_image)
238{
239        CDDrive *cdrom;
240
241        g_return_if_fail (bcs != NULL);
242        g_return_if_fail (BACON_IS_CD_SELECTION (bcs));
243
244        if (bcs->priv->have_file_image == have_file_image) {
245                return;
246        }
247
248        if (have_file_image == FALSE)
249        {
250                GList *item;
251                int index;
252
253                index = g_list_length (bcs->priv->cdroms) - 1;
254                gtk_combo_box_remove_text (GTK_COMBO_BOX (bcs), index);
255
256                item = g_list_last (bcs->priv->cdroms);
257                cdrom = (CDDrive *)item->data;
258                cd_drive_free (cdrom);
259                bcs->priv->cdroms = g_list_delete_link
260                        (bcs->priv->cdroms, item);
261                gtk_widget_set_sensitive (GTK_WIDGET (bcs), (bcs->priv->cdroms != NULL));
262        } else {
263                gboolean activate = FALSE;
264
265                cdrom = cd_drive_get_file_image ();
266                gtk_combo_box_append_text (GTK_COMBO_BOX (bcs),
267                                cdrom->display_name);
268                if (bcs->priv->cdroms == NULL) {
269                        activate = TRUE;
270                }
271                bcs->priv->cdroms = g_list_append (bcs->priv->cdroms, cdrom);
272                gtk_widget_set_sensitive (GTK_WIDGET (bcs), TRUE);
273                if (activate != FALSE) {
274                        gtk_combo_box_set_active (GTK_COMBO_BOX (bcs), 0);
275                }
276        }
277
278        bcs->priv->have_file_image = have_file_image;
279}
280
281static gint
282compare_drives (CDDrive *drive1, CDDrive *drive2)
283{
284        if (!drive1 || !drive2)
285                return 1;
286
287        if ((drive1->type & CDDRIVE_TYPE_FILE)
288            && (drive2->type & CDDRIVE_TYPE_FILE))
289                return 0;
290
291        if (!drive1->device || !drive2->device)
292                return 1;
293
294        return strcmp (drive1->device, drive2->device);
295}
296
297static void
298bacon_cd_selection_set_recorders_only (BaconCdSelection *bcs,
299                                       gboolean recorders_only)
300{
301
302        g_return_if_fail (bcs != NULL);
303        g_return_if_fail (BACON_IS_CD_SELECTION (bcs));
304
305        if (bcs->priv->show_recorders_only == recorders_only)
306                return;
307
308        g_signal_handlers_block_by_func (G_OBJECT (bcs),
309                        combo_device_changed, bcs);
310
311        if (recorders_only == TRUE) {
312                GList *l = g_list_last (bcs->priv->cdroms);
313                int i = g_list_length (bcs->priv->cdroms);
314
315                while (l) {
316                        GList *prev = l->prev;
317                        CDDrive *drive = l->data;
318
319                        i--;
320
321                        if (!(drive->type & CDDRIVE_TYPE_CD_RECORDER
322                              || drive->type & CDDRIVE_TYPE_CDRW_RECORDER
323                              || drive->type & CDDRIVE_TYPE_DVD_RAM_RECORDER
324                              || drive->type & CDDRIVE_TYPE_DVD_RW_RECORDER
325                              || drive->type & CDDRIVE_TYPE_FILE)) {
326                                gtk_combo_box_remove_text (GTK_COMBO_BOX (bcs), i);
327                                cd_drive_free (drive);
328                                bcs->priv->cdroms = g_list_delete_link (bcs->priv->cdroms, l);
329                        }
330
331                        l = prev;
332                }
333
334                /* Removing entries from the combo box may have invalidated
335                 * the currently selected one
336                 */
337                if (gtk_combo_box_get_active (GTK_COMBO_BOX (bcs)) == -1) {
338                        gtk_combo_box_set_active (GTK_COMBO_BOX (bcs), 0);
339                }
340        } else {
341                GList *drives = scan_for_cdroms (recorders_only, bcs->priv->have_file_image);
342                GList *l;
343                int i = g_list_length (bcs->priv->cdroms);
344
345                gtk_widget_set_sensitive (GTK_WIDGET (bcs), (drives != NULL));
346
347                if (bcs->priv->have_file_image)
348                        i--;
349
350                for (l = drives; l != NULL; l = l->next) {
351                        CDDrive *drive = l->data;
352
353                        if (!g_list_find_custom (bcs->priv->cdroms,
354                                                 drive,
355                                                 (GCompareFunc)compare_drives)) {
356                                gtk_combo_box_insert_text (GTK_COMBO_BOX (bcs),
357                                                           i,
358                                                           drive->display_name);
359                                bcs->priv->cdroms = g_list_insert (bcs->priv->cdroms,
360                                                                   drive,
361                                                                   i);
362                        } else {
363                                cd_drive_free (drive);
364                        }
365                }
366                g_list_free (drives);
367        }
368
369        g_signal_handlers_unblock_by_func (G_OBJECT (bcs),
370                        combo_device_changed, bcs);
371
372        /* Force a signal out */
373        combo_device_changed (NULL, (gpointer) bcs);
374
375        bcs->priv->show_recorders_only = recorders_only;
376}
377
378/* Properties */
379static void
380bacon_cd_selection_set_property (GObject *object, guint property_id,
381                const GValue *value, GParamSpec *pspec)
382{
383        BaconCdSelection *bcs;
384
385        g_return_if_fail (BACON_IS_CD_SELECTION (object));
386
387        bcs = BACON_CD_SELECTION (object);
388
389        switch (property_id)
390        {
391        case PROP_DEVICE:
392                bacon_cd_selection_set_device (bcs, g_value_get_string (value));
393                break;
394        case PROP_FILE_IMAGE:
395                bacon_cd_selection_set_have_file_image (bcs,
396                                g_value_get_boolean (value));
397                break;
398        case PROP_RECORDERS_ONLY:
399                bacon_cd_selection_set_recorders_only (bcs,
400                                g_value_get_boolean (value));
401                break;
402        default:
403                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
404        }
405}
406
407static void
408bacon_cd_selection_get_property (GObject *object, guint property_id,
409                GValue *value, GParamSpec *pspec)
410{
411        BaconCdSelection *bcs;
412
413        g_return_if_fail (BACON_IS_CD_SELECTION (object));
414
415        bcs = BACON_CD_SELECTION (object);
416
417        switch (property_id)
418        {
419        case PROP_DEVICE:
420                g_value_set_string (value, bacon_cd_selection_get_device (bcs));
421                break;
422        case PROP_FILE_IMAGE:
423                g_value_set_boolean (value, bcs->priv->have_file_image);
424                break;
425        case PROP_RECORDERS_ONLY:
426                g_value_set_boolean (value, bcs->priv->show_recorders_only);
427                break;
428        default:
429                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
430        }
431}
432
433const char *
434bacon_cd_selection_get_default_device (BaconCdSelection *bcs)
435{
436        GList *l;
437        CDDrive *drive;
438
439        g_return_val_if_fail (bcs != NULL, "/dev/cdrom");
440        g_return_val_if_fail (BACON_IS_CD_SELECTION (bcs), "/dev/cdrom");
441
442        l = bcs->priv->cdroms;
443        if (bcs->priv->cdroms == NULL)
444                return "/dev/cdrom";
445
446        drive = l->data;
447
448        return drive->device;
449}
450
451void
452bacon_cd_selection_set_device (BaconCdSelection *bcs, const char *device)
453{
454        GList *l;
455        CDDrive *drive;
456        gboolean found;
457        int i;
458
459        found = FALSE;
460        i = -1;
461
462        g_return_if_fail (bcs != NULL);
463        g_return_if_fail (BACON_IS_CD_SELECTION (bcs));
464
465        for (l = bcs->priv->cdroms; l != NULL && found == FALSE;
466                        l = l->next)
467        {
468                i++;
469
470                drive = l->data;
471
472                if (strcmp (drive->device, device) == 0)
473                        found = TRUE;
474        }
475
476        if (found)
477        {
478                gtk_combo_box_set_active (GTK_COMBO_BOX (bcs), i);
479        } else {
480                /* If the device doesn't exist, set it back to
481                 * the default */
482                gtk_combo_box_set_active (GTK_COMBO_BOX (bcs), 0);
483
484                drive = get_drive (bcs, 0);
485
486                if (drive == NULL)
487                        return;
488
489                g_signal_emit (G_OBJECT (bcs),
490                                bcs_table_signals [DEVICE_CHANGED],
491                                0, drive->device);
492        }
493}
494
495const char *
496bacon_cd_selection_get_device (BaconCdSelection *bcs)
497{
498        CDDrive *drive;
499        int i;
500
501        g_return_val_if_fail (bcs != NULL, NULL);
502        g_return_val_if_fail (BACON_IS_CD_SELECTION (bcs), NULL);
503
504        i = gtk_combo_box_get_active (GTK_COMBO_BOX (bcs));
505        drive = get_drive (bcs, i);
506
507        return drive ? drive->device : NULL;
508}
509
510const CDDrive *
511bacon_cd_selection_get_cdrom (BaconCdSelection *bcs)
512{
513        CDDrive *drive;
514        int i;
515
516        g_return_val_if_fail (bcs != NULL, NULL);
517        g_return_val_if_fail (BACON_IS_CD_SELECTION (bcs), NULL);
518
519        i = gtk_combo_box_get_active (GTK_COMBO_BOX (bcs));
520        drive = get_drive (bcs, i);
521
522        return drive;
523}
524
Note: See TracBrowser for help on using the repository browser.