[Xfce4-commits] <thunar:master> Initial import of the shared progress dialog.

Jannis Pohlmann jannis at xfce.org
Sun Sep 13 15:52:01 CEST 2009


Updating branch refs/heads/master
         to 1fca6edc38868a1636214e41d1e6e65638bb8581 (commit)
       from 1559dd2d14da591f89be1b9af3d874e593082cbc (commit)

commit 1fca6edc38868a1636214e41d1e6e65638bb8581
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Sat Sep 12 15:40:35 2009 +0200

    Initial import of the shared progress dialog.
    
    This introduces a new view called ThunarProgressView which essentially
    replaces the old ThunarProgressDialog. The new ThunarProgressDialog is a
    container GtkWindow (I wonder about renaming it to ThunarProgressWindow)
    for all the ThunarProgressViews associated with running file operations.
    
    ThunarProgressDialog also creates a status icon that can be used to
    toggle its visibility.
    
    Things left on the TODO list:
    - Check if we can lower the CPU usage of the dialog (X goes up to
      around 50% on my machine with the dialog visible), compare this to
      the situation before.
    - Double-check if the use of gtk_window_present() is correct here.
    - Either prepend (instead of append) new views or scroll down to them
      upon their creation.

 thunar/Makefile.am              |    2 +
 thunar/thunar-application.c     |   62 +++--
 thunar/thunar-application.h     |  174 ++++++------
 thunar/thunar-progress-dialog.c |  564 +++++++++++------------------------
 thunar/thunar-progress-dialog.h |   52 ++--
 thunar/thunar-progress-view.c   |  618 +++++++++++++++++++++++++++++++++++++++
 thunar/thunar-progress-view.h   |   55 ++++
 7 files changed, 1003 insertions(+), 524 deletions(-)

diff --git a/thunar/Makefile.am b/thunar/Makefile.am
index 241c739..b286fc5 100644
--- a/thunar/Makefile.am
+++ b/thunar/Makefile.am
@@ -146,6 +146,8 @@ Thunar_SOURCES =							\
 	thunar-private.h						\
 	thunar-progress-dialog.c					\
 	thunar-progress-dialog.h					\
+	thunar-progress-view.c						\
+	thunar-progress-view.h						\
 	thunar-properties-dialog.c					\
 	thunar-properties-dialog.h					\
 	thunar-renamer-dialog.c						\
diff --git a/thunar/thunar-application.c b/thunar/thunar-application.c
index 98f01ae..a4bf914 100644
--- a/thunar/thunar-application.c
+++ b/thunar/thunar-application.c
@@ -123,6 +123,7 @@ struct _ThunarApplication
   GObject                __parent__;
 
   ThunarPreferences     *preferences;
+  GtkWidget             *progress_dialog;
   GList                 *windows;
 
   gboolean               daemon;
@@ -194,6 +195,7 @@ thunar_application_init (ThunarApplication *application)
   application->preferences = thunar_preferences_get ();
 
   application->files_to_launch = NULL;
+  application->progress_dialog = NULL;
 
   /* check if we have a saved accel map */
   path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm");
@@ -253,7 +255,7 @@ thunar_application_finalize (GObject *object)
   if (G_UNLIKELY (application->show_dialogs_timer_id != 0))
     g_source_remove (application->show_dialogs_timer_id);
 
-  /* drop the open windows */
+  /* drop the open windows (this includes the progress dialog) */
   for (lp = application->windows; lp != NULL; lp = lp->next)
     {
       g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), G_CALLBACK (thunar_application_window_destroyed), application);
@@ -386,7 +388,6 @@ thunar_application_launch (ThunarApplication *application,
                            GList             *target_file_list,
                            GClosure          *new_files_closure)
 {
-  GtkWindow *window;
   GtkWidget *dialog;
   GdkScreen *screen;
   ThunarJob *job;
@@ -394,7 +395,7 @@ thunar_application_launch (ThunarApplication *application,
   _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent));
 
   /* parse the parent pointer */
-  screen = thunar_util_parse_parent (parent, &window);
+  screen = thunar_util_parse_parent (parent, NULL);
 
   /* try to allocate a new job for the operation */
   job = (*launcher) (source_file_list, target_file_list);
@@ -403,31 +404,23 @@ thunar_application_launch (ThunarApplication *application,
   if (G_LIKELY (new_files_closure != NULL))
     g_signal_connect_closure (job, "new-files", new_files_closure, FALSE);
 
-  /* allocate a progress dialog for the job */
-  dialog = g_object_new (THUNAR_TYPE_PROGRESS_DIALOG,
-                         "icon-name", icon_name,
-                         "title", title,
-                         "job", job,
-                         "screen", screen,
-                         NULL);
-
-  /* connect to the parent (if any) */
-  if (G_LIKELY (window != NULL))
-    gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
+  /* get the shared progress dialog */
+  dialog = thunar_application_get_progress_dialog (application);
 
-  /* be sure to destroy the dialog when the job is done */
-  g_signal_connect_after (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), dialog);
+  /* place the dialog on the given screen */
+  if (screen != NULL)
+    gtk_window_set_screen (GTK_WINDOW (dialog), screen);
 
-  /* hook up the dialog window */
-  thunar_application_take_window (application, GTK_WINDOW (dialog));
+  thunar_progress_dialog_add_job (THUNAR_PROGRESS_DIALOG (dialog), job, icon_name, title);
 
   /* Set up a timer to show the dialog, to make sure we don't
    * just popup and destroy a dialog for a very short job.
    */
   if (G_LIKELY (application->show_dialogs_timer_id == 0))
     {
-      application->show_dialogs_timer_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 750, thunar_application_show_dialogs,
-                                                               application, thunar_application_show_dialogs_destroy);
+      application->show_dialogs_timer_id = 
+        g_timeout_add_full (G_PRIORITY_DEFAULT, 750, thunar_application_show_dialogs,
+                            application, thunar_application_show_dialogs_destroy);
     }
 
   /* drop our reference on the job */
@@ -692,14 +685,12 @@ static gboolean
 thunar_application_show_dialogs (gpointer user_data)
 {
   ThunarApplication *application = THUNAR_APPLICATION (user_data);
-  GList             *lp;
 
   GDK_THREADS_ENTER ();
 
-  /* show all progress dialogs */
-  for (lp = application->windows; lp != NULL; lp = lp->next)
-    if (THUNAR_IS_PROGRESS_DIALOG (lp->data))
-      gtk_widget_show (GTK_WIDGET (lp->data));
+  /* show the progress dialog */
+  if (application->progress_dialog != NULL)
+    gtk_window_present (GTK_WINDOW (application->progress_dialog));
 
   GDK_THREADS_LEAVE ();
 
@@ -1021,6 +1012,27 @@ thunar_application_bulk_rename (ThunarApplication *application,
 
 
 
+GtkWidget *
+thunar_application_get_progress_dialog (ThunarApplication *application)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), NULL);
+
+  if (application->progress_dialog == NULL)
+    {
+      application->progress_dialog = thunar_progress_dialog_new ();
+
+      g_object_add_weak_pointer (G_OBJECT (application->progress_dialog),
+                                 (gpointer) &application->progress_dialog);
+
+      thunar_application_take_window (application, 
+                                      GTK_WINDOW (application->progress_dialog));
+    }
+
+  return application->progress_dialog;
+}
+
+
+
 static void
 thunar_application_process_files_finish (ThunarBrowser *browser,
                                          ThunarFile    *file,
diff --git a/thunar/thunar-application.h b/thunar/thunar-application.h
index d90dd28..8fdf401 100644
--- a/thunar/thunar-application.h
+++ b/thunar/thunar-application.h
@@ -36,92 +36,94 @@ typedef struct _ThunarApplication      ThunarApplication;
 #define THUNAR_IS_APPLICATION_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_APPLICATION))
 #define THUNAR_APPLICATION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_APPLICATION, ThunarApplicationClass))
 
-GType              thunar_application_get_type          (void) G_GNUC_CONST;
-
-ThunarApplication *thunar_application_get               (void);
-
-gboolean           thunar_application_get_daemon        (ThunarApplication *application);
-void               thunar_application_set_daemon        (ThunarApplication *application,
-                                                         gboolean           daemon);
-
-GList             *thunar_application_get_windows       (ThunarApplication *application);
-
-gboolean           thunar_application_has_windows       (ThunarApplication *application);
-
-void               thunar_application_take_window       (ThunarApplication *application,
-                                                         GtkWindow         *window);
-
-GtkWidget         *thunar_application_open_window       (ThunarApplication *application,
-                                                         ThunarFile        *directory,
-                                                         GdkScreen         *screen,
-                                                         const gchar       *startup_id);
-
-gboolean           thunar_application_bulk_rename       (ThunarApplication *application,
-                                                         const gchar       *working_directory,
-                                                         gchar            **filenames,
-                                                         gboolean           standalone,
-                                                         GdkScreen         *screen,
-                                                         const gchar       *startup_id,
-                                                         GError           **error);
-
-gboolean           thunar_application_process_filenames (ThunarApplication *application,
-                                                         const gchar       *working_directory,
-                                                         gchar            **filenames,
-                                                         GdkScreen         *screen,
-                                                         const gchar       *startup_id,
-                                                         GError           **error);
-
-gboolean           thunar_application_is_processing     (ThunarApplication *application);
-
-void               thunar_application_copy_to           (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *source_file_list,
-                                                         GList             *target_file_list,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_copy_into         (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *source_file_list,
-                                                         GFile             *target_file,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_link_into         (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *source_file_list,
-                                                         GFile             *target_file,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_move_into         (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *source_file_list,
-                                                         GFile             *target_file,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_unlink_files      (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *file_list);
-
-void               thunar_application_trash             (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *file_list);
-
-void               thunar_application_creat             (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *file_list,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_mkdir             (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *file_list,
-                                                         GClosure          *new_files_closure);
-
-void               thunar_application_empty_trash       (ThunarApplication *application,
-                                                         gpointer           parent);
-
-void               thunar_application_restore_files     (ThunarApplication *application,
-                                                         gpointer           parent,
-                                                         GList             *trash_file_list,
-                                                         GClosure          *new_files_closure);
+GType              thunar_application_get_type            (void) G_GNUC_CONST;
+
+ThunarApplication *thunar_application_get                 (void);
+
+gboolean           thunar_application_get_daemon          (ThunarApplication *application);
+void               thunar_application_set_daemon          (ThunarApplication *application,
+                                                           gboolean           daemon);
+
+GList             *thunar_application_get_windows         (ThunarApplication *application);
+
+gboolean           thunar_application_has_windows         (ThunarApplication *application);
+
+void               thunar_application_take_window         (ThunarApplication *application,
+                                                           GtkWindow         *window);
+
+GtkWidget         *thunar_application_open_window         (ThunarApplication *application,
+                                                           ThunarFile        *directory,
+                                                           GdkScreen         *screen,
+                                                           const gchar       *startup_id);
+
+gboolean           thunar_application_bulk_rename         (ThunarApplication *application,
+                                                           const gchar       *working_directory,
+                                                           gchar            **filenames,
+                                                           gboolean           standalone,
+                                                           GdkScreen         *screen,
+                                                           const gchar       *startup_id,
+                                                           GError           **error);
+
+GtkWidget         *thunar_application_get_progress_dialog (ThunarApplication *application);
+
+gboolean           thunar_application_process_filenames   (ThunarApplication *application,
+                                                           const gchar       *working_directory,
+                                                           gchar            **filenames,
+                                                           GdkScreen         *screen,
+                                                           const gchar       *startup_id,
+                                                           GError           **error);
+
+gboolean           thunar_application_is_processing       (ThunarApplication *application);
+
+void               thunar_application_copy_to             (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *source_file_list,
+                                                           GList             *target_file_list,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_copy_into           (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *source_file_list,
+                                                           GFile             *target_file,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_link_into           (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *source_file_list,
+                                                           GFile             *target_file,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_move_into           (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *source_file_list,
+                                                           GFile             *target_file,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_unlink_files        (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *file_list);
+
+void               thunar_application_trash               (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *file_list);
+
+void               thunar_application_creat               (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *file_list,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_mkdir               (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *file_list,
+                                                           GClosure          *new_files_closure);
+
+void               thunar_application_empty_trash         (ThunarApplication *application,
+                                                           gpointer           parent);
+
+void               thunar_application_restore_files       (ThunarApplication *application,
+                                                           gpointer           parent,
+                                                           GList             *trash_file_list,
+                                                           GClosure          *new_files_closure);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-progress-dialog.c b/thunar/thunar-progress-dialog.c
index 2d5b4e6..8942123 100644
--- a/thunar/thunar-progress-dialog.c
+++ b/thunar/thunar-progress-dialog.c
@@ -1,126 +1,78 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2009 Jannis Pohlmann <jannis 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 free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA  02111-1307  USA
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <thunar/thunar-dialogs.h>
-#include <thunar/thunar-gobject-extensions.h>
-#include <thunar/thunar-job.h>
-#include <thunar/thunar-pango-extensions.h>
+#include <gtk/gtk.h>
+
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-progress-dialog.h>
+#include <thunar/thunar-progress-view.h>
 
 
 
-enum
-{
-  PROP_0,
-  PROP_JOB,
-};
-
-
-
-static void              thunar_progress_dialog_dispose      (GObject                    *object);
-static void              thunar_progress_dialog_get_property (GObject                    *object,
-                                                              guint                       prop_id,
-                                                              GValue                     *value,
-                                                              GParamSpec                 *pspec);
-static void              thunar_progress_dialog_set_property (GObject                    *object,
-                                                              guint                       prop_id,
-                                                              const GValue               *value,
-                                                              GParamSpec                 *pspec);
-static void              thunar_progress_dialog_response     (GtkDialog                  *dialog,
-                                                              gint                        response);
-static ThunarJobResponse thunar_progress_dialog_ask          (ThunarProgressDialog       *dialog,
-                                                              const gchar                *message,
-                                                              ThunarJobResponse           choices,
-                                                              ThunarJob                  *job);
-static ThunarJobResponse thunar_progress_dialog_ask_replace  (ThunarProgressDialog       *dialog,
-                                                              ThunarFile                 *src_file,
-                                                              ThunarFile                 *dst_file,
-                                                              ThunarJob                  *job);
-static void              thunar_progress_dialog_error        (ThunarProgressDialog       *dialog,
-                                                              GError                     *error,
-                                                              ExoJob                     *job);
-static void              thunar_progress_dialog_finished     (ThunarProgressDialog       *dialog,
-                                                              ExoJob                     *job);
-static void              thunar_progress_dialog_info_message (ThunarProgressDialog       *dialog,
-                                                              const gchar                *message,
-                                                              ExoJob                     *job);
-static void              thunar_progress_dialog_percent      (ThunarProgressDialog       *dialog,
-                                                              gdouble                     percent,
-                                                              ExoJob                     *job);
+static void     thunar_progress_dialog_dispose  (GObject              *object);
+static void     thunar_progress_dialog_finalize (GObject              *object);
+static gboolean thunar_progress_dialog_closed   (ThunarProgressDialog *dialog);
+static gboolean thunar_progress_dialog_toggled  (ThunarProgressDialog *dialog, 
+                                                 GdkEventButton       *button,
+                                                 GtkStatusIcon        *status_icon);
 
 
 
 struct _ThunarProgressDialogClass
 {
-  GtkDialogClass __parent__;
+  GtkWindowClass __parent__;
 };
 
 struct _ThunarProgressDialog
 {
-  GtkDialog  __parent__;
+  GtkWindow      __parent__;
 
-  ThunarJob *job;
+  GtkStatusIcon *status_icon;
+  GtkWidget     *scrollwin;
+  GtkWidget     *vbox;
+  GtkWidget     *content_box;
 
-  GTimeVal   start_time;
-  GTimeVal   last_update_time;
-
-  GtkWidget *progress_bar;
-  GtkWidget *progress_label;
+  GList         *views;
 };
 
 
 
-G_DEFINE_TYPE (ThunarProgressDialog, thunar_progress_dialog, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE (ThunarProgressDialog, thunar_progress_dialog, GTK_TYPE_WINDOW);
 
 
 
 static void
 thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass)
 {
-  GtkDialogClass *gtkdialog_class;
-  GObjectClass   *gobject_class;
+  GObjectClass *gobject_class;
+
+  /* Determine parent type class */
+  thunar_progress_dialog_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->dispose = thunar_progress_dialog_dispose;
-  gobject_class->get_property = thunar_progress_dialog_get_property;
-  gobject_class->set_property = thunar_progress_dialog_set_property;
-
-  gtkdialog_class = GTK_DIALOG_CLASS (klass);
-  gtkdialog_class->response = thunar_progress_dialog_response;
-
-  /**
-   * ThunarProgressDialog:job:
-   *
-   * The #ThunarJob, whose progress is displayed by this dialog, or 
-   * %NULL if no job is set.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_JOB,
-                                   g_param_spec_object ("job", "job", "job",
-                                                        THUNAR_TYPE_JOB,
-                                                        EXO_PARAM_READWRITE));
+  gobject_class->finalize = thunar_progress_dialog_finalize;
 }
 
 
@@ -128,387 +80,227 @@ thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass)
 static void
 thunar_progress_dialog_init (ThunarProgressDialog *dialog)
 {
-  GtkWidget *table;
-  GtkWidget *image;
-  GtkWidget *label;
-
-  /* remember the current time as start time */
-  g_get_current_time (&dialog->start_time);
-
-  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
-  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-  gtk_window_set_default_size (GTK_WINDOW (dialog), 350, -1);
-  gtk_window_set_title (GTK_WINDOW (dialog), "");
-
-  table = g_object_new (GTK_TYPE_TABLE,
-                        "border-width", 6,
-                        "n-columns", 3,
-                        "n-rows", 3,
-                        "row-spacing", 6,
-                        "column-spacing", 5,
-                        NULL);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0);
-  gtk_widget_show (table);
-
-  image = g_object_new (GTK_TYPE_IMAGE, "icon-size", GTK_ICON_SIZE_BUTTON, NULL);
-  gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 1, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 6);
-  gtk_widget_show (image);
-
-  label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
-  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big ());
-  gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 6);
-  gtk_widget_show (label);
-
-  dialog->progress_label = g_object_new (GTK_TYPE_LABEL, "ellipsize", PANGO_ELLIPSIZE_START, "xalign", 0.0f, NULL);
-  gtk_table_attach (GTK_TABLE (table), dialog->progress_label, 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
-  gtk_widget_show (dialog->progress_label);
-
-  dialog->progress_bar = g_object_new (GTK_TYPE_PROGRESS_BAR, "text", " ", NULL);
-  gtk_table_attach (GTK_TABLE (table), dialog->progress_bar, 0, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
-  gtk_widget_show (dialog->progress_bar);
-
-  /* connect the window icon name to the action image */
-  exo_binding_new (G_OBJECT (dialog), "icon-name",
-                   G_OBJECT (image), "icon-name");
-
-  /* connect the window title to the action label */
-  exo_binding_new (G_OBJECT (dialog), "title",
-                   G_OBJECT (label), "label");
-}
+  dialog->views = NULL;
 
+  gtk_window_set_title (GTK_WINDOW (dialog), _("File Operation Progress"));
+  gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 10);
+  gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL);
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), FALSE);
+  gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
 
+  g_signal_connect (dialog, "delete-event", 
+                    G_CALLBACK (thunar_progress_dialog_closed), dialog);
 
-static void
-thunar_progress_dialog_dispose (GObject *object)
-{
-  ThunarProgressDialog *dialog = THUNAR_PROGRESS_DIALOG (object);
+  dialog->vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
+  gtk_widget_show (dialog->vbox);
 
-  /* disconnect from the job (if any) */
-  thunar_progress_dialog_set_job (dialog, NULL);
+  dialog->content_box = gtk_vbox_new (FALSE, 12);
+  gtk_container_set_border_width (GTK_CONTAINER (dialog->content_box), 8);
+  gtk_container_add (GTK_CONTAINER (dialog->vbox), dialog->content_box);
+  gtk_widget_show (dialog->content_box);
 
-  (*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->dispose) (object);
+  dialog->status_icon = gtk_status_icon_new_from_stock (GTK_STOCK_DIRECTORY);
+  gtk_status_icon_set_visible (dialog->status_icon, FALSE);
+
+  g_signal_connect_swapped (dialog->status_icon, "button-press-event", 
+                            G_CALLBACK (thunar_progress_dialog_toggled), 
+                            GTK_WIDGET (dialog));
 }
 
 
 
 static void
-thunar_progress_dialog_get_property (GObject    *object,
-                                     guint       prop_id,
-                                     GValue     *value,
-                                     GParamSpec *pspec)
+thunar_progress_dialog_dispose (GObject *object)
 {
-  ThunarProgressDialog *dialog = THUNAR_PROGRESS_DIALOG (object);
-
-  switch (prop_id)
-    {
-    case PROP_JOB:
-      g_value_set_object (value, thunar_progress_dialog_get_job (dialog));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
+  (*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->dispose) (object);
 }
 
 
 
 static void
-thunar_progress_dialog_set_property (GObject      *object,
-                                     guint         prop_id,
-                                     const GValue *value,
-                                     GParamSpec   *pspec)
+thunar_progress_dialog_finalize (GObject *object)
 {
   ThunarProgressDialog *dialog = THUNAR_PROGRESS_DIALOG (object);
 
-  switch (prop_id)
-    {
-    case PROP_JOB:
-      thunar_progress_dialog_set_job (dialog, g_value_get_object (value));
-      break;
+  /* destroy the status icon */
+  g_object_unref (dialog->status_icon);
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
+  /* free the view list */
+  g_list_free (dialog->views);
+
+  (*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->finalize) (object);
 }
 
 
 
-static ThunarJobResponse
-thunar_progress_dialog_ask (ThunarProgressDialog *dialog,
-                            const gchar          *message,
-                            ThunarJobResponse     choices,
-                            ThunarJob            *job)
+static gboolean
+thunar_progress_dialog_closed (ThunarProgressDialog *dialog)
 {
-  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (dialog->job == job, THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
 
-  /* be sure to display the progress dialog prior to opening the question dialog */
-  gtk_widget_show_now (GTK_WIDGET (dialog));
+  /* hide the progress dialog */
+  gtk_widget_hide (GTK_WIDGET (dialog));
 
-  /* display the question dialog */
-  return thunar_dialogs_show_job_ask (GTK_WINDOW (dialog), message, choices);
+  /* don't destroy the dialog */
+  return TRUE;
 }
 
 
 
-static ThunarJobResponse
-thunar_progress_dialog_ask_replace (ThunarProgressDialog *dialog,
-                                    ThunarFile           *src_file,
-                                    ThunarFile           *dst_file,
-                                    ThunarJob            *job)
+static gboolean
+thunar_progress_dialog_toggled (ThunarProgressDialog *dialog,
+                                GdkEventButton       *event,
+                                GtkStatusIcon        *status_icon)
 {
-  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (dialog->job == job, THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL);
-  _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
+  _thunar_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
 
-  /* be sure to display the progress dialog prior to opening the question dialog */
-  gtk_widget_show_now (GTK_WIDGET (dialog));
+  /* toggle the visibility of the progress dialog */
+  if (GTK_WIDGET_VISIBLE (GTK_WIDGET (dialog)))
+    gtk_widget_hide (GTK_WIDGET (dialog));
+  else
+    gtk_widget_show (GTK_WIDGET (dialog));
 
-  /* display the question dialog */
-  return thunar_dialogs_show_job_ask_replace (GTK_WINDOW (dialog), src_file, dst_file);
+  return TRUE;
 }
 
 
 
 static void
-thunar_progress_dialog_error (ThunarProgressDialog *dialog,
-                              GError               *error,
-                              ExoJob               *job)
+thunar_progress_dialog_view_needs_attention (ThunarProgressDialog *dialog,
+                                             ThunarProgressView   *view)
 {
   _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
-  _thunar_return_if_fail (error != NULL && error->message != NULL);
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
-  _thunar_return_if_fail (dialog->job == THUNAR_JOB (job));
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
 
-  /* be sure to display the progress dialog prior to opening the error dialog */
-  gtk_widget_show_now (GTK_WIDGET (dialog));
+  /* TODO scroll to the view */
 
-  /* display the error message */
-  thunar_dialogs_show_job_error (GTK_WINDOW (dialog), error);
+  /* raise the dialog */
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 
 
 static void
-thunar_progress_dialog_finished (ThunarProgressDialog *dialog,
-                                 ExoJob               *job)
+thunar_progress_dialog_job_finished (ThunarProgressDialog *dialog,
+                                     ThunarProgressView   *view)
 {
-  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
-  _thunar_return_if_fail (dialog->job == THUNAR_JOB (job));
-
-  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
-}
-
+  guint n_views;
 
-
-static void
-thunar_progress_dialog_info_message (ThunarProgressDialog *dialog,
-                                     const gchar          *message,
-                                     ExoJob               *job)
-{
   _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
-  _thunar_return_if_fail (g_utf8_validate (message, -1, NULL));
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
-  _thunar_return_if_fail (dialog->job == THUNAR_JOB (job));
-
-  gtk_label_set_text (GTK_LABEL (dialog->progress_label), message);
-}
-
-
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
 
-static inline guint64
-time_diff (const GTimeVal *now,
-           const GTimeVal *last)
-{
-  return ((guint64) now->tv_sec - last->tv_sec) * G_USEC_PER_SEC
-       + ((guint64) last->tv_usec - last->tv_usec);
-}
+  /* remove the view from the list */
+  dialog->views = g_list_remove (dialog->views, view);
 
+  /* destroy the widget */
+  gtk_widget_destroy (GTK_WIDGET (view));
 
+  /* determine the number of views left */
+  n_views = g_list_length (dialog->views);
 
-static void
-thunar_progress_dialog_percent (ThunarProgressDialog *dialog,
-                                gdouble               percent,
-                                ExoJob               *job)
-{
-  GTimeVal current_time;
-  gulong   remaining_time;
-  gulong   elapsed_time;
-  gchar    text[512];
-
-  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
-  _thunar_return_if_fail (percent >= 0.0 && percent <= 100.0);
-  _thunar_return_if_fail (THUNAR_IS_JOB (job));
-  _thunar_return_if_fail (dialog->job == THUNAR_JOB (job));
-
-  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (dialog->progress_bar), percent / 100.0);
-
-  /* check if we should update the time display (every 400ms) */
-  g_get_current_time (&current_time);
-  if (time_diff (&current_time, &dialog->last_update_time) > 400 * 1000)
+  /* check if we've just removed the 4th view and are now left with
+   * 3 of them, in which case we drop the scroll window */
+  if (n_views == 3)
     {
-      /* calculate the remaining time (in seconds) */
-      elapsed_time = time_diff (&current_time, &dialog->start_time) / 1000;
-      remaining_time = ((100 * elapsed_time) / percent - elapsed_time) / 1000;
-
-      /* setup the time label */
-      if (G_LIKELY (remaining_time > 0))
-        {
-          /* format the time text */
-          if (remaining_time > 60 * 60)
-            {
-              remaining_time = (gulong) (remaining_time / (60 * 60));
-              g_snprintf (text, sizeof (text), ngettext ("(%lu hour remaining)", "(%lu hours remaining)", remaining_time), remaining_time);
-            }
-          else if (remaining_time > 60)
-            {
-              remaining_time = (gulong) (remaining_time / 60);
-              g_snprintf (text, sizeof (text), ngettext ("(%lu minute remaining)", "(%lu minutes remaining)", remaining_time), remaining_time);
-            }
-          else
-            {
-              remaining_time = remaining_time;
-              g_snprintf (text, sizeof (text), ngettext ("(%lu second remaining)", "(%lu seconds remaining)", remaining_time), remaining_time);
-            }
-
-          /* apply the time text */
-          gtk_progress_bar_set_text (GTK_PROGRESS_BAR (dialog->progress_bar), text);
-        }
-      else
-        {
-          /* display an empty label */
-          gtk_progress_bar_set_text (GTK_PROGRESS_BAR (dialog->progress_bar), " ");
-        }
-
-      /* remember the current time as last update time */
-      dialog->last_update_time = current_time;
-    }
-}
-
+      /* reparent the content box */
+      gtk_widget_reparent (dialog->content_box, dialog->vbox);
 
+      /* destroy the scroll win */
+      gtk_widget_destroy (dialog->scrollwin);
+    }
 
-static void
-thunar_progress_dialog_response (GtkDialog *dialog,
-                                 gint       response)
-{
-  /* cancel the job appropriately */
-  switch (response)
+  /* check if we have less than 4 views and need to shrink the window */
+  if (n_views <= 3)
     {
-    case GTK_RESPONSE_NONE:
-    case GTK_RESPONSE_REJECT:
-    case GTK_RESPONSE_DELETE_EVENT:
-    case GTK_RESPONSE_CANCEL:
-    case GTK_RESPONSE_CLOSE:
-    case GTK_RESPONSE_NO:
-      if (G_LIKELY (THUNAR_PROGRESS_DIALOG (dialog)->job != NULL))
-        exo_job_cancel (EXO_JOB (THUNAR_PROGRESS_DIALOG (dialog)->job));
-      break;
+      /* try to shrink the window */
+      gtk_window_resize (GTK_WINDOW (dialog), 400, 10);
     }
 
-  if (GTK_DIALOG_CLASS (thunar_progress_dialog_parent_class)->response != NULL)
-    (*GTK_DIALOG_CLASS (thunar_progress_dialog_parent_class)->response) (dialog, response);
+  /* destroy the dialog if there are no views left */
+  if (dialog->views == NULL)
+    gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 
 
-/**
- * thunar_progress_dialog_new:
- *
- * Allocates a new #ThunarProgressDialog.
- *
- * Return value: the newly allocated #ThunarProgressDialog.
- **/
 GtkWidget*
 thunar_progress_dialog_new (void)
 {
-  return thunar_progress_dialog_new_with_job (NULL);
-}
-
-
-
-/**
- * thunar_progress_dialog_new_with_job:
- * @job : a #ThunarJob or %NULL.
- *
- * Allocates a new #ThunarProgressDialog and associates it with the @job.
- *
- * Return value: the newly allocated #ThunarProgressDialog.
- **/
-GtkWidget*
-thunar_progress_dialog_new_with_job (ThunarJob *job)
-{
-  _thunar_return_val_if_fail (job == NULL || THUNAR_IS_JOB (job), NULL);
-  return g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, "job", job, NULL);
-}
-
-
-
-/**
- * thunar_progress_dialog_get_job:
- * @dialog : a #ThunarProgressDialog.
- *
- * Returns the #ThunarJob associated with @dialog
- * or %NULL if no job is currently associated with @dialog.
- *
- * Return value: the job associated with @dialog or %NULL.
- **/
-ThunarJob *
-thunar_progress_dialog_get_job (ThunarProgressDialog *dialog)
-{
-  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), NULL);
-  return dialog->job;
+  return g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, NULL);
 }
 
 
 
-/**
- * thunar_progress_dialog_set_job:
- * @dialog : a #ThunarProgressDialog.
- * @job    : a #ThunarJob or %NULL.
- *
- * Associates @job with @dialog.
- **/
 void
-thunar_progress_dialog_set_job (ThunarProgressDialog *dialog,
-                                ThunarJob            *job)
+thunar_progress_dialog_add_job (ThunarProgressDialog *dialog,
+                                ThunarJob            *job,
+                                const gchar          *icon_name,
+                                const gchar          *title)
 {
-  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
-  _thunar_return_if_fail (job == NULL || THUNAR_IS_JOB (job));
-
-  /* check if we're already on that job */
-  if (G_UNLIKELY (dialog->job == job))
-    return;
+  GtkWidget *viewport;
+  GtkWidget *view;
+  gchar     *tooltip_text;
+  guint      n_views;
 
-  /* disconnect from the previous job */
-  if (G_LIKELY (dialog->job != NULL))
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  _thunar_return_if_fail (g_utf8_validate (title, -1, NULL));
+
+  view = thunar_progress_view_new_with_job (job);
+  thunar_progress_view_set_icon_name (THUNAR_PROGRESS_VIEW (view), icon_name);
+  thunar_progress_view_set_title (THUNAR_PROGRESS_VIEW (view), title);
+  gtk_box_pack_start (GTK_BOX (dialog->content_box), view, FALSE, TRUE, 0);
+  gtk_widget_show (view);
+  
+  /* add the view to the list of known views */
+  dialog->views = g_list_prepend (dialog->views, view);
+
+  /* determine the number of views now being active */
+  n_views = g_list_length (dialog->views);
+
+  /* check if we need to wrap the views in a scroll window (starting 
+   * at 4 parallel operations */
+  if (n_views == 4)
     {
-      g_signal_handlers_disconnect_matched (dialog->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, dialog);
-      g_object_unref (G_OBJECT (dialog->job));
+      /* create a scrolled window and add it to the dialog */
+      dialog->scrollwin = gtk_scrolled_window_new (NULL, NULL);
+      gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (dialog->scrollwin),
+                                           GTK_SHADOW_NONE);
+      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->scrollwin), 
+                                      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+      gtk_container_add (GTK_CONTAINER (dialog->vbox), dialog->scrollwin);
+      gtk_widget_show (dialog->scrollwin);
+
+      /* create a viewport for the content box */
+      viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (dialog->scrollwin)),
+                                   gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (dialog->scrollwin)));
+      gtk_container_add (GTK_CONTAINER (dialog->scrollwin), viewport);
+      gtk_widget_show (viewport);
+
+      /* move the content box into the viewport */
+      gtk_widget_reparent (dialog->content_box, viewport);
     }
 
-  /* activate the new job */
-  dialog->job = job;
+  g_signal_connect_swapped (view, "need-attention", 
+                            G_CALLBACK (thunar_progress_dialog_view_needs_attention), dialog);
 
-  /* connect to the new job */
-  if (G_LIKELY (job != NULL))
-    {
-      g_object_ref (job);
-
-      g_signal_connect_swapped (job, "ask", G_CALLBACK (thunar_progress_dialog_ask), dialog);
-      g_signal_connect_swapped (job, "ask-replace", G_CALLBACK (thunar_progress_dialog_ask_replace), dialog);
-      g_signal_connect_swapped (job, "error", G_CALLBACK (thunar_progress_dialog_error), dialog);
-      g_signal_connect_swapped (job, "finished", G_CALLBACK (thunar_progress_dialog_finished), dialog);
-      g_signal_connect_swapped (job, "info-message", G_CALLBACK (thunar_progress_dialog_info_message), dialog);
-      g_signal_connect_swapped (job, "percent", G_CALLBACK (thunar_progress_dialog_percent), dialog);
-    }
+  g_signal_connect_swapped (view, "finished",
+                            G_CALLBACK (thunar_progress_dialog_job_finished), dialog);
 
-  g_object_notify (G_OBJECT (dialog), "job");
-}
+  /* make the status icon visible */
+  gtk_status_icon_set_visible (dialog->status_icon, TRUE);
 
+  /* set status icon tooltip */
+  tooltip_text = g_strdup_printf (ngettext ("1 file operation running", "%d file operations running",
+                                            n_views), 
+                                  n_views);
+#if GTK_CHECK_VERSION (2, 16, 0)
+  gtk_status_icon_set_tooltip_text (dialog->status_icon, tooltip_text);
+#else
+  gtk_status_icon_set_tooltip (dialog->status_icon, tooltip_text);
+#endif
+  g_free (tooltip_text);
+}
diff --git a/thunar/thunar-progress-dialog.h b/thunar/thunar-progress-dialog.h
index cb1dd51..e4bdbf8 100644
--- a/thunar/thunar-progress-dialog.h
+++ b/thunar/thunar-progress-dialog.h
@@ -1,28 +1,27 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2009 Jannis Pohlmann <jannis 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 free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA  02111-1307  USA
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifndef __THUNAR_PROGRESS_DIALOG_H__
 #define __THUNAR_PROGRESS_DIALOG_H__
 
 #include <gtk/gtk.h>
-
 #include <thunar/thunar-job.h>
 
 G_BEGIN_DECLS;
@@ -30,21 +29,20 @@ G_BEGIN_DECLS;
 typedef struct _ThunarProgressDialogClass ThunarProgressDialogClass;
 typedef struct _ThunarProgressDialog      ThunarProgressDialog;
 
-#define THUNAR_TYPE_PROGRESS_DIALOG             (thunar_progress_dialog_get_type ())
-#define THUNAR_PROGRESS_DIALOG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialog))
-#define THUNAR_PROGRESS_DIALOG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialogClass))
-#define THUNAR_IS_PROGRESS_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_PROGRESS_DIALOG))
-#define THUNAR_IS_PROGRESS_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_PROGRESS_DIALOG))
-#define THUNAR_PROGRESS_DIALOG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialogClass))
-
-GType         thunar_progress_dialog_get_type      (void) G_GNUC_CONST;
+#define THUNAR_TYPE_PROGRESS_DIALOG            (thunar_progress_dialog_get_type ())
+#define THUNAR_PROGRESS_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialog))
+#define THUNAR_PROGRESS_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialogClass))
+#define THUNAR_IS_PROGRESS_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_PROGRESS_DIALOG))
+#define THUNAR_IS_PROGRESS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_PROGRESS_DIALOG))
+#define THUNAR_PROGRESS_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_PROGRESS_DIALOG, ThunarProgressDialogClass))
 
-GtkWidget    *thunar_progress_dialog_new           (void) G_GNUC_MALLOC;
-GtkWidget    *thunar_progress_dialog_new_with_job  (ThunarJob            *job) G_GNUC_MALLOC;
+GType     thunar_progress_dialog_get_type (void) G_GNUC_CONST;
 
-ThunarJob    *thunar_progress_dialog_get_job       (ThunarProgressDialog *dialog);
-void          thunar_progress_dialog_set_job       (ThunarProgressDialog *dialog,
-                                                    ThunarJob            *job);
+GtkWidget *thunar_progress_dialog_new     (void);
+void       thunar_progress_dialog_add_job (ThunarProgressDialog *dialog,
+                                           ThunarJob            *job,
+                                           const gchar          *icon_name,
+                                           const gchar          *title);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-progress-view.c b/thunar/thunar-progress-view.c
new file mode 100644
index 0000000..5a0f989
--- /dev/null
+++ b/thunar/thunar-progress-view.c
@@ -0,0 +1,618 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2009 Jannis Pohlmann <jannis 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 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
+
+#include <exo/exo.h>
+
+#include <thunar/thunar-dialogs.h>
+#include <thunar/thunar-gobject-extensions.h>
+#include <thunar/thunar-job.h>
+#include <thunar/thunar-pango-extensions.h>
+#include <thunar/thunar-private.h>
+#include <thunar/thunar-progress-view.h>
+
+
+
+enum
+{
+  PROP_0,
+  PROP_JOB,
+  PROP_ICON_NAME,
+  PROP_TITLE,
+};
+
+
+
+static void              thunar_progress_view_dispose      (GObject            *object);
+static void              thunar_progress_view_get_property (GObject            *object,
+                                                            guint               prop_id,
+                                                            GValue             *value,
+                                                            GParamSpec         *pspec);
+static void              thunar_progress_view_set_property (GObject            *object,
+                                                            guint               prop_id,
+                                                            const GValue       *value,
+                                                            GParamSpec         *pspec);
+static void              thunar_progress_view_cancel_job   (ThunarProgressView *view);
+static ThunarJobResponse thunar_progress_view_ask          (ThunarProgressView *view,
+                                                            const gchar        *message,
+                                                            ThunarJobResponse   choices,
+                                                            ThunarJob          *job);
+static ThunarJobResponse thunar_progress_view_ask_replace  (ThunarProgressView *view,
+                                                            ThunarFile         *src_file,
+                                                            ThunarFile         *dst_file,
+                                                            ThunarJob          *job);
+static void              thunar_progress_view_error        (ThunarProgressView *view,
+                                                            GError             *error,
+                                                            ExoJob             *job);
+static void              thunar_progress_view_finished     (ThunarProgressView *view,
+                                                            ExoJob             *job);
+static void              thunar_progress_view_info_message (ThunarProgressView *view,
+                                                            const gchar        *message,
+                                                            ExoJob             *job);
+static void              thunar_progress_view_percent      (ThunarProgressView *view,
+                                                            gdouble             percent,
+                                                            ExoJob             *job);
+
+
+
+struct _ThunarProgressViewClass
+{
+  GtkVBoxClass __parent__;
+};
+
+struct _ThunarProgressView
+{
+  GtkVBox  __parent__;
+
+  ThunarJob *job;
+
+  GTimeVal   start_time;
+  GTimeVal   last_update_time;
+
+  GtkWidget *progress_bar;
+  GtkWidget *progress_label;
+
+  gchar     *icon_name;
+  gchar     *title;
+};
+
+
+
+G_DEFINE_TYPE (ThunarProgressView, thunar_progress_view, GTK_TYPE_VBOX)
+
+
+
+static void
+thunar_progress_view_class_init (ThunarProgressViewClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->dispose = thunar_progress_view_dispose;
+  gobject_class->get_property = thunar_progress_view_get_property;
+  gobject_class->set_property = thunar_progress_view_set_property;
+
+  /**
+   * ThunarProgressView:job:
+   *
+   * The #ThunarJob, whose progress is displayed by this view, or 
+   * %NULL if no job is set.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_JOB,
+                                   g_param_spec_object ("job", "job", "job",
+                                                        THUNAR_TYPE_JOB,
+                                                        EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_NAME,
+                                   g_param_spec_string ("icon-name",
+                                                        "icon-name",
+                                                        "icon-name",
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TITLE,
+                                   g_param_spec_string ("title",
+                                                        "title",
+                                                        "title",
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  g_signal_new ("need-attention",
+                THUNAR_TYPE_PROGRESS_VIEW,
+                G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
+                0,
+                NULL,
+                NULL,
+                g_cclosure_marshal_VOID__VOID,
+                G_TYPE_NONE,
+                0);
+
+  g_signal_new ("finished",
+                THUNAR_TYPE_PROGRESS_VIEW,
+                G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
+                0,
+                NULL,
+                NULL,
+                g_cclosure_marshal_VOID__VOID,
+                G_TYPE_NONE,
+                0);
+}
+
+
+
+static void
+thunar_progress_view_init (ThunarProgressView *view)
+{
+  GtkWidget *image;
+  GtkWidget *label;
+  GtkWidget *button;
+  GtkWidget *vbox;
+  GtkWidget *vbox2;
+  GtkWidget *hbox;
+
+  /* remember the current time as start time */
+  g_get_current_time (&view->start_time);
+
+  vbox = gtk_vbox_new (FALSE, 6);
+  gtk_container_add (GTK_CONTAINER (view), vbox);
+  gtk_widget_show (vbox);
+
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
+
+  image = g_object_new (GTK_TYPE_IMAGE, "icon-size", GTK_ICON_SIZE_BUTTON, NULL);
+  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
+  gtk_widget_show (image);
+
+  vbox2 = gtk_vbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
+  gtk_widget_show (vbox2);
+
+  label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
+  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big_bold ());
+  gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, TRUE, 0);
+  gtk_widget_show (label);
+
+  view->progress_label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox2), view->progress_label, FALSE, TRUE, 0);
+  gtk_widget_show (view->progress_label);
+
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
+
+  view->progress_bar = g_object_new (GTK_TYPE_PROGRESS_BAR, "text", " ", NULL);
+  gtk_box_pack_start (GTK_BOX (hbox), view->progress_bar, TRUE, TRUE, 0);
+  gtk_widget_show (view->progress_bar);
+
+  button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (thunar_progress_view_cancel_job), view);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+  gtk_widget_show (button);
+  
+  /* connect the view icon name to the action image */
+  exo_binding_new (G_OBJECT (view), "icon-name", G_OBJECT (image), "icon-name");
+
+  /* connect the view title to the action label */
+  exo_binding_new (G_OBJECT (view), "title", G_OBJECT (label), "label");
+}
+
+
+
+static void
+thunar_progress_view_dispose (GObject *object)
+{
+  ThunarProgressView *view = THUNAR_PROGRESS_VIEW (object);
+
+  /* disconnect from the job (if any) */
+  if (view->job != NULL)
+    {
+      exo_job_cancel (EXO_JOB (view->job));
+      thunar_progress_view_set_job (view, NULL);
+    }
+
+  (*G_OBJECT_CLASS (thunar_progress_view_parent_class)->dispose) (object);
+}
+
+
+
+static void
+thunar_progress_view_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  ThunarProgressView *view = THUNAR_PROGRESS_VIEW (object);
+
+  switch (prop_id)
+    {
+    case PROP_JOB:
+      g_value_set_object (value, thunar_progress_view_get_job (view));
+      break;
+
+    case PROP_ICON_NAME:
+      g_value_set_string (value, view->icon_name);
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, view->title);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+thunar_progress_view_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  ThunarProgressView *view = THUNAR_PROGRESS_VIEW (object);
+
+  switch (prop_id)
+    {
+    case PROP_JOB:
+      thunar_progress_view_set_job (view, g_value_get_object (value));
+      break;
+
+    case PROP_ICON_NAME:
+      thunar_progress_view_set_icon_name (view, g_value_get_string (value));
+      break;
+
+    case PROP_TITLE:
+      thunar_progress_view_set_title (view, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+thunar_progress_view_cancel_job (ThunarProgressView *view)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (THUNAR_IS_JOB (view->job));
+
+  if (view->job != NULL)
+    exo_job_cancel (EXO_JOB (view->job));
+}
+
+
+
+static ThunarJobResponse
+thunar_progress_view_ask (ThunarProgressView *view,
+                          const gchar        *message,
+                          ThunarJobResponse   choices,
+                          ThunarJob          *job)
+{
+  GtkWidget *window;
+
+  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_VIEW (view), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (view->job == job, THUNAR_JOB_RESPONSE_CANCEL);
+
+  /* be sure to display the corresponding dialog prior to opening the question view */
+  g_signal_emit_by_name (view, "need-attention");
+
+  /* determine the toplevel window of the view */
+  window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+
+  /* display the question view */
+  return thunar_dialogs_show_job_ask (window != NULL ? GTK_WINDOW (window) : NULL, 
+                                      message, choices);
+}
+
+
+
+static ThunarJobResponse
+thunar_progress_view_ask_replace (ThunarProgressView *view,
+                                  ThunarFile         *src_file,
+                                  ThunarFile         *dst_file,
+                                  ThunarJob          *job)
+{
+  GtkWidget *window;
+
+  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_VIEW (view), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (view->job == job, THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL);
+
+  /* be sure to display the corresponding dialog prior to opening the question view */
+  g_signal_emit_by_name (view, "need-attention");
+
+  /* determine the toplevel window of the view */
+  window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+
+  /* display the question view */
+  return thunar_dialogs_show_job_ask_replace (window != NULL ? GTK_WINDOW (window) : NULL, 
+                                              src_file, dst_file);
+}
+
+
+
+static void
+thunar_progress_view_error (ThunarProgressView *view,
+                            GError             *error,
+                            ExoJob             *job)
+{
+  GtkWidget *window;
+
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (error != NULL && error->message != NULL);
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  _thunar_return_if_fail (view->job == THUNAR_JOB (job));
+
+  /* be sure to display the corresponding dialog prior to opening the question view */
+  g_signal_emit_by_name (view, "need-attention");
+
+  /* determine the toplevel window of the view */
+  window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+
+  /* display the error message */
+  thunar_dialogs_show_job_error (window != NULL ? GTK_WINDOW (window) : NULL, error);
+}
+
+
+
+static void
+thunar_progress_view_finished (ThunarProgressView *view,
+                               ExoJob             *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  _thunar_return_if_fail (view->job == THUNAR_JOB (job));
+
+  /* emit finished signal to notify others that the job is finished */
+  g_signal_emit_by_name (view, "finished");
+}
+
+
+
+static void
+thunar_progress_view_info_message (ThunarProgressView *view,
+                                   const gchar        *message,
+                                   ExoJob             *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (g_utf8_validate (message, -1, NULL));
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  _thunar_return_if_fail (view->job == THUNAR_JOB (job));
+
+  gtk_label_set_text (GTK_LABEL (view->progress_label), message);
+}
+
+
+
+static inline guint64
+time_diff (const GTimeVal *now,
+           const GTimeVal *last)
+{
+  return ((guint64) now->tv_sec - last->tv_sec) * G_USEC_PER_SEC
+       + ((guint64) last->tv_usec - last->tv_usec);
+}
+
+
+
+static void
+thunar_progress_view_percent (ThunarProgressView *view,
+                              gdouble             percent,
+                              ExoJob             *job)
+{
+  GTimeVal current_time;
+  gulong   remaining_time;
+  gulong   elapsed_time;
+  gchar    text[512];
+
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (percent >= 0.0 && percent <= 100.0);
+  _thunar_return_if_fail (THUNAR_IS_JOB (job));
+  _thunar_return_if_fail (view->job == THUNAR_JOB (job));
+  
+  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (view->progress_bar), percent / 100.0);
+
+  /* check if we should update the time display (every 400ms) */
+  g_get_current_time (&current_time);
+  if (time_diff (&current_time, &view->last_update_time) > 400 * 1000)
+    {
+      /* calculate the remaining time (in seconds) */
+      elapsed_time = time_diff (&current_time, &view->start_time) / 1000;
+      remaining_time = ((100 * elapsed_time) / percent - elapsed_time) / 1000;
+
+      /* setup the time label */
+      if (G_LIKELY (remaining_time > 0))
+        {
+          /* format the time text */
+          if (remaining_time > 60 * 60)
+            {
+              remaining_time = (gulong) (remaining_time / (60 * 60));
+              g_snprintf (text, sizeof (text), ngettext ("(%lu hour remaining)", "(%lu hours remaining)", remaining_time), remaining_time);
+            }
+          else if (remaining_time > 60)
+            {
+              remaining_time = (gulong) (remaining_time / 60);
+              g_snprintf (text, sizeof (text), ngettext ("(%lu minute remaining)", "(%lu minutes remaining)", remaining_time), remaining_time);
+            }
+          else
+            {
+              remaining_time = remaining_time;
+              g_snprintf (text, sizeof (text), ngettext ("(%lu second remaining)", "(%lu seconds remaining)", remaining_time), remaining_time);
+            }
+
+          /* apply the time text */
+          gtk_progress_bar_set_text (GTK_PROGRESS_BAR (view->progress_bar), text);
+        }
+      else
+        {
+          /* display an empty label */
+          gtk_progress_bar_set_text (GTK_PROGRESS_BAR (view->progress_bar), " ");
+        }
+
+      /* remember the current time as last update time */
+      view->last_update_time = current_time;
+    }
+}
+
+
+
+/**
+ * thunar_progress_view_new:
+ *
+ * Allocates a new #ThunarProgressView.
+ *
+ * Return value: the newly allocated #ThunarProgressView.
+ **/
+GtkWidget*
+thunar_progress_view_new (void)
+{
+  return thunar_progress_view_new_with_job (NULL);
+}
+
+
+
+/**
+ * thunar_progress_view_new_with_job:
+ * @job : a #ThunarJob or %NULL.
+ *
+ * Allocates a new #ThunarProgressView and associates it with the @job.
+ *
+ * Return value: the newly allocated #ThunarProgressView.
+ **/
+GtkWidget*
+thunar_progress_view_new_with_job (ThunarJob *job)
+{
+  _thunar_return_val_if_fail (job == NULL || THUNAR_IS_JOB (job), NULL);
+  return g_object_new (THUNAR_TYPE_PROGRESS_VIEW, "job", job, NULL);
+}
+
+
+
+/**
+ * thunar_progress_view_get_job:
+ * @view : a #ThunarProgressView.
+ *
+ * Returns the #ThunarJob associated with @view
+ * or %NULL if no job is currently associated with @view.
+ *
+ * Return value: the job associated with @view or %NULL.
+ **/
+ThunarJob *
+thunar_progress_view_get_job (ThunarProgressView *view)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_VIEW (view), NULL);
+  return view->job;
+}
+
+
+
+/**
+ * thunar_progress_view_set_job:
+ * @view : a #ThunarProgressView.
+ * @job    : a #ThunarJob or %NULL.
+ *
+ * Associates @job with @view.
+ **/
+void
+thunar_progress_view_set_job (ThunarProgressView *view,
+                              ThunarJob          *job)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+  _thunar_return_if_fail (job == NULL || THUNAR_IS_JOB (job));
+
+  /* check if we're already on that job */
+  if (G_UNLIKELY (view->job == job))
+    return;
+
+  /* disconnect from the previous job */
+  if (G_LIKELY (view->job != NULL))
+    {
+      g_signal_handlers_disconnect_matched (view->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
+      g_object_unref (G_OBJECT (view->job));
+    }
+
+  /* activate the new job */
+  view->job = job;
+
+  /* connect to the new job */
+  if (G_LIKELY (job != NULL))
+    {
+      g_object_ref (job);
+
+      g_signal_connect_swapped (job, "ask", G_CALLBACK (thunar_progress_view_ask), view);
+      g_signal_connect_swapped (job, "ask-replace", G_CALLBACK (thunar_progress_view_ask_replace), view);
+      g_signal_connect_swapped (job, "error", G_CALLBACK (thunar_progress_view_error), view);
+      g_signal_connect_swapped (job, "finished", G_CALLBACK (thunar_progress_view_finished), view);
+      g_signal_connect_swapped (job, "info-message", G_CALLBACK (thunar_progress_view_info_message), view);
+      g_signal_connect_swapped (job, "percent", G_CALLBACK (thunar_progress_view_percent), view);
+    }
+
+  g_object_notify (G_OBJECT (view), "job");
+}
+
+
+
+void
+thunar_progress_view_set_icon_name (ThunarProgressView *view,
+                                    const gchar        *icon_name)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+
+  if (exo_str_is_equal (view->icon_name, icon_name))
+    return;
+
+  g_free (view->icon_name);
+  view->icon_name = g_strdup (icon_name);
+
+  g_object_notify (G_OBJECT (view), "icon-name");
+}
+
+
+
+void
+thunar_progress_view_set_title (ThunarProgressView *view,
+                                const gchar        *title)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
+
+  if (exo_str_is_equal (view->title, title))
+    return;
+
+  g_free (view->title);
+  view->title = g_strdup (title);
+
+  g_object_notify (G_OBJECT (view), "title");
+}
diff --git a/thunar/thunar-progress-view.h b/thunar/thunar-progress-view.h
new file mode 100644
index 0000000..096a44c
--- /dev/null
+++ b/thunar/thunar-progress-view.h
@@ -0,0 +1,55 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2009 Jannis Pohlmann <jannis 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 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 __THUNAR_PROGRESS_VIEW_H__
+#define __THUNAR_PROGRESS_VIEW_H__
+
+#include <gtk/gtk.h>
+
+#include <thunar/thunar-job.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _ThunarProgressViewClass ThunarProgressViewClass;
+typedef struct _ThunarProgressView      ThunarProgressView;
+
+#define THUNAR_TYPE_PROGRESS_VIEW            (thunar_progress_view_get_type ())
+#define THUNAR_PROGRESS_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_PROGRESS_VIEW, ThunarProgressView))
+#define THUNAR_PROGRESS_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_PROGRESS_VIEW, ThunarProgressViewClass))
+#define THUNAR_IS_PROGRESS_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_PROGRESS_VIEW))
+#define THUNAR_IS_PROGRESS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_PROGRESS_VIEW))
+#define THUNAR_PROGRESS_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_PROGRESS_VIEW, ThunarProgressViewClass))
+
+GType      thunar_progress_view_get_type      (void) G_GNUC_CONST;
+
+GtkWidget *thunar_progress_view_new           (void) G_GNUC_MALLOC;
+GtkWidget *thunar_progress_view_new_with_job  (ThunarJob          *job) G_GNUC_MALLOC;
+
+ThunarJob *thunar_progress_view_get_job       (ThunarProgressView *view);
+void       thunar_progress_view_set_job       (ThunarProgressView *view,
+                                               ThunarJob          *job);
+void       thunar_progress_view_set_icon_name (ThunarProgressView *view,
+                                               const gchar        *icon_name);
+void       thunar_progress_view_set_title     (ThunarProgressView *view,
+                                               const gchar        *title);
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_PROGRESS_VIEW_H__ */



More information about the Xfce4-commits mailing list