[Goodies-commits] r5029 - in xfburn/trunk: . xfburn

David Mohr squisher at xfce.org
Mon Jul 7 05:31:36 CEST 2008


Author: squisher
Date: 2008-07-07 03:31:35 +0000 (Mon, 07 Jul 2008)
New Revision: 5029

Modified:
   xfburn/trunk/NEWS
   xfburn/trunk/TODO
   xfburn/trunk/xfburn/xfburn-adding-progress.c
   xfburn/trunk/xfburn/xfburn-adding-progress.h
   xfburn/trunk/xfburn/xfburn-data-composition.c
Log:
Using threads for adding files, adding can now get aborted

Modified: xfburn/trunk/NEWS
===================================================================
--- xfburn/trunk/NEWS	2008-07-05 18:42:52 UTC (rev 5028)
+++ xfburn/trunk/NEWS	2008-07-07 03:31:35 UTC (rev 5029)
@@ -11,6 +11,7 @@
   debug is enabled, or otherwise some info on the burner that was used.
 - Use fifo buffering, default is 4MB, adjustable in the preferences
 - Preserve file attributes
+- Now using threads for adding files, and the adding can get aborted
 
 xfburn 0.3.0
 ============

Modified: xfburn/trunk/TODO
===================================================================
--- xfburn/trunk/TODO	2008-07-05 18:42:52 UTC (rev 5028)
+++ xfburn/trunk/TODO	2008-07-07 03:31:35 UTC (rev 5029)
@@ -45,3 +45,5 @@
     code bases) [?]
 - determine if it's worth it to add advanced burn options dialog to 
   toggle rockridge and joliet extensions / iso_write_opts profiles
+- check for memory leaks while adding files
+- check if all the enter/leaving of gdk threads slows adding down

Modified: xfburn/trunk/xfburn/xfburn-adding-progress.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-adding-progress.c	2008-07-05 18:42:52 UTC (rev 5028)
+++ xfburn/trunk/xfburn/xfburn-adding-progress.c	2008-07-07 03:31:35 UTC (rev 5029)
@@ -24,26 +24,38 @@
 #include <gtk/gtk.h>
 #include <libxfce4util/libxfce4util.h>
 
+#include "xfburn-global.h"
 #include "xfburn-adding-progress.h"
+#include "xfburn-utils.h"
 
 #define XFBURN_ADDING_PROGRESS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFBURN_TYPE_ADDING_PROGRESS, XfburnAddingProgressPrivate))
 
+enum {
+  ADDING_DONE,
+  LAST_SIGNAL,
+};
+
 /* private struct */
 typedef struct
 {
   GtkWidget *progress_bar;
+  gboolean aborted;
 } XfburnAddingProgressPrivate;
 
 /* prototypes */
 static void xfburn_adding_progress_class_init (XfburnAddingProgressClass *);
 static void xfburn_adding_progress_init (XfburnAddingProgress *);
+static void xfburn_adding_progress_finalize (GObject * object);
+static gboolean cb_delete (GtkWidget *widget, GdkEvent *event, gpointer data);
 
 /* globals */
 static GtkWindowClass *parent_class = NULL;
+static guint signals[LAST_SIGNAL];
 
 /******************************/
 /* XfburnAddingProgress class */
 /******************************/
+
 GtkType
 xfburn_adding_progress_get_type (void)
 {
@@ -72,10 +84,18 @@
 static void
 xfburn_adding_progress_class_init (XfburnAddingProgressClass * klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (XfburnAddingProgressPrivate));
 
   parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize = xfburn_adding_progress_finalize;
+  
+  signals[ADDING_DONE] = g_signal_new ("adding-done", XFBURN_TYPE_ADDING_PROGRESS, G_SIGNAL_ACTION,
+                                          G_STRUCT_OFFSET (XfburnAddingProgressClass, adding_done),
+                                          NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                                          G_TYPE_NONE, 0);
 }
 
 static void
@@ -84,6 +104,8 @@
   XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (win);
   GtkWidget *vbox;
   
+  gtk_window_set_resizable (GTK_WINDOW (win), FALSE);
+
   gtk_window_set_icon_name (GTK_WINDOW (win), GTK_STOCK_ADD);
   gtk_window_set_destroy_with_parent (GTK_WINDOW (win), TRUE);
   gtk_window_set_title (GTK_WINDOW (win), _("Adding files to the composition"));
@@ -93,19 +115,42 @@
   gtk_container_add (GTK_CONTAINER (win), vbox);
     
   priv->progress_bar = gtk_progress_bar_new ();
-  gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (priv->progress_bar), 0.1);
+  gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (priv->progress_bar), 0.01);
   gtk_widget_show (priv->progress_bar);
-  gtk_box_pack_start (GTK_BOX (vbox), priv->progress_bar, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->progress_bar, TRUE, TRUE, BORDER);
 
   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar), 0.5);  
+
+  priv->aborted = FALSE;
+  g_signal_connect (G_OBJECT (win), "delete-event", G_CALLBACK (cb_delete), NULL);
 }
 
+static void
+xfburn_adding_progress_finalize (GObject * object)
+{
+  //XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (object);
+
+}
+
 /* internals */
 
+static gboolean
+cb_delete (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+  XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (widget);
+  priv->aborted = TRUE;
+
+  return TRUE;
+}
+
 /******************/
 /* public methods */
 /******************/
-GtkWidget *
+
+/*
+ * These functions are expected to be called from the gui thread
+ */
+XfburnAddingProgress *
 xfburn_adding_progress_new (void)
 {
   GtkWidget *obj;
@@ -113,14 +158,46 @@
   obj = g_object_new (xfburn_adding_progress_get_type (), NULL);
 
   gtk_widget_realize (obj);
-  return obj;
+
+  return XFBURN_ADDING_PROGRESS (obj);
 }
 
+/*
+ * these functions are expected to be called from the secondary thread
+ */
 void
 xfburn_adding_progress_pulse (XfburnAddingProgress *adding_progress)
 {
   XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (adding_progress);
   
-  DBG ("pulse");
+  gdk_threads_enter ();
+  //DBG ("pulse");
   gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progress_bar));
+  gdk_threads_leave ();
 }
+
+void
+xfburn_adding_progress_done (XfburnAddingProgress *adding_progress)
+{
+  //XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (adding_progress);
+  
+  gdk_threads_enter ();
+  g_signal_emit (G_OBJECT (adding_progress), signals[ADDING_DONE], 0);
+  gdk_threads_leave ();
+}
+
+gboolean
+xfburn_adding_progress_is_aborted (XfburnAddingProgress *adding_progress)
+{
+  XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (adding_progress);
+  
+  return priv->aborted;
+}
+
+void xfburn_adding_progress_show (XfburnAddingProgress *adding_progress)
+{
+  XfburnAddingProgressPrivate *priv = XFBURN_ADDING_PROGRESS_GET_PRIVATE (adding_progress);
+
+  priv->aborted = FALSE;
+  gtk_widget_show (GTK_WIDGET (adding_progress));
+}

Modified: xfburn/trunk/xfburn/xfburn-adding-progress.h
===================================================================
--- xfburn/trunk/xfburn/xfburn-adding-progress.h	2008-07-05 18:42:52 UTC (rev 5028)
+++ xfburn/trunk/xfburn/xfburn-adding-progress.h	2008-07-07 03:31:35 UTC (rev 5029)
@@ -26,6 +26,8 @@
 
 #include <gtk/gtk.h>
 
+#include "xfburn-data-composition.h"
+
 G_BEGIN_DECLS
 #define XFBURN_TYPE_ADDING_PROGRESS            (xfburn_adding_progress_get_type ())
 #define XFBURN_ADDING_PROGRESS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFBURN_TYPE_ADDING_PROGRESS, XfburnAddingProgress))
@@ -33,23 +35,26 @@
 #define XFBURN_IS_ADDING_PROGRESS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFBURN_TYPE_ADDING_PROGRESS))
 #define XFBURN_IS_ADDING_PROGRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFBURN_TYPE_ADDING_PROGRESS))
 #define XFBURN_ADDING_PROGRESS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFBURN_TYPE_ADDING_PROGRESS, XfburnAddingProgressClass))
-typedef struct _XfburnAddingProgress XfburnAddingProgress;
-typedef struct _XfburnAddingProgressClass XfburnAddingProgressClass;
 
-struct _XfburnAddingProgress
+typedef struct 
 {
   GtkWindow window;
-};
+} XfburnAddingProgress;
 
-struct _XfburnAddingProgressClass
+typedef struct 
 {
   GtkWindowClass parent_class;
-};
+  void (*adding_done) (XfburnAddingProgress *progress, XfburnDataComposition *dc);
+} XfburnAddingProgressClass;
 
 GtkType xfburn_adding_progress_get_type (void);
 
-GtkWidget *xfburn_adding_progress_new (void);
+XfburnAddingProgress *xfburn_adding_progress_new (void);
 void xfburn_adding_progress_pulse (XfburnAddingProgress *adding_progress);
+void xfburn_adding_progress_wait_until_done (XfburnAddingProgress *adding_progress);
+void xfburn_adding_progress_done (XfburnAddingProgress *adding_progress);
+gboolean xfburn_adding_progress_is_aborted (XfburnAddingProgress *adding_progress);
+void xfburn_adding_progress_show (XfburnAddingProgress *adding_progress);
 
 G_END_DECLS
 #endif

Modified: xfburn/trunk/xfburn/xfburn-data-composition.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-data-composition.c	2008-07-05 18:42:52 UTC (rev 5028)
+++ xfburn/trunk/xfburn/xfburn-data-composition.c	2008-07-07 03:31:35 UTC (rev 5029)
@@ -48,10 +48,7 @@
 #include "xfburn-data-composition.h"
 #include "xfburn-global.h"
 
-#if 0
 #include "xfburn-adding-progress.h"
-#endif
-
 #include "xfburn-composition.h"
 #include "xfburn-burn-data-cd-composition-dialog.h"
 #include "xfburn-burn-data-dvd-composition-dialog.h"
@@ -61,6 +58,46 @@
 
 #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);
@@ -90,37 +127,36 @@
                                       XfburnDataComposition *);
 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);
 
-static gboolean add_file_to_list_with_name (const gchar *name, XfburnDataComposition * dc, GtkTreeModel * model,
-                                            const gchar * path, GtkTreeIter * iter, GtkTreeIter * insertion,
-                                            GtkTreeViewDropPosition position);
-static gboolean add_file_to_list (XfburnDataComposition * dc, GtkTreeModel * model, const gchar * path, GtkTreeIter * iter,
-                                  GtkTreeIter * insertion, GtkTreeViewDropPosition position);
+/* 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);
                                   
-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;
-
 typedef struct
 {
   gchar *filename;
   gboolean modified;
  
   guint n_new_directory;
+
+  GSList *full_paths_to_add;
+  gchar *selected_files;
+  GtkTreePath *path_where_insert;
+
+  GdkDragContext * dc;
+  gboolean success;
+  gboolean del;
+  guint32 time;
   
   GtkActionGroup *action_group;
   GtkUIManager *ui_manager;
@@ -129,9 +165,8 @@
   GtkWidget *entry_volume_name;
   GtkWidget *content;
   GtkWidget *disc_usage;
-#if 0
   GtkWidget *progress;
-#endif
+
 } XfburnDataCompositionPrivate;
 
 /* globals */
@@ -246,6 +281,8 @@
   {"text/plain", 0, DATA_COMPOSITION_DND_TARGET_TEXT_PLAIN}
   };
 
+  priv->full_paths_to_add = NULL;
+
   instances++;
   
   /* initialize static members */
@@ -365,11 +402,12 @@
                     G_CALLBACK (cb_treeview_button_pressed), composition);
   g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (cb_selection_changed), composition);
                     
-#if 0                    
   /* adding progress window */
-  priv->progress = xfburn_adding_progress_new (); 
-#endif
-  
+  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);
@@ -600,6 +638,7 @@
     if (strcmp (current_filename, filename) == 0) {
       g_free (current_filename);
       gtk_tree_path_free (current_path);
+      gdk_threads_leave ();
       return TRUE;
     }
     
@@ -641,6 +680,32 @@
 }
 
 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_slist_foreach (priv->full_paths_to_add, (GFunc) g_free, NULL);
+    g_slist_free (priv->full_paths_to_add);
+    priv->full_paths_to_add = NULL;
+  }
+
+  xfburn_default_cursor (priv->content);
+}
+
+static void
 action_rename_selection (GtkAction * action, XfburnDataComposition * dc)
 {
   XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
@@ -818,6 +883,7 @@
   g_list_free (references);
 }
 
+
 static void
 action_add_selected_files (GtkAction *action, XfburnDataComposition *dc)
 {
@@ -830,107 +896,35 @@
   selected_files = xfburn_file_browser_get_selection (browser);
   
   if (selected_files) {
-    GtkTreeModel *model;
-    const gchar * file = NULL;
     GtkTreeSelection *selection;
     GList *selected_paths = NULL;
-    GtkTreePath *path_where_insert = NULL;
-    GtkTreeIter iter_where_insert;
-    DataCompositionEntryType type = -1;
+    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);
-    model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
+    params->model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
     
     if (selected_paths) {
-      path_where_insert = (GtkTreePath *) (selected_paths->data);
+      priv->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);
+      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);
     }
     
-    file = strtok (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);
+    priv->selected_files = selected_files;
 
-      if (full_path[strlen (full_path) - 1] == '\r')
-        full_path[strlen (full_path) - 1] = '\0';
-
-      if (strcmp (full_path, g_getenv ("HOME")) == 0) {
-        GtkMessageDialog *dialog = (GtkMessageDialog *) gtk_message_dialog_new (NULL,
-                                        GTK_DIALOG_DESTROY_WITH_PARENT,
-                                        GTK_MESSAGE_WARNING,
-                                        GTK_BUTTONS_YES_NO,
-                                        ((const gchar *) _("Adding home directory")));
-        gint ret;
-        gboolean quit = FALSE;
-        DBG ("Adding home directory");
-        gtk_message_dialog_format_secondary_text (dialog,
-                                        _("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\nAre you sure you want to proceed?"));
-        ret = gtk_dialog_run (GTK_DIALOG (dialog));
-        switch (ret) {
-          case GTK_RESPONSE_YES:
-            break;
-          default:
-            g_free (full_path);
-            quit = TRUE;
-        }
-        xfburn_busy_cursor (GTK_DIALOG (dialog)->vbox);
-        gtk_widget_destroy (GTK_WIDGET (dialog));
-        if (quit)
-          break;
-      }
-
-      /* add files to the disc content */
-      if (type == DATA_COMPOSITION_TYPE_DIRECTORY) {
-        guint64 old_size, size;
-        gchar *humansize = NULL;
-        
-        add_file_to_list (dc, model, full_path, &iter, &iter_where_insert, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
-        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);
-        
-        humansize = xfburn_humanreadable_filesize (old_size + size);
-        
-        gtk_tree_store_set (GTK_TREE_STORE (model), &iter_where_insert, 
-                            DATA_COMPOSITION_COLUMN_HUMANSIZE, humansize,
-                            DATA_COMPOSITION_COLUMN_SIZE, old_size + size, -1);
-        
-        g_free (humansize);
-      } else if (type == DATA_COMPOSITION_TYPE_FILE) {
-        GtkTreeIter parent;
-        
-        if (gtk_tree_model_iter_parent (model, &parent, &iter_where_insert))
-          add_file_to_list (dc, model, full_path, &iter, &parent, GTK_TREE_VIEW_DROP_INTO_OR_AFTER);  
-        else 
-          add_file_to_list (dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
-      } else {
-        add_file_to_list (dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
-      }
-      
-      g_free (full_path);
-
-      file = strtok (NULL, "\n");
-    }
+    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);
-    
-    g_free (selected_files);
   }
-  
-  xfburn_default_cursor (priv->content);
 }
 
 static void
@@ -1004,8 +998,9 @@
 }
 
 static gboolean
-add_file_to_list_with_name (const gchar *name, XfburnDataComposition * dc, GtkTreeModel * model, const gchar * path,
-                            GtkTreeIter * iter, GtkTreeIter * insertion, GtkTreeViewDropPosition position)
+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);
   
@@ -1031,9 +1026,7 @@
     }
     g_free (basename);
     
-#if 0
     xfburn_adding_progress_pulse (XFBURN_ADDING_PROGRESS (priv->progress));
-#endif
     
     /* find parent */
     switch (position){
@@ -1042,10 +1035,12 @@
       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:
@@ -1056,13 +1051,16 @@
     }
   
     /* 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"));
 
@@ -1071,6 +1069,7 @@
       return FALSE;
     }
     gtk_tree_path_free (tree_path);
+    gdk_threads_leave ();
     
     /* new directory */
     if (S_ISDIR (s.st_mode)) {
@@ -1089,6 +1088,7 @@
         return FALSE;
       }
 
+      gdk_threads_enter ();
       gtk_tree_store_append (GTK_TREE_STORE (model), iter, parent);
 
       gtk_tree_store_set (GTK_TREE_STORE (model), iter,
@@ -1097,6 +1097,7 @@
                           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;
@@ -1106,8 +1107,10 @@
         if (new_path) {
           guint64 size;
 
-          if (add_file_to_list (dc, model, new_path, &new_iter, iter, GTK_TREE_VIEW_DROP_INTO_OR_AFTER)) {
+          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; 
           }
           
@@ -1116,31 +1119,34 @@
       }
 
       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;
+      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;
 	  
-	    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);
+      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);
@@ -1165,10 +1171,11 @@
 
       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);
+      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);
@@ -1181,19 +1188,162 @@
   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
-add_file_to_list (XfburnDataComposition * dc, GtkTreeModel * model, const gchar * path, GtkTreeIter * iter,
-                  GtkTreeIter * insertion, GtkTreeViewDropPosition position)
+show_add_home_question_dialog ()
 {
+  GtkMessageDialog *dialog;
+  gint ret;
+  gboolean ok = TRUE;
+
+  gdk_threads_enter ();
+  DBG ("Adding home directory");
+  dialog = (GtkMessageDialog *) gtk_message_dialog_new (NULL,
+                                  GTK_DIALOG_DESTROY_WITH_PARENT,
+                                  GTK_MESSAGE_WARNING,
+                                  GTK_BUTTONS_YES_NO,
+                                  ((const gchar *) _("Adding home directory")));
+  gtk_message_dialog_format_secondary_text (dialog,
+                                  _("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\nAre you sure you want to proceed?"));
+  ret = gtk_dialog_run (GTK_DIALOG (dialog));
+  switch (ret) {
+    case GTK_RESPONSE_YES:
+      break;
+    default:
+      ok = FALSE;
+  }
+  xfburn_busy_cursor (GTK_DIALOG (dialog)->vbox);
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+
+  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 = add_file_to_list_with_name (basename, dc, model, path, iter, insertion, position);
+    ret = thread_add_file_to_list_with_name (basename, dc, model, path, iter, insertion, position);
     
     g_free (basename);
   }
@@ -1318,6 +1468,8 @@
     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) {      
@@ -1363,10 +1515,6 @@
           continue;
       }
 
-      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);
-      
       if (path_where_insert && type == DATA_COMPOSITION_TYPE_DIRECTORY 
           && gtk_tree_path_is_descendant (path_where_insert, path_src)) {
 
@@ -1377,6 +1525,10 @@
         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)) {                
@@ -1435,17 +1587,17 @@
     
     if (path_where_insert)
       gtk_tree_path_free (path_where_insert);  
+    gtk_widget_hide (priv->progress);
+    xfburn_default_cursor (priv->content);
   }
   else if (sd->target == gdk_atom_intern ("text/plain", FALSE)) {
+    ThreadAddFilesDragParams *params;
     const gchar *file = NULL;
 
-#if 0
-    gtk_widget_show (priv->progress);
-#endif
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
     
     file = strtok ((gchar *) sd->data, "\n");
     while (file) {
-      GtkTreeIter iter;
       gchar *full_path;
 
       if (g_str_has_prefix (file, "file://"))
@@ -1458,37 +1610,77 @@
       if (full_path[strlen (full_path) - 1] == '\r')
         full_path[strlen (full_path) - 1] = '\0';
 
-      /* add files to the disc content */
-      if (path_where_insert) {
-        gtk_tree_model_get_iter (model, &iter_where_insert, path_where_insert);
-        
-        if (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)
-            gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), path_where_insert, FALSE);
-        }
-        
-        gtk_tree_path_free (path_where_insert);  
-      } else  {
-        add_file_to_list (composition, model, full_path, &iter, NULL, position);
-      }
-     
-      g_free (full_path);
+      /* remember path to add it later in another thread */
+      priv->full_paths_to_add = g_slist_append (priv->full_paths_to_add, full_path);
 
       file = strtok (NULL, "\n");
     }
 
-#if 0
-    gtk_widget_hide (priv->progress);
-#endif
+    priv->full_paths_to_add = g_slist_reverse (priv->full_paths_to_add);
+
+    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);
+
+    g_thread_create ((GThreadFunc) thread_add_files_drag, params, FALSE, NULL);
+
     gtk_drag_finish (dc, TRUE, FALSE, t);
   } else {
     gtk_drag_finish (dc, FALSE, FALSE, t);
+    xfburn_default_cursor (priv->content);
   }
-  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;
+  GSList *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_slist_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 {
@@ -1589,6 +1781,7 @@
 {
   LoadParserStruct * parserinfo = (LoadParserStruct *) data;
   XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (parserinfo->dc);
+
   
   if (!(parserinfo->started) && !strcmp (element_name, "xfburn-composition"))
     parserinfo->started = TRUE;
@@ -1600,15 +1793,18 @@
 
     if ((i = _find_attribute (attribute_names, "name")) != -1 &&
         (j = _find_attribute (attribute_names, "source")) != -1) {
-      GtkTreeIter iter;
+      //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;
@@ -1817,28 +2013,20 @@
 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) {
-    XfburnDataCompositionPrivate *priv = XFBURN_DATA_COMPOSITION_GET_PRIVATE (dc);
+    params = g_new (ThreadAddFilesCLIParams, 1);
 
-    GtkTreeModel *model;
-    int i;
-    gchar *full_path = NULL;
+    params->filenames = filenames;
+    params->filec = filec;
+    params->dc = dc;
 
-    model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->content));
-
+    xfburn_adding_progress_show (XFBURN_ADDING_PROGRESS (priv->progress));
     xfburn_busy_cursor (priv->content);
 
-    for (i=0; i<filec; i++) {
-      GtkTreeIter iter;
-      
-      g_message ("Adding %s to the data composition... (might take a while)", filenames[i]);
-
-      full_path = g_build_filename (filenames[i], NULL);
-
-      add_file_to_list (dc, model, full_path, &iter, NULL, GTK_TREE_VIEW_DROP_AFTER);  
-    }
-
-    xfburn_default_cursor (priv->content);
+    g_thread_create ((GThreadFunc) thread_add_files_cli, params, FALSE, NULL);
   }
 }
 




More information about the Goodies-commits mailing list