Logo Search packages:      
Sourcecode: nautilus-cd-burner version File versions  Download package

ncb-selection-dialog.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Authors: William Jon McCann <mccann@jhu.edu>
 *
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>

#include <glade/glade.h>
#include <libgnomevfs/gnome-vfs.h>
#include <gconf/gconf-client.h>

#include "nautilus-burn-drive.h"
#include "nautilus-burn-drive-selection.h"
#include "make-iso.h"

#include "ncb-selection.h"
#include "ncb-selection-dialog.h"

static void     ncb_selection_dialog_class_init (NcbSelectionDialogClass *klass);
static void     ncb_selection_dialog_init       (NcbSelectionDialog      *fade);
static void     ncb_selection_dialog_finalize   (GObject                 *object);

#define NCB_SELECTION_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NCB_TYPE_SELECTION_DIALOG, NcbSelectionDialogPrivate))

#define MAX_ISO_NAME_LEN  32

struct NcbSelectionDialogPrivate
{
        GladeXML                *xml;
      NcbSelection            *selection;
        guint                    update_selection_idle_id;
};

G_DEFINE_TYPE (NcbSelectionDialog, ncb_selection_dialog, GTK_TYPE_DIALOG)

static void
ncb_selection_dialog_set_property (GObject            *object,
                                   guint               prop_id,
                                   const GValue       *value,
                                   GParamSpec         *pspec)
{
        switch (prop_id) {
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
        }
}

static void
ncb_selection_dialog_get_property (GObject            *object,
                                   guint               prop_id,
                                   GValue             *value,
                                   GParamSpec         *pspec)
{
        switch (prop_id) {
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
        }
}

static char *
size_to_string_text (guint64 bytes)
{
      guint64     t_bytes;
      const char *unit;
      char       *result;

      if (bytes > 1125899906842624ull) {
            t_bytes = (bytes * 10) / 1125899906842624ull;
            unit = "PiB";
      } else if (bytes > 1099511627776ull) {
            t_bytes = (bytes * 10) / 1099511627776ull;
            unit = "TiB";
      } else if (bytes > 1073741824ull) {
            t_bytes = (bytes * 10) / 1073741824ull;
            unit = "GiB";
      } else if (bytes > 1048576) {
            t_bytes = (bytes * 10) / 1048576;
            unit = "MiB";
      } else if (bytes > 1024) {
            t_bytes = (bytes * 10) / 1024;
            unit = "KiB";
      } else {
            t_bytes = bytes;
            unit = "B";
      }

      result = g_strdup_printf ("%" G_GUINT64_FORMAT ".%" G_GUINT64_FORMAT " %s", t_bytes / 10, t_bytes % 10, unit);

      return result;
}

static void
ncb_selection_dialog_set_size (NcbSelectionDialog *dialog,
                               guint64             size)
{
      GtkWidget *label;
      char      *str;

        g_return_if_fail (dialog != NULL);

      label = glade_xml_get_widget (dialog->priv->xml, "size_label");

      str = size_to_string_text (size);
      gtk_label_set_markup (GTK_LABEL (label), str);
      g_free (str);
}

static void
ncb_selection_dialog_set_label (NcbSelectionDialog *dialog,
                                const char         *label)
{
      NcbSelectionSource type;
      GtkWidget     *entry;
      gboolean       sensitive;

      entry = glade_xml_get_widget (dialog->priv->xml, "cdname_entry");

      if (label != NULL) {
            gtk_entry_set_text (GTK_ENTRY (entry), label);
      }

      ncb_selection_get_source (dialog->priv->selection, &type, NULL);
      sensitive = (type == NCB_SELECTION_SOURCE_BURN_FOLDER);

      gtk_editable_set_editable (GTK_EDITABLE (entry), sensitive);
      gtk_widget_set_sensitive (entry, sensitive);
}

static void
update_source (NcbSelectionDialog *dialog)
{
      char              *name;
        gboolean           is_copy;
      NcbSelectionSource type;

        is_copy = FALSE;
      ncb_selection_get_source (dialog->priv->selection, &type, &name);

      if (type == NCB_SELECTION_SOURCE_DEVICE) {
            is_copy = TRUE;
      }

        if (is_copy) {
                GtkWidget *widget;

            gtk_window_set_title (GTK_WINDOW (dialog), _("Copy Disc"));
            widget = glade_xml_get_widget (dialog->priv->xml, "target_label");
            gtk_label_set_text_with_mnemonic (GTK_LABEL (widget), _("Copy disc _to:"));
        } else {
            gtk_window_set_title (GTK_WINDOW (dialog), _("Write to Disc"));
      }
}

static void
update_source_size (NcbSelectionDialog *dialog)
{
        guint64            size;

      gtk_widget_set_sensitive (GTK_WIDGET (dialog), TRUE);
      gdk_window_set_cursor (GTK_WIDGET (dialog)->window, NULL);

      ncb_selection_get_size (dialog->priv->selection, &size);
      ncb_selection_dialog_set_size (dialog, size);
}

static void
update_label (NcbSelectionDialog *dialog)
{
      char              *label;

      ncb_selection_get_label (dialog->priv->selection, &label);
      ncb_selection_dialog_set_label (dialog, label);
}

static gboolean
update_dialog_selection (NcbSelectionDialog *dialog)
{
      update_source (dialog);
      update_source_size (dialog);
      update_label (dialog);

        dialog->priv->update_selection_idle_id = 0;

      return FALSE;
}

void
ncb_selection_dialog_set_selection (NcbSelectionDialog      *dialog,
                            NcbSelection            *selection)
{
        g_return_if_fail (dialog != NULL);

      if (dialog->priv->selection != NULL) {
            g_object_unref (dialog->priv->selection);
      }

      if (selection != NULL) {
            dialog->priv->selection = g_object_ref (selection);
      }

      /* FIXME: reconnect notify signals */

        if (dialog->priv->update_selection_idle_id > 0) {
                g_source_remove (dialog->priv->update_selection_idle_id);
        }
        dialog->priv->update_selection_idle_id = g_idle_add ((GSourceFunc)update_dialog_selection, dialog);
}

NcbSelection *
ncb_selection_dialog_get_selection (NcbSelectionDialog *dialog)
{
      g_return_val_if_fail (dialog != NULL, NULL);

      return g_object_ref (dialog->priv->selection);
}

static void
label_entry_insert_text (GtkEditable        *editable,
                   const char         *new_text,
                   int                 new_text_length,
                   int                *position,
                   NcbSelectionDialog *dialog)
{
      char *current_text;

      if (new_text_length < 0) {
            new_text_length = strlen (new_text);
      }

      current_text = gtk_editable_get_chars (editable, 0, -1);
      if (strlen (current_text) +  new_text_length >= MAX_ISO_NAME_LEN) {
            gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (editable)));
            g_signal_stop_emission_by_name (editable, "insert_text");
      }

      g_free (current_text);
}

static void
label_entry_changed (GtkEditable        *editable,
                 NcbSelectionDialog *dialog)
{
      char *text;

      /* sync with selection */
      text = gtk_editable_get_chars (editable, 0, -1);
      ncb_selection_set_label (dialog->priv->selection, text);
      g_free (text);
}

static void
ncb_selection_dialog_set_drive (NcbSelectionDialog *dialog,
                                NautilusBurnDrive  *drive)
{
      GtkWidget *selection;
      selection = glade_xml_get_widget (dialog->priv->xml, "target_optionmenu");

      nautilus_burn_drive_selection_set_active (NAUTILUS_BURN_DRIVE_SELECTION (selection), drive);
}

static void
ncb_selection_dialog_get_drive (NcbSelectionDialog *dialog,
                                NautilusBurnDrive **drive)
{
      GtkWidget *selection;

        if (drive != NULL) {
                *drive = NULL;
        }

      selection = glade_xml_get_widget (dialog->priv->xml, "target_optionmenu");

      if (! selection) {
            return;
      }

      /* the drive is reffed */
        if (drive != NULL) {
                *drive = nautilus_burn_drive_selection_get_active (NAUTILUS_BURN_DRIVE_SELECTION (selection));
        }
}

static void
ncb_selection_dialog_class_init (NcbSelectionDialogClass *klass)
{
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);

        object_class->finalize     = ncb_selection_dialog_finalize;
        object_class->get_property = ncb_selection_dialog_get_property;
        object_class->set_property = ncb_selection_dialog_set_property;

        g_type_class_add_private (klass, sizeof (NcbSelectionDialogPrivate));
}

static void
update_speeds_combobox (NautilusBurnDrive *drive,
                  GtkWidget     *combobox)
{
      const int         *write_speeds;
      int                i;
      GtkTreeModel            *model;
      GtkTreeIter        iter;
      NautilusBurnMediaType    type;
      gboolean           is_rewritable;
      gboolean           is_blank;
      int                      default_speed;
      int                      default_speed_index = 0;
        GConfClient             *gc;

      gc = gconf_client_get_default ();
      default_speed = gconf_client_get_int (gc, "/apps/nautilus-cd-burner/default_speed", NULL);
      g_object_unref (G_OBJECT (gc));

      model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));

      gtk_list_store_clear (GTK_LIST_STORE (model));

      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
                      0, _("Maximum possible"),
                      1, 0,
                      -1);

      write_speeds = nautilus_burn_drive_get_write_speeds (drive);
      type = nautilus_burn_drive_get_media_type_full (drive,
                                          &is_rewritable,
                                          &is_blank,
                                          NULL, NULL);

      for (i = 0; write_speeds[i] > 0; i++) {
            char *name;

            name = NULL;

            if (write_speeds[i] == default_speed) {
                  default_speed_index = i + 1;
            }

            if (is_rewritable || is_blank) {
                  switch (type) {
                  case NAUTILUS_BURN_MEDIA_TYPE_CDR:
                  case NAUTILUS_BURN_MEDIA_TYPE_CDRW:
                        name = g_strdup_printf ("%.1f\303\227",
                                          NAUTILUS_BURN_DRIVE_CD_SPEED (write_speeds[i]));
                        break;
                  case NAUTILUS_BURN_MEDIA_TYPE_DVDR:
                  case NAUTILUS_BURN_MEDIA_TYPE_DVDRW:
                  case NAUTILUS_BURN_MEDIA_TYPE_DVD_RAM:
                  case NAUTILUS_BURN_MEDIA_TYPE_DVD_PLUS_R:
                  case NAUTILUS_BURN_MEDIA_TYPE_DVD_PLUS_RW:
                  case NAUTILUS_BURN_MEDIA_TYPE_DVD_PLUS_R_DL:
                        name = g_strdup_printf ("%.1f\303\227",
                                          NAUTILUS_BURN_DRIVE_DVD_SPEED (write_speeds[i]));
                        break;
                  default:
                        break;
                  }

            } else {
                  name = g_strdup_printf ("CD: %.1f\303\227  DVD: %.1f\303\227",
                                    NAUTILUS_BURN_DRIVE_CD_SPEED (write_speeds[i]),
                                    NAUTILUS_BURN_DRIVE_DVD_SPEED (write_speeds[i]));
            }

            /* If we can't get the media type see if the drive is capable DVD */
            if (name == NULL) {
                  gboolean is_dvd;
                  int      type;

                  type = nautilus_burn_drive_get_drive_type (drive);

                  is_dvd = (type & NAUTILUS_BURN_DRIVE_TYPE_DVD_RW_RECORDER)
                        || (type & NAUTILUS_BURN_DRIVE_TYPE_DVD_RAM_RECORDER);
                  if (is_dvd) {
                        name = g_strdup_printf ("CD %.1f\303\227, DVD %.1f\303\227",
                                          NAUTILUS_BURN_DRIVE_CD_SPEED (write_speeds[i]),
                                          NAUTILUS_BURN_DRIVE_DVD_SPEED (write_speeds[i]));
                  } else {
                        name = g_strdup_printf ("%.1f\303\227",
                                          NAUTILUS_BURN_DRIVE_CD_SPEED (write_speeds[i]));
                  }
            }

            gtk_list_store_append (GTK_LIST_STORE (model), &iter);
            gtk_list_store_set (GTK_LIST_STORE (model), &iter,
                            0, name,
                            1, write_speeds [i],
                            -1);
            g_free (name);
      }

      /* Disable speed if no items in list */
      gtk_widget_set_sensitive (combobox, i > 0);

      gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), default_speed_index);
}

static void
dialog_media_added_cb (NautilusBurnDrive *drive,
                   gpointer           data)
{
      update_speeds_combobox (drive, GTK_WIDGET (data));
}

static void
refresh_dialog (NcbSelectionDialog *dialog)
{
      GtkWidget               *combobox;
      NautilusBurnDrive       *drive;
      GtkTreeModel            *model;

      /* Find active recorder: */
      ncb_selection_dialog_get_drive (dialog, &drive);

      /* add speed items: */
      combobox = glade_xml_get_widget (dialog->priv->xml, "speed_combobox");
      model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));

      g_signal_connect (drive, "media-added", G_CALLBACK (dialog_media_added_cb), combobox);

      if (drive) {
            int type;

            type = nautilus_burn_drive_get_drive_type (drive);

            if (type == NAUTILUS_BURN_DRIVE_TYPE_FILE) {
                  gtk_list_store_clear (GTK_LIST_STORE (model));
                  gtk_widget_set_sensitive (combobox, FALSE);
            } else {
                  update_speeds_combobox (drive, combobox);
            }

            nautilus_burn_drive_unref (drive);
      }
}

static void
setup_speed_combobox (GtkWidget *combobox)
{
      GtkCellRenderer *cell;
      GtkListStore    *store;

      store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);

      gtk_combo_box_set_model (GTK_COMBO_BOX (combobox),
                         GTK_TREE_MODEL (store));
        g_object_unref (store);

      cell = gtk_cell_renderer_text_new ();
      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), cell, TRUE);
      gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), cell,
                              "text", 0,
                              NULL);
}

static void
sync_drive_selection (NcbSelectionDialog *dialog)
{
      NautilusBurnDrive *drive;
      GtkWidget         *combobox;

      combobox = glade_xml_get_widget (dialog->priv->xml, "target_optionmenu");

      /* sync with selection */
      drive = nautilus_burn_drive_selection_get_active (NAUTILUS_BURN_DRIVE_SELECTION (combobox));
      ncb_selection_set_drive (dialog->priv->selection, drive);
      g_object_unref (drive);
}

static void
target_changed (NautilusBurnDriveSelection *drive_selection,
            const char                 *device_path,
                NcbSelectionDialog         *dialog)
{
      refresh_dialog (dialog);
      sync_drive_selection (dialog);
}

static void
ncb_selection_dialog_get_speed (NcbSelectionDialog *dialog,
                                int                *speed)
{
      GtkTreeModel *model;
      GtkTreeIter   iter;
        GtkWidget    *combobox;

        if (speed != NULL) {
                *speed = 0;
        }

        combobox = glade_xml_get_widget (dialog->priv->xml, "speed_combobox");
      if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &iter)) {
            return;
      }

      model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));
        gtk_tree_model_get (model, &iter, 1, speed, -1);
}

static void
speed_changed (GtkComboBox        *widget,
             NcbSelectionDialog *dialog)
{
      int speed;

      ncb_selection_dialog_get_speed (dialog, &speed);
      ncb_selection_set_speed (dialog->priv->selection, speed);
}

static void
init_dialog (NcbSelectionDialog *dialog)
{
      GtkWidget *label;
      GtkWidget *drive_combobox;
      GtkWidget *speed_combobox;
      GtkWidget *dummy_check;

      /* Fill in targets */
      drive_combobox = glade_xml_get_widget (dialog->priv->xml, "target_optionmenu");

      gtk_widget_show (drive_combobox);
      g_object_set (drive_combobox, "file-image", TRUE, NULL);
      g_object_set (drive_combobox, "show-recorders-only", TRUE, NULL);
      g_signal_connect (drive_combobox, "device-changed", G_CALLBACK (target_changed), dialog);

      speed_combobox = glade_xml_get_widget (dialog->priv->xml, "speed_combobox");
      g_signal_connect (speed_combobox, "changed", G_CALLBACK (speed_changed), dialog);
      setup_speed_combobox (speed_combobox);

      ncb_selection_dialog_set_label (dialog, "");

      label = glade_xml_get_widget (dialog->priv->xml, "size_label");
      gtk_label_set_markup (GTK_LABEL (label), _("Calculating..."));

      dummy_check = glade_xml_get_widget (dialog->priv->xml, "dummy_check");
        gtk_widget_hide (dummy_check);

      refresh_dialog (dialog);
      sync_drive_selection (dialog);
}

static void
selection_source_type_changed (NcbSelection       *selection,
                         GParamSpec         *pspec,
                         NcbSelectionDialog *dialog)
{
      update_source (dialog);
}

static void
selection_source_size_changed (NcbSelection       *selection,
                         GParamSpec         *pspec,
                         NcbSelectionDialog *dialog)
{
      update_source_size (dialog);
}

static void
selection_label_changed (NcbSelection       *selection,
                   GParamSpec         *pspec,
                   NcbSelectionDialog *dialog)
{
      update_label (dialog);
}

static void
selection_drive_changed (NcbSelection       *selection,
                   GParamSpec         *pspec,
                   NcbSelectionDialog *dialog)
{
      NautilusBurnDrive *drive;

      drive = ncb_selection_peek_drive (selection);
      ncb_selection_dialog_set_drive (dialog, drive);
}

static void
ncb_selection_dialog_init (NcbSelectionDialog *dialog)
{
        GtkWidget *vbox;
        GtkWidget *button;
        GtkWidget *entry;

        dialog->priv = NCB_SELECTION_DIALOG_GET_PRIVATE (dialog);

      dialog->priv->selection = ncb_selection_new ();
      g_signal_connect (dialog->priv->selection, "notify::source-type",
                    G_CALLBACK (selection_source_type_changed),
                    dialog);
      g_signal_connect (dialog->priv->selection, "notify::source-size",
                    G_CALLBACK (selection_source_size_changed),
                    dialog);
      g_signal_connect (dialog->priv->selection, "notify::drive",
                    G_CALLBACK (selection_drive_changed),
                    dialog);
      g_signal_connect (dialog->priv->selection, "notify::label",
                    G_CALLBACK (selection_label_changed),
                    dialog);

      dialog->priv->xml = glade_xml_new (DATADIR "/nautilus-cd-burner.glade", "selection_dialog_vbox", NULL);

        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);

      vbox = glade_xml_get_widget (dialog->priv->xml, "selection_dialog_vbox");
        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
                            vbox,
                            TRUE, TRUE, 0);
        gtk_widget_show_all (vbox);

      gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_HELP, GTK_RESPONSE_HELP);
      gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
      button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Write"), GTK_RESPONSE_OK);

      init_dialog (dialog);

      gtk_window_set_icon_name (GTK_WINDOW (dialog), "nautilus-cd-burner");

      /* make insensitive until fill_dialog finishes */
      gtk_widget_set_sensitive (GTK_WIDGET (dialog), FALSE);

      entry = glade_xml_get_widget (dialog->priv->xml, "cdname_entry");
      g_signal_connect (entry, "insert_text", G_CALLBACK (label_entry_insert_text), dialog);
      g_signal_connect (entry, "changed", G_CALLBACK (label_entry_changed), dialog);
}

static void
ncb_selection_dialog_finalize (GObject *object)
{
        NcbSelectionDialog *dialog;

        g_return_if_fail (object != NULL);
        g_return_if_fail (NCB_IS_SELECTION_DIALOG (object));

        dialog = NCB_SELECTION_DIALOG (object);

        g_return_if_fail (dialog->priv != NULL);

        G_OBJECT_CLASS (ncb_selection_dialog_parent_class)->finalize (object);
}

GtkWidget *
ncb_selection_dialog_new (void)
{
        GObject *object;

        object = g_object_new (NCB_TYPE_SELECTION_DIALOG, NULL);

        return GTK_WIDGET (object);
}

Generated by  Doxygen 1.6.0   Back to index