[Goodies-commits] r5211 - xfburn/trunk/xfburn

David Mohr squisher at xfce.org
Sat Aug 9 04:20:20 CEST 2008


Author: squisher
Date: 2008-08-09 02:20:20 +0000 (Sat, 09 Aug 2008)
New Revision: 5211

Added:
   xfburn/trunk/xfburn/xfburn-audio-composition.c
   xfburn/trunk/xfburn/xfburn-audio-composition.h
Log:
Using data-composition as base for audio-composition

Copied: xfburn/trunk/xfburn/xfburn-audio-composition.c (from rev 5210, xfburn/trunk/xfburn/xfburn-data-composition.c)
===================================================================
--- xfburn/trunk/xfburn/xfburn-audio-composition.c	                        (rev 0)
+++ xfburn/trunk/xfburn/xfburn-audio-composition.c	2008-08-09 02:20:20 UTC (rev 5211)
@@ -0,0 +1,2096 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2005-2006 Jean-François Wauthy (pollux at xfce.org)
+ *
+ * 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 Library 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.
+ */
+
+#ifdef	HAVE_CONFIG_H
+#include <config.h>
+#endif /* !HAVE_CONFIG_H */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#ifdef HAVE_THUNAR_VFS
+#include <thunar-vfs/thunar-vfs.h>
+#endif
+
+#include <exo/exo.h>
+
+#include <libisofs.h>
+
+#include "xfburn-data-composition.h"
+#include "xfburn-global.h"
+
+#include "xfburn-adding-progress.h"
+#include "xfburn-composition.h"
+#include "xfburn-burn-data-cd-composition-dialog.h"
+#include "xfburn-burn-data-dvd-composition-dialog.h"
+#include "xfburn-data-disc-usage.h"
+#include "xfburn-main-window.h"
+#include "xfburn-utils.h"
+
+#define XFBURN_DATA_COMPOSITION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFBURN_TYPE_DATA_COMPOSITION, XfburnDataCompositionPrivate))
+
+enum
+{
+  DATA_COMPOSITION_COLUMN_ICON,
+  DATA_COMPOSITION_COLUMN_CONTENT,
+  DATA_COMPOSITION_COLUMN_HUMANSIZE,
+  DATA_COMPOSITION_COLUMN_SIZE,
+  DATA_COMPOSITION_COLUMN_PATH,
+  DATA_COMPOSITION_COLUMN_TYPE,
+  DATA_COMPOSITION_N_COLUMNS
+};
+
+typedef enum
+{
+  DATA_COMPOSITION_TYPE_FILE,
+  DATA_COMPOSITION_TYPE_DIRECTORY
+} DataCompositionEntryType;
+
+
+/* thread parameters */
+typedef struct {
+  char **filenames;
+  int filec;
+  XfburnDataComposition *dc;
+} ThreadAddFilesCLIParams;
+
+typedef struct {
+  XfburnDataComposition *dc;
+  GtkTreeModel *model;
+  GtkTreeIter iter_where_insert;
+  DataCompositionEntryType type;
+} ThreadAddFilesActionParams;
+
+typedef struct {
+  XfburnDataComposition *composition;
+  DataCompositionEntryType type;
+  GtkWidget *widget;
+  GtkTreeViewDropPosition position;
+  GtkTreeIter iter_dummy;
+} ThreadAddFilesDragParams;
+
+/* prototypes */
+static void xfburn_data_composition_class_init (XfburnDataCompositionClass *);
+static void composition_interface_init (XfburnCompositionInterface *composition, gpointer iface_data);
+static void xfburn_data_composition_init (XfburnDataComposition *dc);
+static void xfburn_data_composition_finalize (GObject * object);
+
+static void show_custom_controls (XfburnComposition *composition);
+static void hide_custom_controls (XfburnComposition *composition);
+static void load_from_file (XfburnComposition *composition, const gchar *file);
+static void save_to_file (XfburnComposition *composition);
+
+static gint directory_tree_sortfunc (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data);
+
+static void action_create_directory (GtkAction *, XfburnDataComposition *);
+static void action_clear (GtkAction *, XfburnDataComposition *);
+static void action_remove_selection (GtkAction *, XfburnDataComposition *);
+static void action_rename_selection (GtkAction *, XfburnDataComposition *);
+static void action_add_selected_files (GtkAction *, XfburnDataComposition *);
+
+static gboolean cb_treeview_button_pressed (GtkTreeView * treeview, GdkEventButton * event, XfburnDataComposition * dc);
+static void cb_treeview_row_activated (GtkTreeView * treeview, GtkTreePath * path, GtkTreeViewColumn * column, XfburnDataComposition * composition);
+static void cb_selection_changed (GtkTreeSelection *selection, XfburnDataComposition * dc);
+static void cb_begin_burn (XfburnDataDiscUsage * du, XfburnDataComposition * dc);
+static void cb_cell_file_edited (GtkCellRenderer * renderer, gchar * path, gchar * newtext, XfburnDataComposition * dc);
+
+static void cb_content_drag_data_rcv (GtkWidget * widget, GdkDragContext * dc, guint x, guint y, GtkSelectionData * sd,
+                                      guint info, guint t, XfburnDataComposition * composition);
+static void cb_content_drag_data_get (GtkWidget * widget, GdkDragContext * dc, GtkSelectionData * data, guint info,
+                                      guint time, XfburnDataComposition * content);
+static void cb_adding_done (XfburnAddingProgress *progress, XfburnDataComposition *dc);
+
+/* thread entry points */
+static void thread_add_files_cli (ThreadAddFilesCLIParams *params);
+static void thread_add_files_action (ThreadAddFilesActionParams *params);
+static void thread_add_files_drag (ThreadAddFilesDragParams *params);
+
+/* thread helpers */
+static gboolean thread_add_file_to_list_with_name (const gchar *name, XfburnDataComposition * dc, 
+                                                   GtkTreeModel * model, const gchar * path, GtkTreeIter * iter, 
+                                                   GtkTreeIter * insertion, GtkTreeViewDropPosition position);
+static gboolean thread_add_file_to_list (XfburnDataComposition * dc, GtkTreeModel * model, const gchar * path, 
+                                         GtkTreeIter * iter, GtkTreeIter * insertion, GtkTreeViewDropPosition position);
+static IsoImage * generate_iso_image (XfburnDataComposition * dc);
+                                  
+typedef struct
+{
+  gchar *filename;
+  gboolean modified;
+ 
+  guint n_new_directory;
+
+  GList *full_paths_to_add;
+  gchar *selected_files;
+  GtkTreePath *path_where_insert;
+
+  GdkDragContext * dc;
+  gboolean success;
+  gboolean del;
+  guint32 time;
+
+  void *thread_params;
+  
+  GtkActionGroup *action_group;
+  GtkUIManager *ui_manager;
+
+  GtkWidget *toolbar;
+  GtkWidget *entry_volume_name;
+  GtkWidget *content;
+  GtkWidget *disc_usage;
+  GtkWidget *progress;
+
+} XfburnDataCompositionPrivate;
+
+/* globals */
+static GtkHPanedClass *parent_class = NULL;
+static guint instances = 0;
+
+static const GtkActionEntry action_entries[] = {
+  {"add-file", GTK_STOCK_ADD, N_("Add"), NULL, N_("Add the selected file(s) to the composition"),
+   G_CALLBACK (action_add_selected_files),},
+  {"create-dir", GTK_STOCK_NEW, N_("Create directory"), NULL, N_("Add a new directory to the composition"),
+   G_CALLBACK (action_create_directory),},
+  {"remove-file", GTK_STOCK_REMOVE, N_("Remove"), NULL, N_("Remove the selected file(s) from the composition"),
+   G_CALLBACK (action_remove_selection),},
+  {"clear", GTK_STOCK_CLEAR, N_("Clear"), NULL, N_("Clear the content of the composition"),
+   G_CALLBACK (action_clear),},
+  {"import-session", "xfburn-import-session", N_("Import"), NULL, N_("Import existing session"),},
+  {"rename-file", GTK_STOCK_EDIT, N_("Rename"), NULL, N_("Rename the selected file"),
+   G_CALLBACK (action_rename_selection),},
+};
+
+static const gchar *toolbar_actions[] = {
+  "add-file",
+  "remove-file",
+  "create-dir",
+  "clear",
+  "import-session",
+};
+
+static GdkPixbuf *icon_directory = NULL, *icon_file = NULL;
+
+/***************************/
+/* XfburnDataComposition class */
+/***************************/
+GtkType
+xfburn_data_composition_get_type (void)
+{
+  static GtkType data_composition_type = 0;
+
+  if (!data_composition_type) {
+    static const GTypeInfo data_composition_info = {
+      sizeof (XfburnDataCompositionClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) xfburn_data_composition_class_init,
+      NULL,
+      NULL,
+      sizeof (XfburnDataComposition),
+      0,
+      (GInstanceInitFunc) xfburn_data_composition_init
+    };
+
+    static const GInterfaceInfo composition_info = {
+      (GInterfaceInitFunc) composition_interface_init,    /* interface_init */
+      NULL,                                               /* interface_finalize */
+      NULL                                                /* interface_data */
+    };
+    
+    data_composition_type = g_type_register_static (GTK_TYPE_VBOX, "XfburnDataComposition", &data_composition_info, 0);
+    
+    g_type_add_interface_static (data_composition_type, XFBURN_TYPE_COMPOSITION, &composition_info);
+  }
+
+  return data_composition_type;
+}
+
+static void
+xfburn_data_composition_class_init (XfburnDataCompositionClass * klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (XfburnDataCompositionPrivate));
+  
+  parent_class = g_type_class_peek_parent (klass);
+  
+  object_class->finalize = xfburn_data_composition_finalize;
+}
+
+static void
+composition_interface_init (XfburnCompositionInterface *composition, gpointer iface_data)
+{
+  composition->show_custom_controls = show_custom_controls;
+  composition->hide_custom_controls = hide_custom_controls;
+  composition->load = load_from_file;
+  composition->save = save_to_file;
+}
+
+static void
+xfburn_data_composition_init (XfburnDataComposition * composition)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+  
+  gint x, y;
+  ExoToolbarsModel *model_toolbar;
+  gint toolbar_position;
+  GtkWidget *hbox_toolbar;
+  GtkWidget *hbox, *label;
+  GtkWidget *scrolled_window;
+  GtkTreeStore *model;
+  GtkTreeViewColumn *column_file;
+  GtkCellRenderer *cell_icon, *cell_file;
+  GtkTreeSelection *selection;
+  GtkAction *action = NULL;
+  GdkScreen *screen;
+  GtkIconTheme *icon_theme;
+  
+  const gchar ui_string[] = "<ui> <popup name=\"popup-menu\">"
+    "<menuitem action=\"create-dir\"/>" "<separator/>"
+    "<menuitem action=\"rename-file\"/>" "<menuitem action=\"remove-file\"/>" "</popup></ui>";
+
+  GtkTargetEntry gte_src[] =  { { "XFBURN_TREE_PATHS", GTK_TARGET_SAME_WIDGET, DATA_COMPOSITION_DND_TARGET_INSIDE } };
+  GtkTargetEntry gte_dest[] = { { "XFBURN_TREE_PATHS", GTK_TARGET_SAME_WIDGET, DATA_COMPOSITION_DND_TARGET_INSIDE },
+                                { "text/plain", 0, DATA_COMPOSITION_DND_TARGET_TEXT_PLAIN },
+                                { "text/uri-list", 0, DATA_COMPOSITION_DND_TARGET_TEXT_URI_LIST },
+                              };
+
+  priv->full_paths_to_add = NULL;
+
+  instances++;
+  
+  /* initialize static members */
+  screen = gtk_widget_get_screen (GTK_WIDGET (composition));
+  icon_theme = gtk_icon_theme_get_for_screen (screen);
+
+  gtk_icon_size_lookup (GTK_ICON_SIZE_SMALL_TOOLBAR, &x, &y);
+  if (!icon_directory)
+    icon_directory = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory", x, 0, NULL);
+  if (!icon_file)
+    icon_file = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-regular", x, 0, NULL);
+
+  /* create ui manager */
+  priv->action_group = gtk_action_group_new ("xfburn-data-composition");
+  gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
+  gtk_action_group_add_actions (priv->action_group, action_entries, G_N_ELEMENTS (action_entries),
+                                GTK_WIDGET (composition));
+
+  priv->ui_manager = gtk_ui_manager_new ();
+  gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0);
+
+  gtk_ui_manager_add_ui_from_string (priv->ui_manager, ui_string, -1, NULL);
+
+  hbox_toolbar = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (composition), hbox_toolbar, FALSE, TRUE, 0);
+  gtk_widget_show (hbox_toolbar);
+  
+  /* toolbar */
+  model_toolbar = exo_toolbars_model_new ();
+  exo_toolbars_model_set_actions (model_toolbar, (gchar **) toolbar_actions, G_N_ELEMENTS (toolbar_actions));
+  toolbar_position = exo_toolbars_model_add_toolbar (model_toolbar, -1, "content-toolbar");
+  exo_toolbars_model_set_style (model_toolbar, GTK_TOOLBAR_BOTH, toolbar_position);
+
+  exo_toolbars_model_add_item (model_toolbar, toolbar_position, -1, "add-file", EXO_TOOLBARS_ITEM_TYPE);
+  exo_toolbars_model_add_item (model_toolbar, toolbar_position, -1, "create-dir", EXO_TOOLBARS_ITEM_TYPE);
+  exo_toolbars_model_add_separator (model_toolbar, toolbar_position, -1);
+  exo_toolbars_model_add_item (model_toolbar, toolbar_position, -1, "remove-file", EXO_TOOLBARS_ITEM_TYPE);
+  exo_toolbars_model_add_item (model_toolbar, toolbar_position, -1, "clear", EXO_TOOLBARS_ITEM_TYPE);
+  //exo_toolbars_model_add_separator (model_toolbar, toolbar_position, -1);
+  //exo_toolbars_model_add_item (model_toolbar, toolbar_position, -1, "import-session", EXO_TOOLBARS_ITEM_TYPE);
+
+  priv->toolbar = exo_toolbars_view_new_with_model (priv->ui_manager, model_toolbar);
+  gtk_box_pack_start (GTK_BOX (hbox_toolbar), priv->toolbar, TRUE, TRUE, 0);
+  gtk_widget_show (priv->toolbar);
+
+    
+  /* volume name */
+  hbox = gtk_hbox_new (FALSE, 5);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
+  gtk_box_pack_start (GTK_BOX (hbox_toolbar), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+  
+  label = gtk_label_new (_("Volume name :"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+  
+  priv->entry_volume_name = gtk_entry_new ();
+  gtk_entry_set_text (GTK_ENTRY (priv->entry_volume_name), _(DATA_COMPOSITION_DEFAULT_NAME));
+  gtk_box_pack_start (GTK_BOX (hbox), priv->entry_volume_name, FALSE, FALSE, 0);
+  gtk_widget_show (priv->entry_volume_name);
+  
+  /* content treeview */
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
+  gtk_widget_show (scrolled_window);
+  gtk_box_pack_start (GTK_BOX (composition), scrolled_window, TRUE, TRUE, 0);
+
+  priv->content = exo_tree_view_new ();
+  model = gtk_tree_store_new (DATA_COMPOSITION_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
+                              G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_UINT);
+							  
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model), DATA_COMPOSITION_COLUMN_CONTENT,
+                                   directory_tree_sortfunc, NULL, NULL);
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), DATA_COMPOSITION_COLUMN_CONTENT, GTK_SORT_ASCENDING);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (priv->content), GTK_TREE_MODEL (model));
+  gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (priv->content), TRUE);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->content));
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+  gtk_widget_show (priv->content);
+  gtk_container_add (GTK_CONTAINER (scrolled_window), priv->content);
+
+  column_file = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (column_file, _("Contents"));
+
+  cell_icon = gtk_cell_renderer_pixbuf_new ();
+  gtk_tree_view_column_pack_start (column_file, cell_icon, FALSE);
+  gtk_tree_view_column_set_attributes (column_file, cell_icon, "pixbuf", DATA_COMPOSITION_COLUMN_ICON, NULL);
+  g_object_set (cell_icon, "xalign", 0.0, "ypad", 0, NULL);
+
+  cell_file = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column_file, cell_file, TRUE);
+  gtk_tree_view_column_set_attributes (column_file, cell_file, "text", DATA_COMPOSITION_COLUMN_CONTENT, NULL);
+  g_signal_connect (G_OBJECT (cell_file), "edited", G_CALLBACK (cb_cell_file_edited), composition);
+  g_object_set (G_OBJECT (cell_file), "editable", TRUE, NULL);
+
+  gtk_tree_view_append_column (GTK_TREE_VIEW (priv->content), column_file);
+
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->content), -1, _("Size"),
+                                               gtk_cell_renderer_text_new (), "text", DATA_COMPOSITION_COLUMN_HUMANSIZE,
+                                               NULL);
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->content), -1, _("Local Path"),
+                                               gtk_cell_renderer_text_new (), "text", DATA_COMPOSITION_COLUMN_PATH, NULL);
+
+  /* Contents column */
+  gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), 0), 1);
+  gtk_tree_view_column_set_min_width (gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), 0), 200);
+  /* Size (HUMANSIZE) column */
+  gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), 1), 1);
+  gtk_tree_view_column_set_min_width (gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), 1), 60);
+  /* Local Path (PATH) column */
+  gtk_tree_view_column_set_resizable (gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), 2), 1);
+
+
+  g_signal_connect (G_OBJECT (priv->content), "row-activated", G_CALLBACK (cb_treeview_row_activated), composition);
+  g_signal_connect (G_OBJECT (priv->content), "button-press-event",
+                    G_CALLBACK (cb_treeview_button_pressed), composition);
+  g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (cb_selection_changed), composition);
+                    
+  /* adding progress window */
+  priv->progress = GTK_WIDGET (xfburn_adding_progress_new ()); 
+  g_signal_connect (G_OBJECT (priv->progress), "adding-done", G_CALLBACK (cb_adding_done), composition);
+  gtk_window_set_transient_for (GTK_WINDOW (priv->progress), GTK_WINDOW (xfburn_main_window_get_instance ()));
+  /* FIXME: progress should have a busy cursor */
+
+  /* disc usage */
+  priv->disc_usage = xfburn_data_disc_usage_new ();
+  gtk_box_pack_start (GTK_BOX (composition), priv->disc_usage, FALSE, FALSE, 5);
+  gtk_widget_show (priv->disc_usage);
+  g_signal_connect (G_OBJECT (priv->disc_usage), "begin-burn", G_CALLBACK (cb_begin_burn), composition);
+
+  /* set up DnD */
+  gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->content), GDK_BUTTON1_MASK, gte_src,
+                                          G_N_ELEMENTS (gte_src), GDK_ACTION_COPY | GDK_ACTION_MOVE);
+  g_signal_connect (G_OBJECT (priv->content), "drag-data-get", G_CALLBACK (cb_content_drag_data_get),
+                    composition);
+  gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (priv->content), gte_dest, G_N_ELEMENTS (gte_dest),
+                                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
+  g_signal_connect (G_OBJECT (priv->content), "drag-data-received", G_CALLBACK (cb_content_drag_data_rcv),
+                    composition);
+                    
+  action = gtk_action_group_get_action (priv->action_group, "remove-file");
+  gtk_action_set_sensitive (GTK_ACTION (action), FALSE);
+}
+
+static void
+xfburn_data_composition_finalize (GObject * object)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (object);
+  
+  g_free (priv->filename);
+  
+  /* free static members */
+  instances--;
+  if (instances == 0) {
+    if (icon_directory) {
+      g_object_unref (icon_directory);
+      icon_directory = NULL;
+    }
+    if (icon_file) {
+      g_object_unref (icon_file);
+      icon_file = NULL;
+    }
+  }
+  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/*************/
+/* internals */
+/*************/
+static void
+show_custom_controls (XfburnComposition *composition)
+{
+  DBG ("show");
+}
+
+static void
+hide_custom_controls (XfburnComposition *composition)
+{
+  DBG ("hide");
+}
+
+static void
+cb_begin_burn (XfburnDataDiscUsage * du, XfburnDataComposition * dc)
+{
+  XfburnMainWindow *mainwin = xfburn_main_window_get_instance ();
+  GtkWidget *dialog = NULL;
+  IsoImage *image = NULL;
+
+  if (!iso_init()) {
+    g_critical ("Could not initialize libisofs!");
+    return;
+  }
+
+  image = generate_iso_image (XFBURN_DATA_COMPOSITION (dc));
+  
+  switch (xfburn_data_disc_usage_get_disc_type (du)) {
+  case CD_DISC:
+    dialog = xfburn_burn_data_cd_composition_dialog_new (image);
+    break;
+  case DVD_DISC:
+    dialog = xfburn_burn_data_dvd_composition_dialog_new (image);
+    break;
+  }
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (mainwin));
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+}
+
+static void
+cb_treeview_row_activated (GtkTreeView * treeview, GtkTreePath * path, GtkTreeViewColumn * column,
+                         XfburnDataComposition * composition)
+{
+  gtk_tree_view_expand_row (treeview, path, FALSE);
+}
+
+static void
+cb_selection_changed (GtkTreeSelection *selection, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  gint n_selected_rows;
+  GtkAction *action = NULL;
+  
+  
+  n_selected_rows = gtk_tree_selection_count_selected_rows (selection);
+  if (n_selected_rows == 0) {
+    action = gtk_action_group_get_action (priv->action_group, "add-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);
+    action = gtk_action_group_get_action (priv->action_group, "create-dir");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);  
+    action = gtk_action_group_get_action (priv->action_group, "remove-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), FALSE);  
+  } else if (n_selected_rows == 1) {
+    action = gtk_action_group_get_action (priv->action_group, "add-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);
+    action = gtk_action_group_get_action (priv->action_group, "create-dir");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);  
+    action = gtk_action_group_get_action (priv->action_group, "remove-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);
+  } else {
+    action = gtk_action_group_get_action (priv->action_group, "add-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), FALSE);
+    action = gtk_action_group_get_action (priv->action_group, "create-dir");
+    gtk_action_set_sensitive (GTK_ACTION (action), FALSE);  
+    action = gtk_action_group_get_action (priv->action_group, "remove-file");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);     
+  }
+}
+
+static gboolean
+cb_treeview_button_pressed (GtkTreeView * treeview, GdkEventButton * event, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  if ((event->button == 1) && (event->type == GDK_BUTTON_PRESS)) {
+    GtkTreePath *path;
+    
+    if (gtk_tree_view_get_path_at_pos (treeview, event->x, event->y, &path, NULL, NULL, NULL)) {
+      gtk_tree_path_free (path);
+    } else {
+      GtkTreeSelection *selection;
+
+      selection = gtk_tree_view_get_selection (treeview);
+      gtk_tree_selection_unselect_all (selection);
+    }
+    
+    return FALSE;
+  }
+  
+  if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) {
+    GtkTreeSelection *selection;
+    GtkTreePath *path;
+    GtkWidget *menu_popup;
+    GtkWidget *menuitem_remove;
+    GtkWidget *menuitem_rename;
+
+    selection = gtk_tree_view_get_selection (treeview);
+
+    if (gtk_tree_view_get_path_at_pos (treeview, event->x, event->y, &path, NULL, NULL, NULL)) {
+      gtk_tree_selection_unselect_all (selection);
+      gtk_tree_selection_select_path (selection, path);
+      gtk_tree_path_free (path);
+    }
+
+    menu_popup = gtk_ui_manager_get_widget (priv->ui_manager, "/popup-menu");
+    menuitem_remove = gtk_ui_manager_get_widget (priv->ui_manager, "/popup-menu/remove-file");
+    menuitem_rename = gtk_ui_manager_get_widget (priv->ui_manager, "/popup-menu/rename-file");
+
+    if (gtk_tree_selection_count_selected_rows (selection) >= 1)
+      gtk_widget_set_sensitive (menuitem_remove, TRUE);
+    else
+      gtk_widget_set_sensitive (menuitem_remove, FALSE);
+    if (gtk_tree_selection_count_selected_rows (selection) == 1)
+      gtk_widget_set_sensitive (menuitem_rename, TRUE);
+    else
+      gtk_widget_set_sensitive (menuitem_rename, FALSE);
+
+    gtk_menu_popup (GTK_MENU (menu_popup), NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time ());
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static gint
+directory_tree_sortfunc (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data)
+{
+  /* adapted from gnomebaker */
+  gchar *aname, *bname;
+  DataCompositionEntryType atype = -1, btype = -1;
+  gint result = 0;
+
+  gtk_tree_model_get (model, a, DATA_COMPOSITION_COLUMN_CONTENT, &aname, DATA_COMPOSITION_COLUMN_TYPE, &atype, -1);
+  gtk_tree_model_get (model, b, DATA_COMPOSITION_COLUMN_CONTENT, &bname, DATA_COMPOSITION_COLUMN_TYPE, &btype, -1);
+
+  if ( (atype == DATA_COMPOSITION_TYPE_DIRECTORY) && (btype != DATA_COMPOSITION_TYPE_DIRECTORY) )
+    result = -1;
+  else if ( (atype != DATA_COMPOSITION_TYPE_DIRECTORY) && (btype == DATA_COMPOSITION_TYPE_DIRECTORY) )
+    result = 1;
+  else
+    result = g_ascii_strcasecmp (aname, bname);
+
+  g_free (aname);
+  g_free (bname);
+
+  return result;
+}
+
+static gboolean
+file_exists_on_same_level (GtkTreeModel * model, GtkTreePath * path, gboolean skip_path, const gchar *filename)
+{
+  GtkTreePath *current_path = NULL;
+  GtkTreeIter current_iter;
+  
+  current_path = gtk_tree_path_copy (path);
+  for (;gtk_tree_path_prev (current_path););
+   
+  if (gtk_tree_model_get_iter (model, &current_iter, current_path)) {
+    do {
+      gchar *current_filename = NULL;
+      
+      if (skip_path && gtk_tree_path_compare (path, current_path) == 0) {
+        gtk_tree_path_next (current_path);
+        continue;
+      }
+
+      gtk_tree_model_get (model, &current_iter, DATA_COMPOSITION_COLUMN_CONTENT, &current_filename, -1);
+      if (strcmp (current_filename, filename) == 0) {
+        g_free (current_filename);
+        gtk_tree_path_free (current_path);
+        return TRUE;
+      }
+      
+      g_free (current_filename);
+      gtk_tree_path_next (current_path);
+    } while (gtk_tree_model_iter_next (model, &current_iter));
+  }
+  
+  gtk_tree_path_free (current_path);
+  return FALSE;
+}
+
+static void
+cb_cell_file_edited (GtkCellRenderer * renderer, gchar * path, gchar * newtext, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreePath *real_path;
+
+  if (strlen (newtext) == 0) {
+    xfce_err (_("You must give a name to the file"));
+    return;
+  }
+    
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  real_path = gtk_tree_path_new_from_string (path);
+
+  if (gtk_tree_model_get_iter (model, &iter, real_path)) {
+    if (file_exists_on_same_level (model, real_path, TRUE, newtext)) {
+      xfce_err (_("A file with the same name is already present in the composition"));
+    }
+    else {
+      gtk_tree_store_set (GTK_TREE_STORE (model), &iter, DATA_COMPOSITION_COLUMN_CONTENT, newtext, -1);
+    }
+  }
+
+  gtk_tree_path_free (real_path);
+}
+
+static void
+cb_adding_done (XfburnAddingProgress *progress, XfburnDataComposition *dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+
+  gtk_widget_hide (priv->progress);
+
+  if (priv->selected_files) {
+    g_free (priv->selected_files);
+    priv->selected_files = NULL;
+  }
+
+  if (priv->path_where_insert) {
+    gtk_tree_path_free (priv->path_where_insert);
+    priv->path_where_insert = NULL;
+  }
+
+  if (priv->full_paths_to_add) {
+    g_list_foreach (priv->full_paths_to_add, (GFunc) g_free, NULL);
+    g_list_free (priv->full_paths_to_add);
+    priv->full_paths_to_add = NULL;
+  }
+
+  g_free (priv->thread_params);
+  xfburn_default_cursor (priv->content);
+}
+
+static void
+action_rename_selection (GtkAction * action, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GList *list;
+  GtkTreePath *path;
+  GtkTreeViewColumn *column;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->content));
+  list = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  path = (GtkTreePath *) list->data;
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), DATA_COMPOSITION_COLUMN_CONTENT - 1);
+  /* -1 because of COLUMN_ICON */
+  
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->content), path, column, TRUE);
+
+  gtk_tree_path_free (path);
+  g_list_free (list);
+}
+
+static void
+action_create_directory (GtkAction * action, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  GList *selected_paths = NULL;
+  GtkTreePath *path_where_insert = NULL;
+  GtkTreeIter iter_where_insert, iter_directory;
+  DataCompositionEntryType type = -1;
+  gchar *humansize = NULL;
+  
+  GtkTreePath *inserted_path = NULL;
+  gchar *directory_text = NULL;
+  
+  GtkTreeViewColumn *column;
+  GtkTreePath *path = NULL;
+  
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->content));
+  selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL);
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+    
+  if (selected_paths) {
+    path_where_insert = (GtkTreePath *) (selected_paths->data);
+
+    gtk_tree_model_get_iter (model, &iter_where_insert, path_where_insert);
+    gtk_tree_model_get (model, &iter_where_insert, DATA_COMPOSITION_COLUMN_TYPE, &type, -1);
+  }
+  
+  if (type == DATA_COMPOSITION_TYPE_DIRECTORY) {
+    gtk_tree_store_append (GTK_TREE_STORE (model), &iter_directory, &iter_where_insert);
+    gtk_tree_view_expand_row (GTK_TREE_VIEW (priv->content), path_where_insert, FALSE);
+  } else if (type == DATA_COMPOSITION_TYPE_FILE) {
+    GtkTreeIter parent;
+        
+    if (gtk_tree_model_iter_parent (model, &parent, &iter_where_insert))
+      gtk_tree_store_append (GTK_TREE_STORE (model), &iter_directory, &parent);
+    else
+      gtk_tree_store_append (GTK_TREE_STORE (model), &iter_directory, NULL);
+  } else {
+    gtk_tree_store_append (GTK_TREE_STORE (model), &iter_directory, NULL);
+  }
+  
+  humansize = xfburn_humanreadable_filesize (4);
+  
+  inserted_path = gtk_tree_model_get_path (model, &iter_directory);
+  if (file_exists_on_same_level (model, inserted_path, TRUE, _("New directory")))
+    directory_text = g_strdup_printf ("%s %d", _("New directory"), ++(priv->n_new_directory));
+  else
+    directory_text = g_strdup (_("New directory"));
+  gtk_tree_path_free (inserted_path);
+  
+  gtk_tree_store_set (GTK_TREE_STORE (model), &iter_directory,
+                      DATA_COMPOSITION_COLUMN_ICON, icon_directory,                     
+                      DATA_COMPOSITION_COLUMN_CONTENT, directory_text,
+                      DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                      DATA_COMPOSITION_COLUMN_SIZE, (guint64) 4,
+                      DATA_COMPOSITION_COLUMN_TYPE, DATA_COMPOSITION_TYPE_DIRECTORY, -1);
+  g_free (directory_text);
+  g_free (humansize);
+  
+  xfburn_data_disc_usage_add_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), 4);
+  
+  gtk_widget_realize (priv->content);
+  
+  /* put the cell renderer in edition mode */
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->content), DATA_COMPOSITION_COLUMN_CONTENT - 1);
+  /* -1 because of COLUMN_ICON */
+  path = gtk_tree_model_get_path (model, &iter_directory);
+  
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->content), path, column, TRUE);
+  gtk_tree_path_free (path);
+}
+
+static void
+remove_row_reference (GtkTreeRowReference *reference, XfburnDataCompositionPrivate *priv)
+{
+  GtkTreePath *path = NULL;
+  GtkTreeModel *model;
+  
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  
+  path = gtk_tree_row_reference_get_path (reference);
+  if (path) {
+    GtkTreeIter iter;
+    
+    if (gtk_tree_model_get_iter (model, &iter, path)) {
+      GtkTreeIter parent, iter_temp;
+      guint64 size = 0;
+      
+      gtk_tree_model_get (model, &iter, DATA_COMPOSITION_COLUMN_SIZE, &size, -1);
+      xfburn_data_disc_usage_sub_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), size);
+
+      iter_temp = iter;
+      while (gtk_tree_model_iter_parent (model, &parent, &iter_temp)) {
+        guint64 old_size;
+        gchar *humansize = NULL;
+
+        /* updates parent directories size */
+        gtk_tree_model_get (model, &parent, DATA_COMPOSITION_COLUMN_SIZE, &old_size, -1);
+
+        humansize = xfburn_humanreadable_filesize (old_size - size);
+        gtk_tree_store_set (GTK_TREE_STORE (model), &parent, 
+                            DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                            DATA_COMPOSITION_COLUMN_SIZE, old_size - size, -1);
+
+        iter_temp = parent;
+
+        g_free (humansize);
+      }
+      
+      gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+    }
+    
+    gtk_tree_path_free (path);
+  }
+  
+  gtk_tree_row_reference_free (reference);
+}
+
+static void
+action_remove_selection (GtkAction * action, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GList *list_paths = NULL, *el;
+  GList *references = NULL;
+  
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->content));
+  list_paths = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  el = list_paths;
+  while (el) {
+    GtkTreePath *path = NULL;
+    GtkTreeRowReference *reference = NULL;
+  
+    path = (GtkTreePath *) el->data;
+    reference = gtk_tree_row_reference_new (model, path);
+    gtk_tree_path_free (path);
+  
+    if (reference)
+      references = g_list_prepend (references, reference);
+    
+    el = g_list_next (el);
+  } 
+  g_list_free (list_paths);
+  
+  g_list_foreach (references, (GFunc) remove_row_reference, priv);
+  g_list_free (references);
+}
+
+
+static void
+action_add_selected_files (GtkAction *action, XfburnDataComposition *dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  XfburnFileBrowser *browser = xfburn_main_window_get_file_browser (xfburn_main_window_get_instance ());
+  
+  gchar *selected_files = NULL;
+  
+  xfburn_busy_cursor (priv->content);
+  selected_files = xfburn_file_browser_get_selection (browser);
+  
+  if (selected_files) {
+    GtkTreeSelection *selection;
+    GList *selected_paths = NULL;
+    ThreadAddFilesActionParams *params;
+
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
+
+    params = g_new (ThreadAddFilesActionParams, 1);
+    params->dc = dc;
+    params->type = -1;
+    priv->path_where_insert = NULL;
+    
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->content));
+    selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL);
+    params->model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+    
+    if (selected_paths) {
+      priv->path_where_insert = (GtkTreePath *) (selected_paths->data);
+
+      gtk_tree_model_get_iter (params->model, &params->iter_where_insert, priv->path_where_insert);
+      gtk_tree_model_get (params->model, &params->iter_where_insert, DATA_COMPOSITION_COLUMN_TYPE, &params->type, -1);
+    }
+    
+    priv->selected_files = selected_files;
+
+    priv->thread_params = params;
+    g_thread_create ((GThreadFunc) thread_add_files_action, params, FALSE, NULL);
+    
+    g_list_foreach (selected_paths, (GFunc) gtk_tree_path_free, NULL);
+    g_list_free (selected_paths);
+  }
+}
+
+static void
+action_clear (GtkAction * action, XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  GtkTreeModel *model;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  gtk_tree_store_clear (GTK_TREE_STORE (model));
+  
+  gtk_entry_set_text (GTK_ENTRY (priv->entry_volume_name), _(DATA_COMPOSITION_DEFAULT_NAME));
+
+  xfburn_data_disc_usage_set_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), 0);
+}
+
+static void
+cb_content_drag_data_get (GtkWidget * widget, GdkDragContext * dc,
+                          GtkSelectionData * data, guint info, guint time, XfburnDataComposition * content)
+{
+  if (info == DATA_COMPOSITION_DND_TARGET_INSIDE) {
+    GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+    GtkTreeModel *model;
+    GList *selected_rows = NULL, *row = NULL;
+    GList *references = NULL;
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+    row = selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+    while (row) {
+      GtkTreeRowReference *reference = NULL;
+      GtkTreePath *temp;
+
+      temp = (GtkTreePath *) row->data;
+      reference = gtk_tree_row_reference_new (model, temp);
+      gtk_tree_path_free (temp);
+
+      references = g_list_prepend (references, reference);
+      
+      row = g_list_next (row);
+    }
+
+    g_list_free (selected_rows);
+
+    gtk_selection_data_set (data, gdk_atom_intern ("XFBURN_TREE_PATHS", FALSE), 8, (const guchar *) &references,
+                            sizeof (GList **));
+  }
+}
+
+static void
+set_modified (XfburnDataCompositionPrivate *priv)
+{
+  if (!(priv->modified)) {
+    XfburnMainWindow *mainwin;
+    GtkUIManager *ui_manager;
+    GtkActionGroup *action_group;
+  
+    mainwin = xfburn_main_window_get_instance ();
+    ui_manager = xfburn_main_window_get_ui_manager (mainwin);
+  
+    action_group = (GtkActionGroup *) gtk_ui_manager_get_action_groups (ui_manager)->data;
+    
+    /*
+    action = gtk_action_group_get_action (action_group, "save-composition");
+    gtk_action_set_sensitive (GTK_ACTION (action), TRUE);
+  */
+    priv->modified = TRUE;
+  }
+}
+
+static gboolean
+thread_add_file_to_list_with_name (const gchar *name, XfburnDataComposition * dc, 
+                                   GtkTreeModel * model, const gchar * path,
+                                   GtkTreeIter * iter, GtkTreeIter * insertion, GtkTreeViewDropPosition position)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  struct stat s;
+
+  if ((stat (path, &s) == 0)) {
+    gchar *basename = NULL;
+    gchar *humansize = NULL;
+    GtkTreeIter *parent = NULL;
+    GtkTreePath *tree_path = NULL;
+
+    if (!S_ISDIR (s.st_mode) && !S_ISREG (s.st_mode)) {
+      return FALSE;
+    }
+    
+    basename = g_path_get_basename (path);
+    if ( (strlen (basename) > 1) && (basename[0] == '.') ) {
+      /* FIXME: is this really what we want? */
+      /* don't add hidden files/directories */
+
+      g_free (basename);  
+      return FALSE;
+    }
+    g_free (basename);
+    
+    xfburn_adding_progress_pulse (XFBURN_ADDING_PROGRESS (priv->progress));
+    
+    /* find parent */
+    switch (position){
+      case GTK_TREE_VIEW_DROP_BEFORE:
+      case GTK_TREE_VIEW_DROP_AFTER:
+      if (insertion) {
+          GtkTreeIter iter_parent;
+          
+          gdk_threads_enter ();
+          if (gtk_tree_model_iter_parent (model, &iter_parent, insertion)) {
+            parent = g_new0 (GtkTreeIter, 1);
+            memcpy (parent, &iter_parent, sizeof (GtkTreeIter));
+          }
+          gdk_threads_leave ();
+        }
+        break;
+      case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+      case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+        parent = g_new0 (GtkTreeIter, 1);
+        memcpy (parent, insertion, sizeof (GtkTreeIter));
+        break;
+    }
+  
+    /* check if the filename is valid */
+    gdk_threads_enter ();
+    if (parent) {
+      tree_path = gtk_tree_model_get_path (model, parent);
+      gtk_tree_path_down (tree_path);
+    } else {
+      tree_path = gtk_tree_path_new_first ();
+    }
+    gdk_threads_leave ();
+    
+    gdk_threads_enter ();
+    if (file_exists_on_same_level (model, tree_path, FALSE, name)) {
+      xfce_err (_("A file with the same name is already present in the composition"));
+
+      gtk_tree_path_free (tree_path);
+      gdk_threads_leave ();
+      g_free (parent);
+      return FALSE;
+    }
+    gtk_tree_path_free (tree_path);
+    gdk_threads_leave ();
+    
+    /* new directory */
+    if (S_ISDIR (s.st_mode)) {
+      GDir *dir = NULL;
+      GError *error = NULL;
+      const gchar *filename = NULL;
+      guint64 total_size = 4;
+
+      dir = g_dir_open (path, 0, &error);
+      if (!dir) {
+        g_warning ("unable to open directory : %s", error->message);
+
+        g_error_free (error);
+        g_free (parent);
+        
+        return FALSE;
+      }
+
+      gdk_threads_enter ();
+      gtk_tree_store_append (GTK_TREE_STORE (model), iter, parent);
+
+      gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+                          DATA_COMPOSITION_COLUMN_ICON, icon_directory,
+                          DATA_COMPOSITION_COLUMN_CONTENT, name,
+                          DATA_COMPOSITION_COLUMN_TYPE, DATA_COMPOSITION_TYPE_DIRECTORY, 
+                          DATA_COMPOSITION_COLUMN_SIZE, (guint64) 4, -1);
+      xfburn_data_disc_usage_add_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), (guint64) 4);
+      gdk_threads_leave ();
+
+      while ((filename = g_dir_read_name (dir))) {
+        GtkTreeIter new_iter;
+        gchar *new_path = NULL;
+
+        new_path = g_build_filename (path, filename, NULL);      
+        if (new_path) {
+          guint64 size;
+
+          if (thread_add_file_to_list (dc, model, new_path, &new_iter, iter, GTK_TREE_VIEW_DROP_INTO_OR_AFTER)) {
+            gdk_threads_enter ();
+            gtk_tree_model_get (model, &new_iter, DATA_COMPOSITION_COLUMN_SIZE, &size, -1);
+            gdk_threads_leave ();
+            total_size += size; 
+          }
+          
+          g_free (new_path);
+        }
+      }
+
+      humansize = xfburn_humanreadable_filesize (total_size);
+      gdk_threads_enter ();
+      gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+                          DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize, DATA_COMPOSITION_COLUMN_SIZE, total_size, -1);
+      gdk_threads_leave ();
+
+      g_dir_close (dir);
+    }
+    /* new file */
+    else if (S_ISREG (s.st_mode)) {
+#ifdef HAVE_THUNAR_VFS
+      GdkScreen *screen;
+      GtkIconTheme *icon_theme;
+      ThunarVfsMimeDatabase *mime_database = NULL;
+      ThunarVfsMimeInfo *mime_info = NULL;
+      const gchar *mime_icon_name = NULL;
+      GdkPixbuf *mime_icon = NULL;
+      gint x,y;
+	  
+      gdk_threads_enter ();
+      screen = gtk_widget_get_screen (GTK_WIDGET (dc));
+      icon_theme = gtk_icon_theme_get_for_screen (screen);
+      
+      mime_database = thunar_vfs_mime_database_get_default ();
+      mime_info = thunar_vfs_mime_database_get_info_for_file (mime_database, path, NULL);
+          
+      gtk_icon_size_lookup (GTK_ICON_SIZE_SMALL_TOOLBAR, &x, &y);
+      mime_icon_name = thunar_vfs_mime_info_lookup_icon_name (mime_info, icon_theme);
+      mime_icon = gtk_icon_theme_load_icon (icon_theme, mime_icon_name, x, 0, NULL);
+#endif
+	
+      gtk_tree_store_append (GTK_TREE_STORE (model), iter, parent);
+
+      humansize = xfburn_humanreadable_filesize (s.st_size);
+
+#ifdef HAVE_THUNAR_VFS
+      gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+                          DATA_COMPOSITION_COLUMN_ICON, (G_IS_OBJECT (mime_icon) ? mime_icon : icon_file),
+                          DATA_COMPOSITION_COLUMN_CONTENT, name,
+                          DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                          DATA_COMPOSITION_COLUMN_SIZE, (guint64) s.st_size, DATA_COMPOSITION_COLUMN_PATH, path,
+                          DATA_COMPOSITION_COLUMN_TYPE, DATA_COMPOSITION_TYPE_FILE, -1);
+#else
+      gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+                          DATA_COMPOSITION_COLUMN_ICON, icon_file,
+                          DATA_COMPOSITION_COLUMN_CONTENT, name,
+                          DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                          DATA_COMPOSITION_COLUMN_SIZE, (guint64) s.st_size, DATA_COMPOSITION_COLUMN_PATH, path,
+                          DATA_COMPOSITION_COLUMN_TYPE, DATA_COMPOSITION_TYPE_FILE, -1);
+#endif
+
+      xfburn_data_disc_usage_add_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), s.st_size);
+#ifdef HAVE_THUNAR_VFS
+      if (G_LIKELY (G_IS_OBJECT (mime_icon)))
+        g_object_unref (mime_icon);
+      thunar_vfs_mime_info_unref (mime_info);
+      g_object_unref (mime_database);
+      gdk_threads_leave ();
+#endif
+    }
+    g_free (humansize);
+    g_free (parent);
+
+    set_modified (priv);
+    return TRUE;
+  }
+  
+  return FALSE;
+}
+
+/* thread entry point */
+static void
+thread_add_files_cli (ThreadAddFilesCLIParams *params)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (params->dc);
+  GtkTreeIter iter;
+
+  GtkTreeModel *model;
+  int i;
+  gchar *full_path = NULL;
+
+  gdk_threads_enter ();
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  gdk_threads_leave ();
+
+  for (i=0; i<params->filec; i++) {
+    full_path = g_build_filename (params->filenames[i], NULL);
+    g_message ("Adding %s to the data composition... (might take a while)", full_path);
+    thread_add_file_to_list (params->dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
+    g_free (full_path);
+  }
+  xfburn_adding_progress_done (XFBURN_ADDING_PROGRESS (priv->progress));
+}
+
+static gboolean
+show_add_home_question_dialog ()
+{
+  gboolean ok = TRUE;
+
+  gdk_threads_enter ();
+  DBG ("Adding home directory");
+  ok = xfburn_ask_yes_no (GTK_MESSAGE_WARNING, ((const gchar *) _("Adding home directory")),
+                          _("You are about to add your home directory to the composition. " \
+                            "This is likely to take a very long time, and also to be too big to fit on one disc.\n\n" \
+                            "Are you sure you want to proceed?")
+                         );
+
+  gdk_threads_leave ();
+
+  return ok;
+}
+
+/* thread entry point */
+static void
+thread_add_files_action (ThreadAddFilesActionParams *params)
+{
+  XfburnDataComposition *dc = params->dc;
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  GtkTreeModel *model = params->model;
+  GtkTreeIter iter_where_insert = params->iter_where_insert;
+  GtkTreePath *path_where_insert = priv->path_where_insert;
+  const gchar * file = NULL;
+
+
+  file = strtok (priv->selected_files, "\n");
+  while (file) {
+    GtkTreeIter iter;
+    gchar *full_path = NULL;
+    
+    if (g_str_has_prefix (file, "file://"))
+      full_path = g_build_filename (&file[7], NULL);
+    else if (g_str_has_prefix (file, "file:"))
+      full_path = g_build_filename (&file[5], NULL);
+    else
+      full_path = g_build_filename (file, NULL);
+
+    if (full_path[strlen (full_path) - 1] == '\r')
+      full_path[strlen (full_path) - 1] = '\0';
+
+    if (strcmp (full_path, g_getenv ("HOME")) == 0) {
+      if (!show_add_home_question_dialog ()) {
+        g_free (full_path);
+        break;
+      }
+    }
+
+    /* add files to the disc content */
+    if (params->type == DATA_COMPOSITION_TYPE_DIRECTORY) {
+      guint64 old_size, size;
+      gchar *humansize = NULL;
+      
+      thread_add_file_to_list (dc, model, full_path, &iter, &iter_where_insert, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
+      gdk_threads_enter ();
+      gtk_tree_view_expand_row (GTK_TREE_VIEW (priv->content), path_where_insert, FALSE);
+      
+      /* update parent directory size */
+      gtk_tree_model_get (model, &iter_where_insert, DATA_COMPOSITION_COLUMN_SIZE, &old_size, -1);
+      gtk_tree_model_get (model, &iter, DATA_COMPOSITION_COLUMN_SIZE, &size, -1);
+      gdk_threads_leave ();
+      
+      humansize = xfburn_humanreadable_filesize (old_size + size);
+      
+      gdk_threads_enter ();
+      gtk_tree_store_set (GTK_TREE_STORE (model), &iter_where_insert, 
+                          DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                          DATA_COMPOSITION_COLUMN_SIZE, old_size + size, -1);
+      gdk_threads_leave ();
+      
+      g_free (humansize);
+    } else if (params->type == DATA_COMPOSITION_TYPE_FILE) {
+      GtkTreeIter parent;
+      gboolean has_parent;
+
+      gdk_threads_enter ();
+      has_parent = gtk_tree_model_iter_parent (model, &parent, &iter_where_insert);
+      gdk_threads_leave ();
+      
+      if (has_parent)
+        thread_add_file_to_list (dc, model, full_path, &iter, &parent, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);  
+      else 
+        thread_add_file_to_list (dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
+    } else {
+      thread_add_file_to_list (dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
+    }
+    
+    g_free (full_path);
+
+    file = strtok (NULL, "\n");
+  }
+  xfburn_adding_progress_done (XFBURN_ADDING_PROGRESS (priv->progress));
+}
+
+static gboolean
+thread_add_file_to_list (XfburnDataComposition * dc, GtkTreeModel * model, 
+                         const gchar * path, GtkTreeIter * iter, GtkTreeIter * insertion, GtkTreeViewDropPosition position)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  struct stat s;
+  gboolean ret = FALSE;
+  
+  if (xfburn_adding_progress_is_aborted (XFBURN_ADDING_PROGRESS (priv->progress))) {
+    DBG ("Adding aborted");
+    xfburn_adding_progress_done (XFBURN_ADDING_PROGRESS (priv->progress));
+    /* FIXME: does this properly release the resources allocated in this thread? */
+    g_thread_exit (NULL);
+  }
+
+  if ((stat (path, &s) == 0)) {
+    gchar *basename = NULL;
+
+    basename = g_path_get_basename (path);
+    
+    ret = thread_add_file_to_list_with_name (basename, dc, model, path, iter, insertion, position);
+    
+    g_free (basename);
+  }
+
+  return ret;
+}
+
+static gboolean
+copy_entry_to (XfburnDataComposition *dc, GtkTreeIter *src, GtkTreeIter *dest, GtkTreeViewDropPosition position)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  
+  gboolean ret = FALSE;
+  
+  GtkTreeModel *model;
+  GtkTreeIter iter_new;
+  
+  GdkPixbuf *icon = NULL;
+  gchar *name = NULL;
+  gchar *humansize = NULL;
+  guint64 size = 0;
+  gchar *path = NULL;
+  DataCompositionEntryType type;
+
+  GtkTreePath *path_level = NULL;
+  
+  guint n_children = 0;
+  guint i;
+  GtkTreePath *path_src = NULL;
+  
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  
+  gtk_tree_model_get (model, src, DATA_COMPOSITION_COLUMN_ICON, &icon, DATA_COMPOSITION_COLUMN_CONTENT, &name,
+                      DATA_COMPOSITION_COLUMN_HUMANSIZE, &humansize, DATA_COMPOSITION_COLUMN_SIZE, &size,
+                      DATA_COMPOSITION_COLUMN_PATH, &path, DATA_COMPOSITION_COLUMN_TYPE, &type, -1);
+  
+  switch (position) {
+    case GTK_TREE_VIEW_DROP_BEFORE:
+    case GTK_TREE_VIEW_DROP_AFTER:
+      gtk_tree_store_insert_before (GTK_TREE_STORE (model), &iter_new, NULL, dest);
+      break;
+    case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+    case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+      if (dest) {
+        path_level = gtk_tree_model_get_path (model, dest);
+        gtk_tree_path_down (path_level);
+      } else {
+        path_level = gtk_tree_path_new_first ();
+      }
+    
+      if (file_exists_on_same_level (model, path_level, FALSE, name)) {
+        xfce_warn (_("A file named \"%s\" already exists in this directory, the file hasn't been added"), name);
+        goto cleanup;
+      }
+      
+      gtk_tree_path_free (path_level);
+      
+      gtk_tree_store_append (GTK_TREE_STORE (model), &iter_new, dest);                          
+      break;
+  }
+  
+  gtk_tree_store_set (GTK_TREE_STORE (model), &iter_new, DATA_COMPOSITION_COLUMN_ICON, icon, 
+                      DATA_COMPOSITION_COLUMN_CONTENT, name, DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
+                      DATA_COMPOSITION_COLUMN_SIZE, size, DATA_COMPOSITION_COLUMN_PATH, path,
+                      DATA_COMPOSITION_COLUMN_TYPE, type, -1);
+    
+  /* copy children */
+  n_children = gtk_tree_model_iter_n_children (model, src);
+
+  for (i = 0; i < n_children; i++) {
+    GtkTreeIter iter_child;
+
+    if (gtk_tree_model_iter_nth_child (model, &iter_child, src, i))
+      copy_entry_to (dc, &iter_child, &iter_new, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
+  }
+
+  path_src = gtk_tree_model_get_path (model, src);
+  if (n_children > 0 && gtk_tree_view_row_expanded (GTK_TREE_VIEW (priv->content), path_src)) {
+    GtkTreePath *path_new = NULL;
+    
+    path_new = gtk_tree_model_get_path (model, &iter_new);
+    gtk_tree_view_expand_row (GTK_TREE_VIEW (priv->content), path_new, FALSE);
+    
+    gtk_tree_path_free (path_new);
+  }
+  gtk_tree_path_free (path_src);
+  
+  ret =  TRUE;
+  
+cleanup:
+  if (G_LIKELY (G_IS_OBJECT (icon)))
+    g_object_unref (icon);
+  g_free (name);
+  g_free (humansize);
+  g_free (path);
+  
+  return ret;
+}
+
+static void
+cb_content_drag_data_rcv (GtkWidget * widget, GdkDragContext * dc, guint x, guint y, GtkSelectionData * sd,
+                          guint info, guint t, XfburnDataComposition * composition)
+{    
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+  
+  GtkTreeModel *model;
+  GtkTreePath *path_where_insert = NULL;
+  GtkTreeViewDropPosition position;
+  GtkTreeIter iter_where_insert;
+
+  g_return_if_fail (sd);
+  g_return_if_fail (sd->data);
+  
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+  
+  gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), x, y, &path_where_insert, &position);
+  
+  xfburn_busy_cursor (priv->content);
+
+  /* move a selection inside of the composition window */
+  if (sd->target == gdk_atom_intern ("XFBURN_TREE_PATHS", FALSE)) {
+    GList *row = NULL, *selected_rows = NULL;
+    GtkTreeIter *iter = NULL;
+    DataCompositionEntryType type_dest = -1;
+    
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
+
+    row = selected_rows = *((GList **) sd->data);
+    
+    if (path_where_insert) {      
+      gtk_tree_model_get_iter (model, &iter_where_insert, path_where_insert);
+      iter = &iter_where_insert;
+      
+      gtk_tree_model_get (model, &iter_where_insert, DATA_COMPOSITION_COLUMN_TYPE, &type_dest, -1);
+      
+      if (type_dest == DATA_COMPOSITION_TYPE_FILE) {
+        if (position == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
+          position = GTK_TREE_VIEW_DROP_AFTER;
+        else if (position == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
+          position = GTK_TREE_VIEW_DROP_BEFORE;
+      }      
+    } else {
+      position = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
+    }
+    
+    /* copy selection */
+    while (row) {
+      GtkTreePath *path_src = NULL;
+      GtkTreeIter iter_src;
+      GtkTreeRowReference *reference = NULL;
+      DataCompositionEntryType type;
+      guint64 size = 0;
+      
+      reference = (GtkTreeRowReference *) row->data;
+    
+      path_src = gtk_tree_row_reference_get_path (reference);
+      if (!path_src) {
+        gtk_tree_row_reference_free (reference);
+        
+        row = g_list_next (row);
+        continue;
+      }
+      
+      if (path_where_insert && (position == GTK_TREE_VIEW_DROP_AFTER || position == GTK_TREE_VIEW_DROP_BEFORE) 
+          && (gtk_tree_path_get_depth (path_where_insert) == gtk_tree_path_get_depth (path_src))) {
+          gtk_tree_path_free (path_src);
+          gtk_tree_row_reference_free (reference);
+      
+          row = g_list_next (row);
+          continue;
+      }
+
+      if (path_where_insert && type == DATA_COMPOSITION_TYPE_DIRECTORY 
+          && gtk_tree_path_is_descendant (path_where_insert, path_src)) {
+
+        gtk_tree_path_free (path_src);
+        gtk_tree_path_free (path_where_insert);
+        gtk_tree_row_reference_free (reference);
+            
+        gtk_drag_finish (dc, FALSE, FALSE, t);
+        return;
+      }
+
+      gtk_tree_model_get_iter (model, &iter_src, path_src);
+      gtk_tree_model_get (model, &iter_src, DATA_COMPOSITION_COLUMN_TYPE, &type,
+                          DATA_COMPOSITION_COLUMN_SIZE, &size, -1);
+      
+      /* copy entry */
+      if (copy_entry_to (composition, &iter_src, iter, position)) {                
+        GtkTreePath *path_parent = gtk_tree_path_copy (path_src);
+        
+        /* update new parent size */
+        if (iter && (position == GTK_TREE_VIEW_DROP_INTO_OR_AFTER 
+                   || position == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)) {
+          guint64 old_size = 0;
+          gchar *parent_humansize = NULL;
+
+          gtk_tree_model_get (model, iter, DATA_COMPOSITION_COLUMN_SIZE, &old_size, -1);
+            
+          parent_humansize = xfburn_humanreadable_filesize (old_size + size);
+          gtk_tree_store_set (GTK_TREE_STORE (model), iter, DATA_COMPOSITION_COLUMN_HUMANSIZE, parent_humansize,
+                              DATA_COMPOSITION_COLUMN_SIZE, old_size + size, -1);
+        
+          g_free (parent_humansize);
+        }
+          
+        if (dc->action == GDK_ACTION_MOVE) {       
+          /* remove source entry */
+          if (gtk_tree_path_up (path_parent) && path_where_insert && 
+              !gtk_tree_path_is_descendant (path_where_insert, path_parent)) {
+            /* update parent size and humansize */
+            GtkTreeIter iter_parent;          
+            guint64 old_size;
+            gchar *parent_humansize = NULL;
+            
+            gtk_tree_model_iter_parent (model, &iter_parent, &iter_src);                
+            gtk_tree_model_get (model, &iter_parent, DATA_COMPOSITION_COLUMN_SIZE, &old_size, -1);
+         
+            parent_humansize = xfburn_humanreadable_filesize (old_size - size);
+            gtk_tree_store_set (GTK_TREE_STORE (model), &iter_parent, 
+                                DATA_COMPOSITION_COLUMN_HUMANSIZE, parent_humansize,
+                                DATA_COMPOSITION_COLUMN_SIZE, old_size - size, -1);
+            g_free (parent_humansize);
+          }
+        
+          gtk_tree_store_remove (GTK_TREE_STORE (model), &iter_src);
+        } else {
+          xfburn_data_disc_usage_add_size (XFBURN_DATA_DISC_USAGE (priv->disc_usage), size);
+        }
+        
+        gtk_tree_path_free (path_parent);
+      }
+
+      gtk_tree_path_free (path_src);
+      gtk_tree_row_reference_free (reference);
+      
+      row = g_list_next (row);
+    }
+    
+    g_list_free (selected_rows);    
+    gtk_drag_finish (dc, TRUE, FALSE, t);
+    
+    if (path_where_insert)
+      gtk_tree_path_free (path_where_insert);  
+    gtk_widget_hide (priv->progress);
+    xfburn_default_cursor (priv->content);
+  }
+  /* drag from the file selector */
+  else if (sd->target == gdk_atom_intern ("text/plain", FALSE)) {
+    ThreadAddFilesDragParams *params;
+    const gchar *file = NULL;
+
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
+    
+    file = strtok ((gchar *) sd->data, "\n");
+    while (file) {
+      gchar *full_path;
+
+      if (g_str_has_prefix (file, "file://"))
+        full_path = g_build_filename (&file[7], NULL);
+      else if (g_str_has_prefix ((gchar *) sd->data, "file:"))
+        full_path = g_build_filename (&file[5], NULL);
+      else
+        full_path = g_build_filename (file, NULL);
+
+      if (full_path[strlen (full_path) - 1] == '\r')
+        full_path[strlen (full_path) - 1] = '\0';
+
+      /* remember path to add it later in another thread */
+      priv->full_paths_to_add = g_list_append (priv->full_paths_to_add, full_path);
+
+      file = strtok (NULL, "\n");
+    }
+
+    priv->full_paths_to_add = g_list_reverse (priv->full_paths_to_add);
+    priv->path_where_insert = path_where_insert;
+
+    params = g_new (ThreadAddFilesDragParams, 1);
+    params->composition = composition;
+    params->position = position;
+    params->widget = widget;
+
+    /* append a dummy row so that gtk doesn't freak out */
+    gtk_tree_store_append (GTK_TREE_STORE (model), &params->iter_dummy, NULL);
+
+    priv->thread_params = params;
+    g_thread_create ((GThreadFunc) thread_add_files_drag, params, FALSE, NULL);
+
+    gtk_drag_finish (dc, TRUE, FALSE, t);
+  } 
+  else if (sd->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+#ifdef HAVE_THUNAR_VFS
+    GList *vfs_paths = NULL;
+    GList *vfs_path;
+    GError *error = NULL;
+    gchar *full_path;
+
+    vfs_paths = thunar_vfs_path_list_from_string ((gchar *) sd->data, &error);
+
+    if (G_LIKELY (vfs_paths != NULL)) {
+      ThreadAddFilesDragParams *params;
+      priv->full_paths_to_add = NULL;
+      for (vfs_path = vfs_paths; vfs_path != NULL; vfs_path = g_list_next (vfs_path)) {
+        ThunarVfsPath *path = THUNAR_VFS_PATH (vfs_path->data);
+        if (thunar_vfs_path_get_scheme (path) != THUNAR_VFS_PATH_SCHEME_FILE)
+          continue;
+        full_path = thunar_vfs_path_dup_string (path);
+        g_debug ("adding uri path: %s", full_path);
+        priv->full_paths_to_add = g_list_prepend (priv->full_paths_to_add, full_path);
+      }
+      thunar_vfs_path_list_free (vfs_paths);
+
+      priv->full_paths_to_add = g_list_reverse (priv->full_paths_to_add);
+      priv->path_where_insert = path_where_insert;
+
+      params = g_new (ThreadAddFilesDragParams, 1);
+      params->composition = composition;
+      params->position = position;
+      params->widget = widget;
+
+      /* append a dummy row so that gtk doesn't freak out */
+      gtk_tree_store_append (GTK_TREE_STORE (model), &params->iter_dummy, NULL);
+
+      priv->thread_params = params;
+      g_thread_create ((GThreadFunc) thread_add_files_drag, params, FALSE, NULL);
+
+      gtk_drag_finish (dc, TRUE, FALSE, t);
+    } else {
+      if (G_UNLIKELY (error != NULL))
+        g_warning ("text/uri-list drag failed because '%s'", error->message);
+      else
+        g_warning("There were no files in the uri list!");
+      gtk_drag_finish (dc, FALSE, FALSE, t);
+      xfburn_default_cursor (priv->content);
+    }
+#else
+    g_warning ("Receiving this type of drag and drop requires thunar-vfs support, sorry!");
+    gtk_drag_finish (dc, FALSE, FALSE, t);
+    xfburn_default_cursor (priv->content);
+#endif
+  } 
+  else {
+    g_warning ("Trying to receive an unsupported drag target, this should not happen.");
+    gtk_drag_finish (dc, FALSE, FALSE, t);
+    xfburn_default_cursor (priv->content);
+  }
+}
+
+/* thread entry point */
+static void
+thread_add_files_drag (ThreadAddFilesDragParams *params)
+{
+  XfburnDataComposition *composition = params->composition;
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+
+  GtkTreeViewDropPosition position = params->position;
+  GtkWidget *widget = params->widget;
+
+  GtkTreeModel *model;
+  GtkTreeIter iter_where_insert;
+  GList *files = priv->full_paths_to_add;
+
+  gdk_threads_enter ();
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+
+  /* remove the dummy row again */
+  gtk_tree_store_remove (GTK_TREE_STORE (model), &params->iter_dummy);
+  gdk_threads_leave ();
+
+  for (; files; files = g_list_next (files)) {
+    gchar *full_path = (gchar *) files->data;
+    GtkTreeIter iter;
+
+    if (priv->path_where_insert) {
+      gdk_threads_enter ();
+      gtk_tree_model_get_iter (model, &iter_where_insert, priv->path_where_insert);
+      gdk_threads_leave ();
+      
+      if (thread_add_file_to_list (composition, model, full_path, &iter, &iter_where_insert, position)) {
+        if (position == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE 
+            || position == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
+          gdk_threads_enter ();
+          gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), priv->path_where_insert, FALSE);
+          gdk_threads_leave ();
+      }
+      
+    } else  {
+      thread_add_file_to_list (composition, model, full_path, &iter, NULL, position);
+    }
+  }
+  xfburn_adding_progress_done (XFBURN_ADDING_PROGRESS (priv->progress));
+}
+
+static void
+fill_image_with_composition (GtkTreeModel *model, IsoImage *image, IsoDir * parent, GtkTreeIter *iter)
+{
+  do {
+      DataCompositionEntryType type;
+      gchar *name = NULL;
+      gchar *src = NULL;
+      IsoNode *node = NULL;
+      IsoDir *dir = NULL;
+      int r;
+      
+      gtk_tree_model_get (model, iter, DATA_COMPOSITION_COLUMN_TYPE, &type,
+			  DATA_COMPOSITION_COLUMN_CONTENT, &name, DATA_COMPOSITION_COLUMN_PATH, &src, -1);
+
+      if (type == DATA_COMPOSITION_TYPE_DIRECTORY)
+        r = iso_tree_add_new_dir (parent, name, &dir);
+      else
+        r = iso_tree_add_node (image, parent, src, &node);
+
+      if (r < 0) {
+        if (r == ISO_NULL_POINTER)
+          g_error ("Failed adding %s as a node to the image: null pointer!", src);
+        else if (r == ISO_NODE_NAME_NOT_UNIQUE)
+          g_error ("Failed adding %s as a node to the image: node name not unique!", src);
+        /* else if (r == ISO_MEM_ERROR)
+          g_error ("Failed adding %s as a node to the image: memory error!", src); */
+        else
+          g_error ("Failed adding %s as a node to the image: code %d!", src, r);
+      }
+
+      /* FIXME: do we need to call iso_node_ref on node? Probably not... */
+      if (type != DATA_COMPOSITION_TYPE_DIRECTORY)
+        iso_node_set_name (node, name);
+
+      g_free (name);
+      g_free (src);
+
+      if (type == DATA_COMPOSITION_TYPE_DIRECTORY && gtk_tree_model_iter_has_child (model, iter)) {
+	GtkTreeIter child;
+
+        /* FIXME: this should not cause a sigfault... 
+        if (iso_node_get_type(node) != LIBISO_DIR)
+            g_error ("Expected %s to be a directory, but it isn't...\n", src);
+        */
+
+	gtk_tree_model_iter_children (model, &child, iter);
+	fill_image_with_composition (model, image, dir, &child);
+      }
+  } while (gtk_tree_model_iter_next (model, iter));
+}
+
+static IsoImage *
+generate_iso_image (XfburnDataComposition * dc)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  IsoImage *image = NULL;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  iso_image_new (gtk_entry_get_text (GTK_ENTRY (priv->entry_volume_name)), &image);
+  iso_image_set_application_id (image, "Xfburn");
+  iso_image_set_data_preparer_id (image, "Xfburn");
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  if (gtk_tree_model_get_iter_first (model, &iter)) {
+    fill_image_with_composition (model, image, iso_image_get_root (image), &iter);
+  }
+
+  return image;
+}
+
+/****************/
+/* loading code */
+/****************/
+typedef struct
+{
+  gboolean started;
+  XfburnDataComposition *dc;
+  GQueue *queue_iter;
+} LoadParserStruct;
+
+static gint
+_find_attribute (const gchar ** attribute_names, const gchar * attr)
+{
+  gint i;
+
+  for (i = 0; attribute_names[i]; i++) {
+    if (!strcmp (attribute_names[i], attr))
+      return i;
+  }
+
+  return -1;
+}
+
+static void
+load_composition_start (GMarkupParseContext * context, const gchar * element_name,
+                        const gchar ** attribute_names, const gchar ** attribute_values,
+                        gpointer data, GError ** error)
+{
+  LoadParserStruct * parserinfo = (LoadParserStruct *) data;
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (parserinfo->dc);
+
+  
+  if (!(parserinfo->started) && !strcmp (element_name, "xfburn-composition"))
+    parserinfo->started = TRUE;
+  else if (!(parserinfo->started))
+    return;
+
+  if (!strcmp (element_name, "file")) {
+    int i, j;
+
+    if ((i = _find_attribute (attribute_names, "name")) != -1 &&
+        (j = _find_attribute (attribute_names, "source")) != -1) {
+      //GtkTreeIter iter;
+      GtkTreeIter *parent;
+      GtkTreeModel *model;
+
+      model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+      parent = g_queue_peek_head (parserinfo->queue_iter);
+          
+      g_error ("This method needs to get fixed, and does not work right now!");
+      /*
+      add_file_to_list_with_name (attribute_values[i], parserinfo->dc, model, attribute_values[j], &iter, 
+                                  parent, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
+      */
+    }
+  } else if (!strcmp (element_name, "directory")) {
+    int i, j;
+
+    if ((i = _find_attribute (attribute_names, "name")) != -1 &&
+        (j = _find_attribute (attribute_names, "source")) != -1) {
+      //GtkTreeIter iter;
+      GtkTreeModel *model;
+
+      model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+      
+      //add_directory_to_list (attribute_values[i], parserinfo->dc, model, attribute_values[j], &iter, parent);    
+    }
+  }
+}
+
+static void
+load_composition_end (GMarkupParseContext * context, const gchar * element_name, gpointer user_data, GError ** error)
+{
+  LoadParserStruct *parserinfo = (LoadParserStruct *) user_data;
+  
+  if (!parserinfo->started)
+    return;
+  
+  if (!strcmp (element_name, "xfburn-composition"))
+    parserinfo->started = FALSE;
+  
+  if (!strcmp (element_name, "directory"))
+    parserinfo->queue_iter = g_queue_pop_head (parserinfo->queue_iter);
+}
+
+static void
+load_from_file (XfburnComposition * composition, const gchar * filename)
+{
+  gchar *file_contents = NULL;
+  GMarkupParseContext *gpcontext = NULL;
+  struct stat st;
+  LoadParserStruct parserinfo;
+  GMarkupParser gmparser = {
+    load_composition_start, load_composition_end, NULL, NULL, NULL
+  };
+  GError *err = NULL;
+#ifdef HAVE_MMAP
+  gint fd = -1;
+  void *maddr = NULL;
+#endif
+  g_return_if_fail (filename != NULL);
+  if (stat (filename, &st) < 0) {
+    g_warning ("Unable to open %s", filename);
+    goto cleanup;
+  }
+
+#ifdef HAVE_MMAP
+  fd = open (filename, O_RDONLY, 0);
+  if (fd < 0)
+    goto cleanup;
+  maddr = mmap (NULL, st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
+  if (maddr)
+    file_contents = maddr;
+#endif
+  if (!file_contents && !g_file_get_contents (filename, &file_contents, NULL, &err)) {
+    if (err) {
+      g_warning ("Unable to read file '%s' (%d): %s", filename, err->code, err->message);
+      g_error_free (err);
+    }
+    goto cleanup;
+  }
+
+  parserinfo.started = FALSE;
+  parserinfo.dc = XFBURN_DATA_COMPOSITION (composition);
+  parserinfo.queue_iter = g_queue_new ();
+  gpcontext = g_markup_parse_context_new (&gmparser, 0, &parserinfo, NULL);
+  if (!g_markup_parse_context_parse (gpcontext, file_contents, st.st_size, &err)) {
+    g_warning ("Error parsing composition (%d): %s", err->code, err->message);
+    g_error_free (err);
+    goto cleanup;
+  }
+
+  if (g_markup_parse_context_end_parse (gpcontext, NULL)) {
+    DBG ("parsed");
+  }
+
+  g_queue_free (parserinfo.queue_iter);
+  
+cleanup:
+  if (gpcontext)
+    g_markup_parse_context_free (gpcontext);
+#ifdef HAVE_MMAP
+  if (maddr) {
+    munmap (maddr, st.st_size);
+    file_contents = NULL;
+  }
+  if (fd > -1)
+    close (fd);
+#endif
+  if (file_contents)
+    g_free (file_contents);
+}
+
+
+/***************/
+/* saving code */
+/***************/
+typedef struct
+{
+  FILE *file_content;
+  gint last_depth;
+} CompositionSaveInfo;
+
+static gboolean
+foreach_save (GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, CompositionSaveInfo *info)
+{
+  gchar *space = NULL;
+  gint i;
+  gchar *name = NULL;
+  gchar *source_path = NULL;
+  DataCompositionEntryType type;
+
+  space = g_strnfill (gtk_tree_path_get_depth (path), '\t');
+  
+  for (i = info->last_depth; i > gtk_tree_path_get_depth (path); i--) {
+    gchar *space2 = NULL;
+
+    space2 = g_strnfill (i - 1, '\t');
+    fprintf (info->file_content, "%s</directory>\n", space2);
+    
+    g_free (space2);
+  }
+  
+  gtk_tree_model_get (model, iter, DATA_COMPOSITION_COLUMN_CONTENT, &name,
+                      DATA_COMPOSITION_COLUMN_PATH, &source_path,
+                      DATA_COMPOSITION_COLUMN_TYPE, &type, -1);
+  
+  fprintf (info->file_content, "%s", space);
+  switch (type) {
+  case DATA_COMPOSITION_TYPE_FILE:
+    fprintf (info->file_content, "<file name=\"%s\" source=\"%s\" />\n", name, source_path);
+    break;
+  case DATA_COMPOSITION_TYPE_DIRECTORY:
+    fprintf (info->file_content, "<directory name=\"%s\" source=\"%s\"", name, source_path);
+  
+    if (gtk_tree_model_iter_has_child (model, iter))
+      fprintf (info->file_content, ">\n");
+    else
+      fprintf (info->file_content, "/>\n");
+
+    break;
+  }
+
+
+  info->last_depth = gtk_tree_path_get_depth (path);
+  
+  g_free (space);
+  g_free (name);
+  g_free (source_path);
+
+  return FALSE;
+}
+
+static void
+save_to_file (XfburnComposition * composition)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+  FILE *file_content;
+  GtkTreeModel *model;
+  CompositionSaveInfo info = {};
+  gint i;
+    
+  if (!(priv->filename)) {
+    priv->filename = g_strdup ("/tmp/gna");
+    
+    g_signal_emit_by_name (G_OBJECT (composition), "name-changed", priv->filename);
+  }
+  
+  file_content = fopen (priv->filename, "w+");
+  fprintf (file_content, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
+  fprintf (file_content, "<xfburn-composition version=\"0.1\">\n");
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+  info.file_content = file_content;
+  info.last_depth = 0;
+  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) foreach_save, &info);
+
+  for (i = info.last_depth; i > 1; i--) {
+    gchar *space2 = NULL;
+
+    space2 = g_strnfill (i - 1, '\t');
+    fprintf (info.file_content, "%s</directory>\n", space2);
+    
+    g_free (space2);
+  }
+    
+  fprintf (file_content, "</xfburn-composition>\n");
+  fclose (file_content);
+}
+
+/******************/
+/* public methods */
+/******************/
+GtkWidget *
+xfburn_data_composition_new (void)
+{
+  return g_object_new (xfburn_data_composition_get_type (), NULL);
+}
+
+void 
+xfburn_data_composition_add_files (XfburnDataComposition *dc, int filec, char **filenames)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+  ThreadAddFilesCLIParams *params;
+  
+  if (filec > 0) {
+    params = g_new (ThreadAddFilesCLIParams, 1);
+
+    params->filenames = filenames;
+    params->filec = filec;
+    params->dc = dc;
+
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
+    xfburn_busy_cursor (priv->content);
+
+    priv->thread_params = params;
+    g_thread_create ((GThreadFunc) thread_add_files_cli, params, FALSE, NULL);
+  }
+}
+
+void
+xfburn_data_composition_hide_toolbar (XfburnDataComposition * composition)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+  
+  gtk_widget_hide (priv->toolbar);
+}
+
+void
+xfburn_data_composition_show_toolbar (XfburnDataComposition * composition)
+{
+  XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (composition);
+  
+  gtk_widget_show (priv->toolbar);
+}
+


Property changes on: xfburn/trunk/xfburn/xfburn-audio-composition.c
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 

Copied: xfburn/trunk/xfburn/xfburn-audio-composition.h (from rev 5210, xfburn/trunk/xfburn/xfburn-data-composition.h)
===================================================================
--- xfburn/trunk/xfburn/xfburn-audio-composition.h	                        (rev 0)
+++ xfburn/trunk/xfburn/xfburn-audio-composition.h	2008-08-09 02:20:20 UTC (rev 5211)
@@ -0,0 +1,64 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2005-2006 Jean-François Wauthy (pollux at xfce.org)
+ *
+ * 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 Library 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.
+ */
+
+#ifndef __XFBURN_DATA_COMPOSITION_H__
+#define __XFBURN_DATA_COMPOSITION_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define XFBURN_TYPE_DATA_COMPOSITION            (xfburn_data_composition_get_type ())
+#define XFBURN_DATA_COMPOSITION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFBURN_TYPE_DATA_COMPOSITION, XfburnDataComposition))
+#define XFBURN_DATA_COMPOSITION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFBURN_TYPE_DATA_COMPOSITION, XfburnDataCompositionClass))
+#define XFBURN_IS_DATA_COMPOSITION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFBURN_TYPE_DATA_COMPOSITION))
+#define XFBURN_IS_DATA_COMPOSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFBURN_TYPE_DATA_COMPOSITION))
+#define XFBURN_DATA_COMPOSITION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFBURN_TYPE_DATA_COMPOSITION, XfburnDataCompositionClass))
+  
+typedef struct
+{
+  GtkVBox vbox;
+} XfburnDataComposition;
+
+typedef struct
+{
+  GtkVBoxClass parent_class;
+} XfburnDataCompositionClass;
+
+enum
+{
+  DATA_COMPOSITION_DND_TARGET_INSIDE,
+  DATA_COMPOSITION_DND_TARGET_TEXT_PLAIN,
+  DATA_COMPOSITION_DND_TARGET_TEXT_URI_LIST,
+};
+
+GtkType xfburn_data_composition_get_type (void);
+
+GtkWidget *xfburn_data_composition_new (void);
+void xfburn_data_composition_add_files (XfburnDataComposition *content, int filec, char **filenames);
+void xfburn_data_composition_hide_toolbar (XfburnDataComposition *content);
+void xfburn_data_composition_show_toolbar (XfburnDataComposition *content);
+
+
+G_END_DECLS
+#endif


Property changes on: xfburn/trunk/xfburn/xfburn-audio-composition.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 




More information about the Goodies-commits mailing list